fumadocs-typescript 3.0.4 → 4.0.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.
@@ -0,0 +1,118 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
32
+ var __async = (__this, __arguments, generator) => {
33
+ return new Promise((resolve, reject) => {
34
+ var fulfilled = (value) => {
35
+ try {
36
+ step(generator.next(value));
37
+ } catch (e) {
38
+ reject(e);
39
+ }
40
+ };
41
+ var rejected = (value) => {
42
+ try {
43
+ step(generator.throw(value));
44
+ } catch (e) {
45
+ reject(e);
46
+ }
47
+ };
48
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
49
+ step((generator = generator.apply(__this, __arguments)).next());
50
+ });
51
+ };
52
+
53
+ // src/markdown.ts
54
+ import { remark } from "remark";
55
+ import {
56
+ remarkGfm,
57
+ rehypeCode
58
+ } from "fumadocs-core/mdx-plugins";
59
+ import remarkRehype from "remark-rehype";
60
+ var processor = remark().use(remarkGfm).use(remarkRehype).use(rehypeCode, {
61
+ lazy: true,
62
+ themes: {
63
+ light: "github-light",
64
+ dark: "github-dark"
65
+ }
66
+ }).use(() => {
67
+ return (tree, file) => {
68
+ file.data.tree = tree;
69
+ return "";
70
+ };
71
+ });
72
+ function renderMarkdownToHast(md) {
73
+ return __async(this, null, function* () {
74
+ md = md.replace(new RegExp("{@link (?<link>[^}]*)}", "g"), "$1");
75
+ const out = yield processor.process(md);
76
+ return out.data.tree;
77
+ });
78
+ }
79
+
80
+ // src/utils/type-table.ts
81
+ import * as fs from "node:fs/promises";
82
+ import { join } from "node:path";
83
+ function getTypeTableOutput(gen, _a, options) {
84
+ return __async(this, null, function* () {
85
+ var _b = _a, { name, type } = _b, props = __objRest(_b, ["name", "type"]);
86
+ const file = props.path && (options == null ? void 0 : options.basePath) ? join(options.basePath, props.path) : props.path;
87
+ let typeName = name;
88
+ let content = "";
89
+ if (file) {
90
+ content = (yield fs.readFile(file)).toString();
91
+ }
92
+ if (type && type.split("\n").length > 1) {
93
+ content += `
94
+ ${type}`;
95
+ } else if (type) {
96
+ typeName != null ? typeName : typeName = "$Fumadocs";
97
+ content += `
98
+ export type ${typeName} = ${type}`;
99
+ }
100
+ const output = gen.generateDocumentation(
101
+ { path: file != null ? file : "temp.ts", content },
102
+ typeName,
103
+ options
104
+ );
105
+ if (name && output.length === 0)
106
+ throw new Error(`${name} in ${file != null ? file : "empty file"} doesn't exist`);
107
+ return output;
108
+ });
109
+ }
110
+
111
+ export {
112
+ __spreadValues,
113
+ __spreadProps,
114
+ __objRest,
115
+ __async,
116
+ renderMarkdownToHast,
117
+ getTypeTableOutput
118
+ };
package/dist/index.d.ts CHANGED
@@ -1,21 +1,23 @@
1
- import { G as GenerateDocumentationOptions, a as GeneratedDoc, D as DocEntry } from './base-BaB_XiY6.js';
2
- export { b as GenerateOptions, d as generate, c as generateDocumentation, g as getProject } from './base-BaB_XiY6.js';
1
+ import { G as GenerateOptions, a as GeneratedDoc, D as DocEntry, b as Generator, c as GenerateTypeTableOptions } from './type-table-Duzly_SK.js';
2
+ export { d as createGenerator, e as generateDocumentation, g as getProject } from './type-table-Duzly_SK.js';
3
3
  import fg from 'fast-glob';
4
4
  import { Nodes } from 'hast';
5
+ import { Root } from 'mdast';
6
+ import { Transformer } from 'unified';
5
7
  import 'ts-morph';
6
8
 
7
9
  interface Templates {
8
10
  block: (doc: GeneratedDoc, children: string) => string;
9
11
  property: (entry: DocEntry) => string;
10
12
  }
11
- interface GenerateMDXOptions extends GenerateDocumentationOptions {
13
+ interface GenerateMDXOptions extends GenerateOptions {
12
14
  /**
13
15
  * a root directory to resolve relative file paths
14
16
  */
15
17
  basePath?: string;
16
18
  templates?: Partial<Templates>;
17
19
  }
18
- declare function generateMDX(source: string, { basePath, templates: overrides, ...rest }?: GenerateMDXOptions): string;
20
+ declare function generateMDX(generator: Generator, source: string, { basePath, templates: overrides, ...rest }?: GenerateMDXOptions): string;
19
21
 
20
22
  interface GenerateFilesOptions {
21
23
  input: string | string[];
@@ -30,8 +32,35 @@ interface GenerateFilesOptions {
30
32
  */
31
33
  transformOutput?: (path: string, content: string) => string;
32
34
  }
33
- declare function generateFiles(options: GenerateFilesOptions): Promise<void>;
35
+ declare function generateFiles(generator: Generator, options: GenerateFilesOptions): Promise<void>;
34
36
 
35
37
  declare function renderMarkdownToHast(md: string): Promise<Nodes>;
36
38
 
37
- export { DocEntry, GenerateDocumentationOptions, type GenerateFilesOptions, type GenerateMDXOptions, GeneratedDoc, generateFiles, generateMDX, renderMarkdownToHast };
39
+ interface RemarkAutoTypeTableOptions {
40
+ /**
41
+ * @defaultValue 'auto-type-table'
42
+ */
43
+ name?: string;
44
+ /**
45
+ * @defaultValue 'TypeTable'
46
+ */
47
+ outputName?: string;
48
+ renderMarkdown?: typeof renderMarkdownToHast;
49
+ /**
50
+ * Customise type table generation
51
+ */
52
+ options?: GenerateTypeTableOptions;
53
+ /**
54
+ * generate required `value` property for `remark-stringify`
55
+ */
56
+ remarkStringify?: boolean;
57
+ generator?: Generator;
58
+ }
59
+ /**
60
+ * Compile `auto-type-table` into Fumadocs UI compatible TypeTable
61
+ *
62
+ * MDX is required to use this plugin.
63
+ */
64
+ declare function remarkAutoTypeTable({ name, outputName, renderMarkdown, options, remarkStringify, generator, }?: RemarkAutoTypeTableOptions): Transformer<Root, Root>;
65
+
66
+ export { DocEntry, type GenerateFilesOptions, type GenerateMDXOptions, GenerateOptions, GeneratedDoc, Generator, type RemarkAutoTypeTableOptions, generateFiles, generateMDX, remarkAutoTypeTable, renderMarkdownToHast };
package/dist/index.js CHANGED
@@ -3,15 +3,111 @@ import {
3
3
  __objRest,
4
4
  __spreadProps,
5
5
  __spreadValues,
6
- generate,
7
- generateDocumentation,
8
- getProject,
6
+ getTypeTableOutput,
9
7
  renderMarkdownToHast
10
- } from "./chunk-PRWE5YDY.js";
8
+ } from "./chunk-2WGVCLFC.js";
11
9
 
12
- // src/generate/mdx.ts
13
- import * as path from "node:path";
10
+ // src/lib/base.ts
11
+ import {
12
+ Project as Project2,
13
+ ts
14
+ } from "ts-morph";
15
+
16
+ // src/get-project.ts
17
+ import { Project } from "ts-morph";
18
+ function getProject(options = {}) {
19
+ var _a;
20
+ return new Project({
21
+ tsConfigFilePath: (_a = options.tsconfigPath) != null ? _a : "./tsconfig.json",
22
+ skipAddingFilesFromTsConfig: true
23
+ });
24
+ }
25
+
26
+ // src/lib/base.ts
14
27
  import fs from "node:fs";
28
+ function createGenerator(config) {
29
+ const project = config instanceof Project2 ? config : getProject(config);
30
+ return {
31
+ generateDocumentation(file, name, options = {}) {
32
+ var _a;
33
+ const sourceFile = project.createSourceFile(
34
+ file.path,
35
+ (_a = file.content) != null ? _a : fs.readFileSync(file.path).toString(),
36
+ {
37
+ overwrite: true
38
+ }
39
+ );
40
+ const out = [];
41
+ for (const [k, d] of sourceFile.getExportedDeclarations()) {
42
+ if (name && name !== k) continue;
43
+ if (d.length > 1)
44
+ console.warn(
45
+ `export ${k} should not have more than one type declaration.`
46
+ );
47
+ out.push(generate(project, k, d[0], options));
48
+ }
49
+ return out;
50
+ }
51
+ };
52
+ }
53
+ function generateDocumentation(file, name, content, options = {}) {
54
+ var _a;
55
+ const gen = createGenerator((_a = options.project) != null ? _a : options.config);
56
+ return gen.generateDocumentation({ path: file, content }, name, options);
57
+ }
58
+ function generate(program, name, declaration, { allowInternal = false, transform }) {
59
+ var _a;
60
+ const entryContext = {
61
+ transform,
62
+ program,
63
+ type: declaration.getType(),
64
+ declaration
65
+ };
66
+ const comment = (_a = declaration.getSymbol()) == null ? void 0 : _a.compilerSymbol.getDocumentationComment(
67
+ program.getTypeChecker().compilerObject
68
+ );
69
+ return {
70
+ name,
71
+ description: comment ? ts.displayPartsToString(comment) : "",
72
+ entries: declaration.getType().getProperties().map((prop) => getDocEntry(prop, entryContext)).filter(
73
+ (entry) => entry && (allowInternal || !("internal" in entry.tags))
74
+ )
75
+ };
76
+ }
77
+ function getDocEntry(prop, context) {
78
+ var _a, _b, _c, _d;
79
+ const { transform, program } = context;
80
+ if (context.type.isClass() && prop.getName().startsWith("#")) {
81
+ return;
82
+ }
83
+ const subType = program.getTypeChecker().getTypeOfSymbolAtLocation(prop, context.declaration);
84
+ const tags = Object.fromEntries(
85
+ prop.getJsDocTags().map((tag) => [tag.getName(), ts.displayPartsToString(tag.getText())])
86
+ );
87
+ let typeName = subType.getNonNullableType().getText(void 0, ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
88
+ if (subType.getAliasSymbol() && subType.getAliasTypeArguments().length === 0) {
89
+ typeName = (_b = (_a = subType.getAliasSymbol()) == null ? void 0 : _a.getEscapedName()) != null ? _b : typeName;
90
+ }
91
+ if ("remarks" in tags) {
92
+ typeName = (_d = (_c = new RegExp("^`(?<name>.+)`").exec(tags.remarks)) == null ? void 0 : _c[1]) != null ? _d : typeName;
93
+ }
94
+ const entry = {
95
+ name: prop.getName(),
96
+ description: ts.displayPartsToString(
97
+ prop.compilerSymbol.getDocumentationComment(
98
+ program.getTypeChecker().compilerObject
99
+ )
100
+ ),
101
+ tags,
102
+ type: typeName,
103
+ required: !prop.isOptional()
104
+ };
105
+ transform == null ? void 0 : transform.call(context, entry, subType, prop);
106
+ return entry;
107
+ }
108
+
109
+ // src/lib/mdx.ts
110
+ import * as path from "node:path";
15
111
  var regex = new RegExp("^---type-table---\\r?\\n(?<file>.+?)(?:#(?<name>.+))?\\r?\\n---end---$", "gm");
16
112
  var defaultTemplates = {
17
113
  block: (doc, c) => `### ${doc.name}
@@ -33,18 +129,17 @@ ${replaceJsDocLinks(value)}`).join("\n")}
33
129
 
34
130
  </div>`
35
131
  };
36
- function generateMDX(source, _a = {}) {
132
+ function generateMDX(generator, source, _a = {}) {
37
133
  var _b = _a, { basePath = "./", templates: overrides } = _b, rest = __objRest(_b, ["basePath", "templates"]);
38
- var _a2;
39
134
  const templates = __spreadValues(__spreadValues({}, defaultTemplates), overrides);
40
- const project = (_a2 = rest.project) != null ? _a2 : getProject(rest.config);
41
135
  return source.replace(regex, (...args) => {
42
136
  const groups = args[args.length - 1];
43
137
  const file = path.resolve(basePath, groups.file);
44
- const content = fs.readFileSync(file);
45
- const docs = generateDocumentation(file, groups.name, content.toString(), __spreadProps(__spreadValues({}, rest), {
46
- project
47
- }));
138
+ const docs = generator.generateDocumentation(
139
+ { path: file },
140
+ groups.name,
141
+ rest
142
+ );
48
143
  return docs.map(
49
144
  (doc) => templates.block(doc, doc.entries.map(templates.property).join("\n"))
50
145
  ).join("\n\n");
@@ -54,15 +149,13 @@ function replaceJsDocLinks(md) {
54
149
  return md.replace(new RegExp("{@link (?<link>[^}]*)}", "g"), "$1");
55
150
  }
56
151
 
57
- // src/generate/file.ts
152
+ // src/lib/file.ts
58
153
  import * as path2 from "node:path";
59
154
  import { mkdir, writeFile, readFile } from "node:fs/promises";
60
155
  import fg from "fast-glob";
61
- function generateFiles(options) {
156
+ function generateFiles(generator, options) {
62
157
  return __async(this, null, function* () {
63
- var _a, _b, _c;
64
158
  const files = yield fg(options.input, options.globOptions);
65
- const project = (_c = (_a = options.options) == null ? void 0 : _a.project) != null ? _c : getProject((_b = options.options) == null ? void 0 : _b.config);
66
159
  const produce = files.map((file) => __async(this, null, function* () {
67
160
  const absolutePath = path2.resolve(file);
68
161
  const outputPath = typeof options.output === "function" ? options.output(file) : path2.resolve(
@@ -70,11 +163,9 @@ function generateFiles(options) {
70
163
  `${path2.basename(file, path2.extname(file))}.mdx`
71
164
  );
72
165
  const content = (yield readFile(absolutePath)).toString();
73
- let result = generateMDX(content, __spreadProps(__spreadValues({
166
+ let result = generateMDX(generator, content, __spreadValues({
74
167
  basePath: path2.dirname(absolutePath)
75
- }, options.options), {
76
- project
77
- }));
168
+ }, options.options));
78
169
  if (options.transformOutput) {
79
170
  result = options.transformOutput(outputPath, result);
80
171
  }
@@ -90,11 +181,134 @@ function write(file, content) {
90
181
  yield writeFile(file, content);
91
182
  });
92
183
  }
184
+
185
+ // src/lib/remark-auto-type-table.tsx
186
+ import { valueToEstree } from "estree-util-value-to-estree";
187
+ import { visit } from "unist-util-visit";
188
+ import { toEstree } from "hast-util-to-estree";
189
+ import { dirname as dirname2 } from "node:path";
190
+ function mapProperty(entry, renderMarkdown) {
191
+ return __async(this, null, function* () {
192
+ const value = valueToEstree({
193
+ type: entry.type,
194
+ default: entry.tags.default || entry.tags.defaultValue
195
+ });
196
+ if (entry.description) {
197
+ const hast = toEstree(yield renderMarkdown(entry.description), {
198
+ elementAttributeNameCase: "react"
199
+ }).body[0];
200
+ value.properties.push({
201
+ type: "Property",
202
+ method: false,
203
+ shorthand: false,
204
+ computed: false,
205
+ key: {
206
+ type: "Identifier",
207
+ name: "description"
208
+ },
209
+ kind: "init",
210
+ value: hast.expression
211
+ });
212
+ }
213
+ return {
214
+ type: "Property",
215
+ method: false,
216
+ shorthand: false,
217
+ computed: false,
218
+ key: {
219
+ type: "Identifier",
220
+ name: entry.name
221
+ },
222
+ kind: "init",
223
+ value
224
+ };
225
+ });
226
+ }
227
+ function remarkAutoTypeTable({
228
+ name = "auto-type-table",
229
+ outputName = "TypeTable",
230
+ renderMarkdown = renderMarkdownToHast,
231
+ options = {},
232
+ remarkStringify = true,
233
+ generator = createGenerator()
234
+ } = {}) {
235
+ return (tree, file) => __async(this, null, function* () {
236
+ const queue = [];
237
+ let basePath = options == null ? void 0 : options.basePath;
238
+ if (!basePath && file.path) basePath = dirname2(file.path);
239
+ visit(tree, "mdxJsxFlowElement", (node) => {
240
+ if (node.name !== name) return;
241
+ const props = {};
242
+ for (const attr of node.attributes) {
243
+ if (attr.type !== "mdxJsxAttribute" || typeof attr.value !== "string")
244
+ throw new Error(
245
+ "`auto-type-table` does not support non-string attributes"
246
+ );
247
+ props[attr.name] = attr.value;
248
+ }
249
+ function run() {
250
+ return __async(this, null, function* () {
251
+ const output = yield getTypeTableOutput(
252
+ generator,
253
+ props,
254
+ __spreadProps(__spreadValues({}, options), {
255
+ basePath
256
+ })
257
+ );
258
+ const rendered = output.map((doc) => __async(this, null, function* () {
259
+ const properties = yield Promise.all(
260
+ doc.entries.map((entry) => mapProperty(entry, renderMarkdown))
261
+ );
262
+ return {
263
+ type: "mdxJsxFlowElement",
264
+ name: outputName,
265
+ attributes: [
266
+ {
267
+ type: "mdxJsxAttribute",
268
+ name: "type",
269
+ value: {
270
+ type: "mdxJsxAttributeValueExpression",
271
+ value: remarkStringify ? JSON.stringify(doc, null, 2) : "",
272
+ data: {
273
+ estree: {
274
+ type: "Program",
275
+ sourceType: "module",
276
+ body: [
277
+ {
278
+ type: "ExpressionStatement",
279
+ expression: {
280
+ type: "ObjectExpression",
281
+ properties
282
+ }
283
+ }
284
+ ]
285
+ }
286
+ }
287
+ }
288
+ }
289
+ ],
290
+ children: []
291
+ };
292
+ }));
293
+ Object.assign(node, {
294
+ type: "root",
295
+ attributes: [],
296
+ children: yield Promise.all(rendered)
297
+ });
298
+ });
299
+ }
300
+ queue.push(run());
301
+ return "skip";
302
+ });
303
+ yield Promise.all(queue);
304
+ });
305
+ }
93
306
  export {
94
- generate,
307
+ createGenerator,
95
308
  generateDocumentation,
96
309
  generateFiles,
97
310
  generateMDX,
98
311
  getProject,
312
+ remarkAutoTypeTable,
99
313
  renderMarkdownToHast
100
314
  };
@@ -0,0 +1,101 @@
1
+ import { Project, Type, ExportedDeclarations, Symbol } from 'ts-morph';
2
+
3
+ interface TypescriptConfig {
4
+ files?: string[];
5
+ tsconfigPath?: string;
6
+ /** A root directory to resolve relative path entries in the config file to. e.g. outDir */
7
+ basePath?: string;
8
+ }
9
+ declare function getProject(options?: TypescriptConfig): Project;
10
+
11
+ interface GeneratedDoc {
12
+ name: string;
13
+ description: string;
14
+ entries: DocEntry[];
15
+ }
16
+ interface DocEntry {
17
+ name: string;
18
+ description: string;
19
+ type: string;
20
+ tags: Record<string, string>;
21
+ required: boolean;
22
+ }
23
+ interface EntryContext {
24
+ program: Project;
25
+ transform?: Transformer;
26
+ type: Type;
27
+ declaration: ExportedDeclarations;
28
+ }
29
+ type Transformer = (this: EntryContext, entry: DocEntry, propertyType: Type, propertySymbol: Symbol) => void;
30
+ interface GenerateOptions {
31
+ /**
32
+ * Allow fields with `@internal` tag
33
+ *
34
+ * @defaultValue false
35
+ */
36
+ allowInternal?: boolean;
37
+ /**
38
+ * Modify output property entry
39
+ */
40
+ transform?: Transformer;
41
+ }
42
+ type Generator = ReturnType<typeof createGenerator>;
43
+ declare function createGenerator(config?: TypescriptConfig | Project): {
44
+ generateDocumentation(file: {
45
+ path: string;
46
+ content?: string;
47
+ }, name: string | undefined, options?: GenerateOptions): GeneratedDoc[];
48
+ };
49
+ /**
50
+ * Generate documentation for properties in an exported type/interface
51
+ *
52
+ * @deprecated use `createGenerator` instead
53
+ */
54
+ declare function generateDocumentation(file: string, name: string | undefined, content: string, options?: GenerateOptions & {
55
+ /**
56
+ * Typescript configurations
57
+ */
58
+ config?: TypescriptConfig;
59
+ project?: Project;
60
+ }): GeneratedDoc[];
61
+
62
+ interface BaseTypeTableProps {
63
+ /**
64
+ * The path to source TypeScript file.
65
+ */
66
+ path?: string;
67
+ /**
68
+ * Exported type name to generate from.
69
+ */
70
+ name?: string;
71
+ /**
72
+ * Set the type to generate from.
73
+ *
74
+ * When used with `name`, it generates the type with `name` as export name.
75
+ *
76
+ * ```ts
77
+ * export const myName = MyType;
78
+ * ```
79
+ *
80
+ * When `type` contains multiple lines, `export const` is not added.
81
+ * You need to export it manually, and specify the type name with `name`.
82
+ *
83
+ * ```tsx
84
+ * <AutoTypeTable
85
+ * path="./file.ts"
86
+ * type={`import { ReactNode } from "react"
87
+ * export const MyName = ReactNode`}
88
+ * name="MyName"
89
+ * />
90
+ * ```
91
+ */
92
+ type?: string;
93
+ }
94
+ interface GenerateTypeTableOptions extends GenerateOptions {
95
+ /**
96
+ * base path to resolve `path` prop
97
+ */
98
+ basePath?: string;
99
+ }
100
+
101
+ export { type BaseTypeTableProps as B, type DocEntry as D, type GenerateOptions as G, type GeneratedDoc as a, type Generator as b, type GenerateTypeTableOptions as c, createGenerator as d, generateDocumentation as e, getProject as g };
@@ -1,47 +1,14 @@
1
- import { G as GenerateDocumentationOptions } from '../base-BaB_XiY6.js';
1
+ import * as runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import { B as BaseTypeTableProps, b as Generator, c as GenerateTypeTableOptions } from '../type-table-Duzly_SK.js';
2
4
  import 'ts-morph';
3
5
 
4
- interface AutoTypeTableProps {
5
- /**
6
- * The path to source TypeScript file.
7
- */
8
- path?: string;
9
- /**
10
- * Exported type name to generate from.
11
- */
12
- name?: string;
13
- /**
14
- * Set the type to generate from.
15
- *
16
- * When used with `name`, it generates the type with `name` as export name.
17
- *
18
- * ```ts
19
- * export const myName = MyType;
20
- * ```
21
- *
22
- * When `type` contains multiple lines, `export const` is not added.
23
- * You need to export it manually, and specify the type name with `name`.
24
- *
25
- * ```tsx
26
- * <AutoTypeTable
27
- * path="./file.ts"
28
- * type={`import { ReactNode } from "react"
29
- * export const MyName = ReactNode`}
30
- * name="MyName"
31
- * />
32
- * ```
33
- */
34
- type?: string;
35
- options?: GenerateDocumentationOptions;
36
- }
37
- declare function createTypeTable(options?: GenerateDocumentationOptions): {
38
- AutoTypeTable: (props: Omit<AutoTypeTableProps, 'options'>) => React.ReactNode;
39
- };
40
- /**
41
- * **Server Component Only**
42
- *
43
- * Display properties in an exported interface via Type Table
44
- */
45
- declare function AutoTypeTable({ path, name, type, options, }: AutoTypeTableProps): Promise<React.ReactElement>;
6
+ type AutoTypeTableProps = BaseTypeTableProps;
7
+ declare function AutoTypeTable({ generator, options, renderMarkdown, ...props }: AutoTypeTableProps & {
8
+ generator: Generator;
9
+ renderMarkdown?: typeof renderMarkdownDefault;
10
+ options?: GenerateTypeTableOptions;
11
+ }): Promise<Promise<runtime.JSX.Element>[]>;
12
+ declare function renderMarkdownDefault(md: string): Promise<ReactNode>;
46
13
 
47
- export { AutoTypeTable, type AutoTypeTableProps, createTypeTable };
14
+ export { AutoTypeTable, type AutoTypeTableProps };
package/dist/ui/index.js CHANGED
@@ -1,58 +1,32 @@
1
1
  import {
2
2
  __async,
3
+ __objRest,
3
4
  __spreadProps,
4
5
  __spreadValues,
5
- generateDocumentation,
6
- getProject,
6
+ getTypeTableOutput,
7
7
  renderMarkdownToHast
8
- } from "../chunk-PRWE5YDY.js";
8
+ } from "../chunk-2WGVCLFC.js";
9
9
 
10
10
  // src/ui/auto-type-table.tsx
11
- import fs from "node:fs/promises";
12
11
  import { TypeTable } from "fumadocs-ui/components/type-table";
13
12
  import { toJsxRuntime } from "hast-util-to-jsx-runtime";
14
13
  import * as runtime from "react/jsx-runtime";
15
14
  import defaultMdxComponents from "fumadocs-ui/mdx";
16
15
  import "server-only";
17
- import { Fragment as Fragment2, jsx as jsx2 } from "react/jsx-runtime";
18
- function createTypeTable(options = {}) {
19
- var _a;
20
- const project = (_a = options.project) != null ? _a : getProject(options.config);
21
- return {
22
- AutoTypeTable(props) {
23
- return /* @__PURE__ */ jsx2(AutoTypeTable, __spreadProps(__spreadValues({}, props), { options: __spreadProps(__spreadValues({}, options), { project }) }));
24
- }
25
- };
26
- }
27
- function AutoTypeTable(_0) {
28
- return __async(this, arguments, function* ({
29
- path,
30
- name,
31
- type,
32
- options = {}
33
- }) {
34
- let typeName = name;
35
- let content = "";
36
- if (path) {
37
- content = (yield fs.readFile(path)).toString();
38
- }
39
- if (type && type.split("\n").length > 1) {
40
- content += `
41
- ${type}`;
42
- } else if (type) {
43
- typeName != null ? typeName : typeName = "$Fumadocs";
44
- content += `
45
- export type ${typeName} = ${type}`;
46
- }
47
- const output = generateDocumentation(
48
- path != null ? path : "temp.ts",
49
- typeName,
50
- content,
51
- options
52
- );
53
- if (name && output.length === 0)
54
- throw new Error(`${name} in ${path != null ? path : "empty file"} doesn't exist`);
55
- return /* @__PURE__ */ jsx2(Fragment2, { children: output.map((item) => __async(this, null, function* () {
16
+ import { jsx as jsx2 } from "react/jsx-runtime";
17
+ function AutoTypeTable(_a) {
18
+ return __async(this, null, function* () {
19
+ var _b = _a, {
20
+ generator,
21
+ options = {},
22
+ renderMarkdown = renderMarkdownDefault
23
+ } = _b, props = __objRest(_b, [
24
+ "generator",
25
+ "options",
26
+ "renderMarkdown"
27
+ ]);
28
+ const output = yield getTypeTableOutput(generator, props, options);
29
+ return output.map((item) => __async(this, null, function* () {
56
30
  const entries = item.entries.map(
57
31
  (entry) => __async(this, null, function* () {
58
32
  return [
@@ -73,10 +47,10 @@ export type ${typeName} = ${type}`;
73
47
  },
74
48
  item.name
75
49
  );
76
- })) });
50
+ }));
77
51
  });
78
52
  }
79
- function renderMarkdown(md) {
53
+ function renderMarkdownDefault(md) {
80
54
  return __async(this, null, function* () {
81
55
  return toJsxRuntime(yield renderMarkdownToHast(md), {
82
56
  Fragment: runtime.Fragment,
@@ -87,6 +61,5 @@ function renderMarkdown(md) {
87
61
  });
88
62
  }
89
63
  export {
90
- AutoTypeTable,
91
- createTypeTable
64
+ AutoTypeTable
92
65
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-typescript",
3
- "version": "3.0.4",
3
+ "version": "4.0.0",
4
4
  "description": "Typescript Integration for Fumadocs",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -28,24 +28,29 @@
28
28
  "dist/*"
29
29
  ],
30
30
  "dependencies": {
31
+ "estree-util-value-to-estree": "^3.3.2",
31
32
  "fast-glob": "^3.3.3",
32
- "hast-util-to-jsx-runtime": "^2.3.3",
33
- "mdast-util-from-markdown": "^2.0.2",
34
- "mdast-util-gfm": "^3.1.0",
35
- "mdast-util-to-hast": "^13.2.0",
36
- "shiki": "^3.0.0",
37
- "ts-morph": "^25.0.1"
33
+ "hast-util-to-estree": "^3.1.3",
34
+ "hast-util-to-jsx-runtime": "^2.3.6",
35
+ "remark": "^15.0.1",
36
+ "remark-rehype": "^11.1.1",
37
+ "shiki": "^3.2.1",
38
+ "ts-morph": "^25.0.1",
39
+ "unist-util-visit": "^5.0.0"
38
40
  },
39
41
  "devDependencies": {
42
+ "@mdx-js/mdx": "^3.1.0",
40
43
  "@types/estree": "^1.0.6",
41
44
  "@types/hast": "^3.0.4",
42
45
  "@types/mdast": "^4.0.3",
43
- "@types/node": "22.13.4",
44
- "@types/react": "19.0.10",
46
+ "@types/node": "22.13.11",
47
+ "@types/react": "19.0.12",
45
48
  "@types/react-dom": "19.0.4",
46
- "typescript": "^5.7.3",
49
+ "typescript": "^5.8.2",
50
+ "unified": "^11.0.5",
47
51
  "eslint-config-custom": "0.0.0",
48
- "fumadocs-ui": "15.0.13",
52
+ "fumadocs-core": "15.1.3",
53
+ "fumadocs-ui": "15.1.3",
49
54
  "tsconfig": "0.0.0"
50
55
  },
51
56
  "peerDependencies": {
@@ -1,55 +0,0 @@
1
- import { Project, Type, ExportedDeclarations, Symbol } from 'ts-morph';
2
-
3
- interface TypescriptConfig {
4
- files?: string[];
5
- tsconfigPath?: string;
6
- /** A root directory to resolve relative path entries in the config file to. e.g. outDir */
7
- basePath?: string;
8
- }
9
- declare function getProject(options?: TypescriptConfig): Project;
10
-
11
- interface GeneratedDoc {
12
- name: string;
13
- description: string;
14
- entries: DocEntry[];
15
- }
16
- interface DocEntry {
17
- name: string;
18
- description: string;
19
- type: string;
20
- tags: Record<string, string>;
21
- required: boolean;
22
- }
23
- interface EntryContext {
24
- program: Project;
25
- transform?: Transformer;
26
- type: Type;
27
- declaration: ExportedDeclarations;
28
- }
29
- type Transformer = (this: EntryContext, entry: DocEntry, propertyType: Type, propertySymbol: Symbol) => void;
30
- interface GenerateOptions {
31
- /**
32
- * Allow fields with `@internal` tag
33
- *
34
- * @defaultValue false
35
- */
36
- allowInternal?: boolean;
37
- /**
38
- * Modify output property entry
39
- */
40
- transform?: Transformer;
41
- }
42
- interface GenerateDocumentationOptions extends GenerateOptions {
43
- /**
44
- * Typescript configurations
45
- */
46
- config?: TypescriptConfig;
47
- project?: Project;
48
- }
49
- /**
50
- * Generate documentation for properties in an exported type/interface
51
- */
52
- declare function generateDocumentation(file: string, name: string | undefined, content: string, options?: GenerateDocumentationOptions): GeneratedDoc[];
53
- declare function generate(program: Project, name: string, declaration: ExportedDeclarations, { allowInternal, transform }: GenerateOptions): GeneratedDoc;
54
-
55
- export { type DocEntry as D, type GenerateDocumentationOptions as G, type GeneratedDoc as a, type GenerateOptions as b, generateDocumentation as c, generate as d, getProject as g };
@@ -1,206 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
- var __spreadValues = (a, b) => {
9
- for (var prop in b || (b = {}))
10
- if (__hasOwnProp.call(b, prop))
11
- __defNormalProp(a, prop, b[prop]);
12
- if (__getOwnPropSymbols)
13
- for (var prop of __getOwnPropSymbols(b)) {
14
- if (__propIsEnum.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- }
17
- return a;
18
- };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
- var __objRest = (source, exclude) => {
21
- var target = {};
22
- for (var prop in source)
23
- if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
- target[prop] = source[prop];
25
- if (source != null && __getOwnPropSymbols)
26
- for (var prop of __getOwnPropSymbols(source)) {
27
- if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
- target[prop] = source[prop];
29
- }
30
- return target;
31
- };
32
- var __async = (__this, __arguments, generator) => {
33
- return new Promise((resolve, reject) => {
34
- var fulfilled = (value) => {
35
- try {
36
- step(generator.next(value));
37
- } catch (e) {
38
- reject(e);
39
- }
40
- };
41
- var rejected = (value) => {
42
- try {
43
- step(generator.throw(value));
44
- } catch (e) {
45
- reject(e);
46
- }
47
- };
48
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
49
- step((generator = generator.apply(__this, __arguments)).next());
50
- });
51
- };
52
-
53
- // src/get-project.ts
54
- import { Project } from "ts-morph";
55
- function getProject(options = {}) {
56
- var _a;
57
- return new Project({
58
- tsConfigFilePath: (_a = options.tsconfigPath) != null ? _a : "./tsconfig.json",
59
- skipAddingFilesFromTsConfig: true
60
- });
61
- }
62
-
63
- // src/generate/base.ts
64
- import {
65
- ts
66
- } from "ts-morph";
67
- function generateDocumentation(file, name, content, options = {}) {
68
- var _a;
69
- const project = (_a = options.project) != null ? _a : getProject(options.config);
70
- const sourceFile = project.createSourceFile(file, content, {
71
- overwrite: true
72
- });
73
- const out = [];
74
- for (const [k, d] of sourceFile.getExportedDeclarations()) {
75
- if (name && name !== k) continue;
76
- if (d.length > 1)
77
- console.warn(
78
- `export ${k} should not have more than one type declaration.`
79
- );
80
- out.push(generate(project, k, d[0], options));
81
- }
82
- return out;
83
- }
84
- function generate(program, name, declaration, { allowInternal = false, transform }) {
85
- var _a;
86
- const entryContext = {
87
- transform,
88
- program,
89
- type: declaration.getType(),
90
- declaration
91
- };
92
- const comment = (_a = declaration.getSymbol()) == null ? void 0 : _a.compilerSymbol.getDocumentationComment(
93
- program.getTypeChecker().compilerObject
94
- );
95
- return {
96
- name,
97
- description: comment ? ts.displayPartsToString(comment) : "",
98
- entries: declaration.getType().getProperties().map((prop) => getDocEntry(prop, entryContext)).filter(
99
- (entry) => entry && (allowInternal || !("internal" in entry.tags))
100
- )
101
- };
102
- }
103
- function getDocEntry(prop, context) {
104
- var _a, _b, _c, _d;
105
- const { transform, program } = context;
106
- if (context.type.isClass() && prop.getName().startsWith("#")) {
107
- return;
108
- }
109
- const subType = program.getTypeChecker().getTypeOfSymbolAtLocation(prop, context.declaration);
110
- const tags = Object.fromEntries(
111
- prop.getJsDocTags().map((tag) => [tag.getName(), ts.displayPartsToString(tag.getText())])
112
- );
113
- let typeName = subType.getNonNullableType().getText(void 0, ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
114
- if (subType.getAliasSymbol() && subType.getAliasTypeArguments().length === 0) {
115
- typeName = (_b = (_a = subType.getAliasSymbol()) == null ? void 0 : _a.getEscapedName()) != null ? _b : typeName;
116
- }
117
- if ("remarks" in tags) {
118
- typeName = (_d = (_c = new RegExp("^`(?<name>.+)`").exec(tags.remarks)) == null ? void 0 : _c[1]) != null ? _d : typeName;
119
- }
120
- const entry = {
121
- name: prop.getName(),
122
- description: ts.displayPartsToString(
123
- prop.compilerSymbol.getDocumentationComment(
124
- program.getTypeChecker().compilerObject
125
- )
126
- ),
127
- tags,
128
- type: typeName,
129
- required: !prop.isOptional()
130
- };
131
- transform == null ? void 0 : transform.call(context, entry, subType, prop);
132
- return entry;
133
- }
134
-
135
- // src/markdown.ts
136
- import { fromMarkdown } from "mdast-util-from-markdown";
137
- import { gfmFromMarkdown } from "mdast-util-gfm";
138
- import { toHast } from "mdast-util-to-hast";
139
- import { getSingletonHighlighter } from "shiki";
140
- function renderMarkdownToHast(md) {
141
- return __async(this, null, function* () {
142
- const mdast = fromMarkdown(
143
- md.replace(new RegExp("{@link (?<link>[^}]*)}", "g"), "$1"),
144
- // replace jsdoc links
145
- { mdastExtensions: [gfmFromMarkdown()] }
146
- );
147
- const highlighter = yield getSingletonHighlighter({
148
- themes: ["vitesse-light", "vitesse-dark"]
149
- });
150
- function preload(contents) {
151
- return __async(this, null, function* () {
152
- yield Promise.all(
153
- contents.map((c) => __async(this, null, function* () {
154
- if ("children" in c) yield preload(c.children);
155
- if (c.type === "code" && c.lang) {
156
- yield highlighter.loadLanguage(
157
- c.lang
158
- );
159
- }
160
- }))
161
- );
162
- });
163
- }
164
- yield preload(mdast.children);
165
- return toHast(mdast, {
166
- handlers: {
167
- // @ts-expect-error hast with mdx
168
- code(_, node) {
169
- var _a;
170
- const lang = (_a = node.lang) != null ? _a : "plaintext";
171
- return highlighter.codeToHast(node.value, {
172
- lang,
173
- themes: {
174
- light: "vitesse-light",
175
- dark: "vitesse-dark"
176
- },
177
- defaultColor: false,
178
- transformers: [
179
- {
180
- name: "rehype-code:pre-process",
181
- line(hast) {
182
- if (hast.children.length > 0) return;
183
- hast.children.push({
184
- type: "text",
185
- value: " "
186
- });
187
- }
188
- }
189
- ]
190
- }).children;
191
- }
192
- }
193
- });
194
- });
195
- }
196
-
197
- export {
198
- __spreadValues,
199
- __spreadProps,
200
- __objRest,
201
- __async,
202
- getProject,
203
- generateDocumentation,
204
- generate,
205
- renderMarkdownToHast
206
- };