fumadocs-typescript 5.0.0 → 5.1.0
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/dist/base-Dvhn4vZx.d.ts +114 -0
- package/dist/index.d.ts +40 -32
- package/dist/index.js +296 -412
- package/dist/parse-tags-B09hzgIX.js +68 -0
- package/dist/ui/index.d.ts +26 -15
- package/dist/ui/index.js +44 -82
- package/package.json +28 -26
- package/dist/base-C72MF-7Q.d.ts +0 -110
- package/dist/chunk-H4DZJVYN.js +0 -142
package/dist/index.js
CHANGED
|
@@ -1,438 +1,322 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "
|
|
10
|
-
|
|
11
|
-
// src/lib/base.ts
|
|
12
|
-
import {
|
|
13
|
-
Project as Project2,
|
|
14
|
-
ts as ts2
|
|
15
|
-
} from "ts-morph";
|
|
1
|
+
import { n as markdownRenderer, t as parseTags } from "./parse-tags-B09hzgIX.js";
|
|
2
|
+
import * as ts$1 from "ts-morph";
|
|
3
|
+
import { Project, ts } from "ts-morph";
|
|
4
|
+
import * as fs$1 from "node:fs/promises";
|
|
5
|
+
import fs from "node:fs/promises";
|
|
6
|
+
import path, { join } from "node:path";
|
|
7
|
+
import { valueToEstree } from "estree-util-value-to-estree";
|
|
8
|
+
import { visit } from "unist-util-visit";
|
|
9
|
+
import { toEstree } from "hast-util-to-estree";
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
16
11
|
|
|
17
|
-
|
|
18
|
-
import { Project } from "ts-morph";
|
|
12
|
+
//#region src/create-project.ts
|
|
19
13
|
function createProject(options = {}) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
});
|
|
14
|
+
return new Project({
|
|
15
|
+
tsConfigFilePath: options.tsconfigPath ?? "./tsconfig.json",
|
|
16
|
+
skipAddingFilesFromTsConfig: true
|
|
17
|
+
});
|
|
25
18
|
}
|
|
26
19
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
} else if (type) {
|
|
46
|
-
typeName != null ? typeName : typeName = "$Fumadocs";
|
|
47
|
-
content += `
|
|
48
|
-
export type ${typeName} = ${type}`;
|
|
49
|
-
}
|
|
50
|
-
const output = yield gen.generateDocumentation(
|
|
51
|
-
{ path: file != null ? file : "temp.ts", content },
|
|
52
|
-
typeName,
|
|
53
|
-
options
|
|
54
|
-
);
|
|
55
|
-
if (name && output.length === 0)
|
|
56
|
-
throw new Error(`${name} in ${file != null ? file : "empty file"} doesn't exist`);
|
|
57
|
-
return output;
|
|
58
|
-
});
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/lib/type-table.ts
|
|
22
|
+
async function getTypeTableOutput(gen, { name, type, ...props }, options) {
|
|
23
|
+
const file = props.path && options?.basePath ? join(options.basePath, props.path) : props.path;
|
|
24
|
+
let typeName = name;
|
|
25
|
+
let content = "";
|
|
26
|
+
if (file) content = (await fs$1.readFile(file)).toString();
|
|
27
|
+
if (type && type.split("\n").length > 1) content += `\n${type}`;
|
|
28
|
+
else if (type) {
|
|
29
|
+
typeName ??= "$Fumadocs";
|
|
30
|
+
content += `\nexport type ${typeName} = ${type}`;
|
|
31
|
+
}
|
|
32
|
+
const output = await gen.generateDocumentation({
|
|
33
|
+
path: file ?? "temp.ts",
|
|
34
|
+
content
|
|
35
|
+
}, typeName, options);
|
|
36
|
+
if (name && output.length === 0) throw new Error(`${name} in ${file ?? "empty file"} doesn't exist`);
|
|
37
|
+
return output;
|
|
59
38
|
}
|
|
60
39
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// src/lib/get-simple-form.ts
|
|
65
|
-
import * as ts from "ts-morph";
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/lib/get-simple-form.ts
|
|
66
42
|
function getSimpleForm(type, checker, noUndefined = false, location) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return `[${elements}]`;
|
|
96
|
-
}
|
|
97
|
-
if (type.isArray() || type.isReadonlyArray()) {
|
|
98
|
-
return "array";
|
|
99
|
-
}
|
|
100
|
-
if (type.getCallSignatures().length > 0) {
|
|
101
|
-
return "function";
|
|
102
|
-
}
|
|
103
|
-
if (type.isClassOrInterface() || type.isObject()) {
|
|
104
|
-
return "object";
|
|
105
|
-
}
|
|
106
|
-
return type.getText(
|
|
107
|
-
location,
|
|
108
|
-
ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope
|
|
109
|
-
);
|
|
43
|
+
if (type.isUndefined() && noUndefined) return "";
|
|
44
|
+
const alias = type.getAliasSymbol();
|
|
45
|
+
if (alias) {
|
|
46
|
+
const args = type.getAliasTypeArguments();
|
|
47
|
+
if (args.length === 0) return alias.getName();
|
|
48
|
+
return `${alias.getName()}<${args.map((arg) => getSimpleForm(arg, checker)).join(", ")}>`;
|
|
49
|
+
}
|
|
50
|
+
if (type.isUnion()) {
|
|
51
|
+
const types = [];
|
|
52
|
+
for (const t of type.getUnionTypes()) {
|
|
53
|
+
const str = getSimpleForm(t, checker, noUndefined);
|
|
54
|
+
if (str.length > 0 && str !== "never") types.unshift(str);
|
|
55
|
+
}
|
|
56
|
+
return types.length > 0 ? dedupe(types).join(" | ").replace("true | false", "boolean") : "never";
|
|
57
|
+
}
|
|
58
|
+
if (type.isIntersection()) {
|
|
59
|
+
const types = [];
|
|
60
|
+
for (const t of type.getIntersectionTypes()) {
|
|
61
|
+
const str = getSimpleForm(t, checker, noUndefined);
|
|
62
|
+
if (str.length > 0 && str !== "never") types.unshift(str);
|
|
63
|
+
}
|
|
64
|
+
return dedupe(types).join(" & ");
|
|
65
|
+
}
|
|
66
|
+
if (type.isTuple()) return `[${type.getTupleElements().map((t) => getSimpleForm(t, checker)).join(", ")}]`;
|
|
67
|
+
if (type.isArray() || type.isReadonlyArray()) return "array";
|
|
68
|
+
if (type.getCallSignatures().length > 0) return "function";
|
|
69
|
+
if (type.isClassOrInterface() || type.isObject()) return "object";
|
|
70
|
+
return type.getText(location, ts$1.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
|
|
110
71
|
}
|
|
111
72
|
function dedupe(arr) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
return out;
|
|
73
|
+
const dedupe$1 = /* @__PURE__ */ new Set();
|
|
74
|
+
const out = [];
|
|
75
|
+
for (const item of arr) if (!dedupe$1.has(item)) {
|
|
76
|
+
out.push(item);
|
|
77
|
+
dedupe$1.add(item);
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
121
80
|
}
|
|
122
81
|
|
|
123
|
-
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/lib/base.ts
|
|
124
84
|
function createGenerator(config) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
);
|
|
155
|
-
out.push(generate(getProject(), k, d[0], options2));
|
|
156
|
-
}
|
|
157
|
-
void (cache == null ? void 0 : cache.write(cacheKey, out));
|
|
158
|
-
return out;
|
|
159
|
-
});
|
|
160
|
-
},
|
|
161
|
-
generateTypeTable(props, options2) {
|
|
162
|
-
return getTypeTableOutput(this, props, options2);
|
|
163
|
-
}
|
|
164
|
-
};
|
|
85
|
+
const options = config instanceof Project ? { project: config } : config;
|
|
86
|
+
const cache = options?.cache ? options.cache : null;
|
|
87
|
+
let instance;
|
|
88
|
+
function getProject() {
|
|
89
|
+
instance ??= options?.project ?? createProject(options);
|
|
90
|
+
return instance;
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
async generateDocumentation(file, name, options$1) {
|
|
94
|
+
const content = file.content ?? (await fs.readFile(path.resolve(file.path))).toString();
|
|
95
|
+
const cacheKey = `${file.path}:${name}:${content}`;
|
|
96
|
+
if (cache) {
|
|
97
|
+
const cached = await cache.read(cacheKey);
|
|
98
|
+
if (cached) return cached;
|
|
99
|
+
}
|
|
100
|
+
const sourceFile = getProject().createSourceFile(file.path, content, { overwrite: true });
|
|
101
|
+
const out = [];
|
|
102
|
+
for (const [k, d] of sourceFile.getExportedDeclarations()) {
|
|
103
|
+
if (name && name !== k) continue;
|
|
104
|
+
if (d.length > 1) console.warn(`export ${k} should not have more than one type declaration.`);
|
|
105
|
+
out.push(generate(getProject(), k, d[0], options$1));
|
|
106
|
+
}
|
|
107
|
+
cache?.write(cacheKey, out);
|
|
108
|
+
return out;
|
|
109
|
+
},
|
|
110
|
+
generateTypeTable(props, options$1) {
|
|
111
|
+
return getTypeTableOutput(this, props, options$1);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
165
114
|
}
|
|
166
115
|
function generate(program, name, declaration, { allowInternal = false, transform } = {}) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
description: comment ? ts2.displayPartsToString(comment) : "",
|
|
180
|
-
entries: declaration.getType().getProperties().map((prop) => getDocEntry(prop, entryContext)).filter(
|
|
181
|
-
(entry) => entry && (allowInternal || !("internal" in entry.tags))
|
|
182
|
-
)
|
|
183
|
-
};
|
|
116
|
+
const entryContext = {
|
|
117
|
+
transform,
|
|
118
|
+
program,
|
|
119
|
+
type: declaration.getType(),
|
|
120
|
+
declaration
|
|
121
|
+
};
|
|
122
|
+
const comment = declaration.getSymbol()?.compilerSymbol.getDocumentationComment(program.getTypeChecker().compilerObject);
|
|
123
|
+
return {
|
|
124
|
+
name,
|
|
125
|
+
description: comment ? ts.displayPartsToString(comment) : "",
|
|
126
|
+
entries: declaration.getType().getProperties().map((prop) => getDocEntry(prop, entryContext)).filter((entry) => entry && (allowInternal || !("internal" in entry.tags)))
|
|
127
|
+
};
|
|
184
128
|
}
|
|
185
129
|
function getDocEntry(prop, context) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
const entry = {
|
|
221
|
-
name: prop.getName(),
|
|
222
|
-
description: ts2.displayPartsToString(
|
|
223
|
-
prop.compilerSymbol.getDocumentationComment(
|
|
224
|
-
program.getTypeChecker().compilerObject
|
|
225
|
-
)
|
|
226
|
-
),
|
|
227
|
-
tags,
|
|
228
|
-
type,
|
|
229
|
-
simplifiedType,
|
|
230
|
-
required: !isOptional,
|
|
231
|
-
deprecated: tags.some((tag) => tag.name === "deprecated")
|
|
232
|
-
};
|
|
233
|
-
transform == null ? void 0 : transform.call(context, entry, subType, prop);
|
|
234
|
-
return entry;
|
|
130
|
+
const { transform, program } = context;
|
|
131
|
+
if (context.type.isClass() && prop.getName().startsWith("#")) return;
|
|
132
|
+
const subType = prop.getTypeAtLocation(context.declaration);
|
|
133
|
+
const isOptional = prop.isOptional();
|
|
134
|
+
const tags = prop.getJsDocTags().map((tag) => ({
|
|
135
|
+
name: tag.getName(),
|
|
136
|
+
text: ts.displayPartsToString(tag.getText())
|
|
137
|
+
}));
|
|
138
|
+
let type = subType.getText(context.declaration, ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | ts.TypeFormatFlags.NoTruncation);
|
|
139
|
+
let simplifiedType = getSimpleForm(subType, program.getTypeChecker(), isOptional, context.declaration);
|
|
140
|
+
for (const tag of tags) {
|
|
141
|
+
if (tag.name === "fumadocsType") {
|
|
142
|
+
const match = /`(?<name>.+)`$/.exec(tag.text)?.[1];
|
|
143
|
+
if (match) type = match;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (tag.name === "remarks") {
|
|
147
|
+
const match = /^`(?<name>.+)`/.exec(tag.text)?.[1];
|
|
148
|
+
if (match) simplifiedType = match;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const entry = {
|
|
152
|
+
name: prop.getName(),
|
|
153
|
+
description: ts.displayPartsToString(prop.compilerSymbol.getDocumentationComment(program.getTypeChecker().compilerObject)),
|
|
154
|
+
tags,
|
|
155
|
+
type,
|
|
156
|
+
simplifiedType,
|
|
157
|
+
required: !isOptional,
|
|
158
|
+
deprecated: tags.some((tag) => tag.name === "deprecated")
|
|
159
|
+
};
|
|
160
|
+
transform?.call(context, entry, subType, prop);
|
|
161
|
+
return entry;
|
|
235
162
|
}
|
|
236
163
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
import { visit } from "unist-util-visit";
|
|
240
|
-
import { toEstree } from "hast-util-to-estree";
|
|
164
|
+
//#endregion
|
|
165
|
+
//#region src/lib/remark-auto-type-table.ts
|
|
241
166
|
function objectBuilder() {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
};
|
|
167
|
+
const out = {
|
|
168
|
+
type: "ObjectExpression",
|
|
169
|
+
properties: []
|
|
170
|
+
};
|
|
171
|
+
return {
|
|
172
|
+
addExpressionNode(key, expression) {
|
|
173
|
+
out.properties.push({
|
|
174
|
+
type: "Property",
|
|
175
|
+
method: false,
|
|
176
|
+
shorthand: false,
|
|
177
|
+
computed: false,
|
|
178
|
+
key: {
|
|
179
|
+
type: "Identifier",
|
|
180
|
+
name: key
|
|
181
|
+
},
|
|
182
|
+
kind: "init",
|
|
183
|
+
value: expression
|
|
184
|
+
});
|
|
185
|
+
},
|
|
186
|
+
addJsxProperty(key, hast) {
|
|
187
|
+
const estree = toEstree(hast, { elementAttributeNameCase: "react" }).body[0];
|
|
188
|
+
this.addExpressionNode(key, estree.expression);
|
|
189
|
+
},
|
|
190
|
+
build() {
|
|
191
|
+
return out;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
271
194
|
}
|
|
272
|
-
function buildTypeProp(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
function onParam(param) {
|
|
304
|
-
return __async(this, null, function* () {
|
|
305
|
-
const node = objectBuilder();
|
|
306
|
-
node.addExpressionNode("name", valueToEstree(param.name));
|
|
307
|
-
if (param.description)
|
|
308
|
-
node.addJsxProperty(
|
|
309
|
-
"description",
|
|
310
|
-
yield renderMarkdown(param.description)
|
|
311
|
-
);
|
|
312
|
-
return node.build();
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
const prop = objectBuilder();
|
|
316
|
-
const output = yield Promise.all(
|
|
317
|
-
entries.map((entry) => __async(null, null, function* () {
|
|
318
|
-
return {
|
|
319
|
-
name: entry.name,
|
|
320
|
-
node: yield onItem(entry)
|
|
321
|
-
};
|
|
322
|
-
}))
|
|
323
|
-
);
|
|
324
|
-
for (const node of output) {
|
|
325
|
-
prop.addExpressionNode(node.name, node.node);
|
|
326
|
-
}
|
|
327
|
-
return prop.build();
|
|
328
|
-
});
|
|
195
|
+
async function buildTypeProp(entries, renderer) {
|
|
196
|
+
async function onItem(entry) {
|
|
197
|
+
const node = objectBuilder();
|
|
198
|
+
const tags = parseTags(entry.tags);
|
|
199
|
+
node.addJsxProperty("type", await renderer.renderTypeToHast(entry.simplifiedType));
|
|
200
|
+
node.addJsxProperty("typeDescription", await renderer.renderTypeToHast(entry.type));
|
|
201
|
+
node.addExpressionNode("required", valueToEstree(entry.required));
|
|
202
|
+
if (tags.default) node.addJsxProperty("default", await renderer.renderTypeToHast(tags.default));
|
|
203
|
+
if (tags.returns) node.addJsxProperty("returns", await renderer.renderMarkdownToHast(tags.returns));
|
|
204
|
+
if (tags.params) node.addExpressionNode("parameters", {
|
|
205
|
+
type: "ArrayExpression",
|
|
206
|
+
elements: await Promise.all(tags.params.map(onParam))
|
|
207
|
+
});
|
|
208
|
+
if (entry.description) node.addJsxProperty("description", await renderer.renderMarkdownToHast(entry.description));
|
|
209
|
+
return node.build();
|
|
210
|
+
}
|
|
211
|
+
async function onParam(param) {
|
|
212
|
+
const node = objectBuilder();
|
|
213
|
+
node.addExpressionNode("name", valueToEstree(param.name));
|
|
214
|
+
if (param.description) node.addJsxProperty("description", await renderer.renderMarkdownToHast(param.description));
|
|
215
|
+
return node.build();
|
|
216
|
+
}
|
|
217
|
+
const prop = objectBuilder();
|
|
218
|
+
const output = await Promise.all(entries.map(async (entry) => ({
|
|
219
|
+
name: entry.name,
|
|
220
|
+
node: await onItem(entry)
|
|
221
|
+
})));
|
|
222
|
+
for (const node of output) prop.addExpressionNode(node.name, node.node);
|
|
223
|
+
return prop.build();
|
|
329
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* Compile `auto-type-table` into Fumadocs UI compatible TypeTable
|
|
227
|
+
*
|
|
228
|
+
* MDX is required to use this plugin.
|
|
229
|
+
*/
|
|
330
230
|
function remarkAutoTypeTable(config = {}) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
});
|
|
398
|
-
yield Promise.all(queue);
|
|
399
|
-
});
|
|
231
|
+
const { name = "auto-type-table", outputName = "TypeTable", options: generateOptions = {}, remarkStringify = true, generator = createGenerator(), renderMarkdown, renderType, shiki } = config;
|
|
232
|
+
let renderer;
|
|
233
|
+
if (renderMarkdown && renderType) renderer = {
|
|
234
|
+
renderMarkdownToHast: renderMarkdown,
|
|
235
|
+
renderTypeToHast: renderType
|
|
236
|
+
};
|
|
237
|
+
else {
|
|
238
|
+
renderer = markdownRenderer(shiki);
|
|
239
|
+
if (renderMarkdown) renderer.renderMarkdownToHast = renderMarkdown;
|
|
240
|
+
if (renderType) renderer.renderTypeToHast = renderType;
|
|
241
|
+
}
|
|
242
|
+
return async (tree, file) => {
|
|
243
|
+
const queue = [];
|
|
244
|
+
async function run(node, props) {
|
|
245
|
+
let basePath = props.cwd ? file.cwd : generateOptions.basePath;
|
|
246
|
+
if (file.dirname) basePath ??= file.dirname;
|
|
247
|
+
const rendered = (await generator.generateTypeTable(props, {
|
|
248
|
+
...generateOptions,
|
|
249
|
+
basePath
|
|
250
|
+
})).map(async (doc) => {
|
|
251
|
+
return {
|
|
252
|
+
type: "mdxJsxFlowElement",
|
|
253
|
+
name: outputName,
|
|
254
|
+
attributes: [{
|
|
255
|
+
type: "mdxJsxAttribute",
|
|
256
|
+
name: "type",
|
|
257
|
+
value: {
|
|
258
|
+
type: "mdxJsxAttributeValueExpression",
|
|
259
|
+
value: remarkStringify ? JSON.stringify(doc, null, 2) : "",
|
|
260
|
+
data: { estree: {
|
|
261
|
+
type: "Program",
|
|
262
|
+
sourceType: "module",
|
|
263
|
+
body: [{
|
|
264
|
+
type: "ExpressionStatement",
|
|
265
|
+
expression: await buildTypeProp(doc.entries, renderer)
|
|
266
|
+
}]
|
|
267
|
+
} }
|
|
268
|
+
}
|
|
269
|
+
}],
|
|
270
|
+
children: []
|
|
271
|
+
};
|
|
272
|
+
});
|
|
273
|
+
Object.assign(node, {
|
|
274
|
+
type: "root",
|
|
275
|
+
attributes: [],
|
|
276
|
+
children: await Promise.all(rendered)
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
visit(tree, "mdxJsxFlowElement", (node) => {
|
|
280
|
+
if (node.name !== name) return;
|
|
281
|
+
const props = {};
|
|
282
|
+
const onError = (message, cause) => {
|
|
283
|
+
const location = node.position ? `${file.path}:${node.position.start.line}:${node.position.start.column}` : file.path;
|
|
284
|
+
throw new Error(`${location} from <auto-type-table>: ${message}`, { cause });
|
|
285
|
+
};
|
|
286
|
+
for (const attr of node.attributes) if (attr.type !== "mdxJsxAttribute") onError("only named attributes are allowed.");
|
|
287
|
+
else if (typeof attr.value === "string") props[attr.name] = attr.value;
|
|
288
|
+
else if (attr.value === null) props[attr.name] = true;
|
|
289
|
+
else onError("only string & boolean attributes are allowed.");
|
|
290
|
+
queue.push(run(node, props).catch((err) => {
|
|
291
|
+
onError("failed to generate type table", err);
|
|
292
|
+
}));
|
|
293
|
+
return "skip";
|
|
294
|
+
});
|
|
295
|
+
await Promise.all(queue);
|
|
296
|
+
};
|
|
400
297
|
}
|
|
401
298
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
import { createHash } from "crypto";
|
|
405
|
-
import path2 from "path";
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region src/cache/fs-cache.ts
|
|
406
301
|
function createFileSystemGeneratorCache(dir) {
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
);
|
|
425
|
-
} catch (e) {
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
};
|
|
302
|
+
dir = path.resolve(dir);
|
|
303
|
+
const initDirPromise = fs.mkdir(dir, { recursive: true }).catch(() => {});
|
|
304
|
+
return {
|
|
305
|
+
async write(input, data) {
|
|
306
|
+
const hash = createHash("SHA256").update(input).digest("hex").slice(0, 12);
|
|
307
|
+
await initDirPromise;
|
|
308
|
+
await fs.writeFile(path.join(dir, `${hash}.json`), JSON.stringify(data));
|
|
309
|
+
},
|
|
310
|
+
async read(input) {
|
|
311
|
+
const hash = createHash("SHA256").update(input).digest("hex").slice(0, 12);
|
|
312
|
+
try {
|
|
313
|
+
return JSON.parse((await fs.readFile(path.join(dir, `${hash}.json`))).toString());
|
|
314
|
+
} catch {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
};
|
|
431
319
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
createProject,
|
|
436
|
-
remarkAutoTypeTable,
|
|
437
|
-
renderMarkdownToHast
|
|
438
|
-
};
|
|
320
|
+
|
|
321
|
+
//#endregion
|
|
322
|
+
export { createFileSystemGeneratorCache, createGenerator, createProject, remarkAutoTypeTable };
|