Skip to content

Commit b83d946

Browse files
committed
TypeScript: Introduce createGenerator API
1 parent d7765de commit b83d946

File tree

13 files changed

+228
-174
lines changed

13 files changed

+228
-174
lines changed

.changeset/social-moons-roll.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
'fumadocs-typescript': major
3+
---
4+
5+
**Use `createGenerator` API**
6+
7+
Create a generator instance:
8+
9+
```ts
10+
import { createGenerator } from 'fumadocs-typescript';
11+
12+
const generator = createGenerator(tsconfig);
13+
```
14+
15+
Refactor:
16+
17+
```tsx
18+
import { remarkAutoTypeTable, createTypeTable } from 'fumadocs-typescript';
19+
20+
generateDocumentation('./file.ts', 'MyClass', fs.readFileSync('./file.ts').toString())
21+
generateMDX('content', {...})
22+
generateFiles({...})
23+
const processor = createProcessor({
24+
remarkPlugins: [remarkAutoTypeTable],
25+
});
26+
27+
const AutoTypeTable = createTypeTable()
28+
return <AutoTypeTable {...props} />
29+
```
30+
31+
To:
32+
33+
```tsx
34+
import { AutoTypeTable, remarkAutoTypeTable } from "fumadocs-typescript";
35+
36+
generator.generateDocumentation({path: './file.ts'}, 'MyClass')
37+
generateMDX(generator, 'content', { ... })
38+
generateFiles(generator, { ... })
39+
const processor = createProcessor({
40+
remarkPlugins: [
41+
[remarkAutoTypeTable, { generator }],
42+
],
43+
});
44+
45+
return <AutoTypeTable generator={generator} {...props} />
46+
```
47+
48+
This ensure the compiler instance is always re-used.

apps/docs/app/docs/[...slug]/page.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import * as Preview from '@/components/preview';
2222
import { createMetadata } from '@/lib/metadata';
2323
import { openapi, source } from '@/lib/source';
2424
import { Wrapper } from '@/components/preview/wrapper';
25-
import { AutoTypeTable } from '@/components/type-table';
2625
import { metadataImage } from '@/lib/metadata-image';
2726
import { File, Folder, Files } from 'fumadocs-ui/components/files';
2827
import { Mermaid } from '@theguild/remark-mermaid/mermaid';
@@ -37,6 +36,8 @@ import {
3736
} from '@/components/ui/hover-card';
3837
import Link from 'fumadocs-core/link';
3938
import { UiOverview } from '@/components/ui-overview';
39+
import { AutoTypeTable } from 'fumadocs-typescript/ui';
40+
import { createGenerator } from 'fumadocs-typescript';
4041

4142
function PreviewRenderer({ preview }: { preview: string }): ReactNode {
4243
if (preview && preview in Preview) {
@@ -47,6 +48,8 @@ function PreviewRenderer({ preview }: { preview: string }): ReactNode {
4748
return null;
4849
}
4950

51+
const generator = createGenerator();
52+
5053
export const revalidate = false;
5154

5255
export default async function Page(props: {
@@ -123,7 +126,9 @@ export default async function Page(props: {
123126
Tab,
124127
Mermaid,
125128
TypeTable,
126-
AutoTypeTable,
129+
AutoTypeTable: (props) => (
130+
<AutoTypeTable generator={generator} {...props} />
131+
),
127132
Accordion,
128133
Accordions,
129134
Wrapper,

apps/docs/components/type-table.ts

Lines changed: 0 additions & 3 deletions
This file was deleted.

apps/docs/content/docs/ui/(integrations)/typescript.mdx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,26 @@ It comes with the `AutoTypeTable` component. Learn more about [Auto Type Table](
1818
You can use it as a remark plugin:
1919

2020
```ts title="source.config.ts" tab="Fumadocs MDX"
21-
import { remarkAutoTypeTable } from 'fumadocs-typescript';
21+
import { remarkAutoTypeTable, createGenerator } from 'fumadocs-typescript';
2222
import { defineConfig } from 'fumadocs-mdx/config';
2323

24+
const generator = createGenerator();
25+
2426
export default defineConfig({
2527
mdxOptions: {
26-
remarkPlugins: [remarkAutoTypeTable],
28+
remarkPlugins: [[remarkAutoTypeTable, { generator }]],
2729
},
2830
});
2931
```
3032

3133
```ts tab="MDX Compiler"
32-
import { remarkAutoTypeTable } from 'fumadocs-typescript';
34+
import { remarkAutoTypeTable, createGenerator } from 'fumadocs-typescript';
3335
import { compile } from '@mdx-js/mdx';
3436

37+
const generator = createGenerator();
38+
3539
await compile('...', {
36-
remarkPlugins: [remarkAutoTypeTable],
40+
remarkPlugins: [[remarkAutoTypeTable, { generator }]],
3741
});
3842
```
3943

apps/docs/content/docs/ui/components/auto-type-table.mdx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,22 @@ fumadocs-typescript
4141
Initialize the TypeScript compiler and add it as a MDX component.
4242

4343
```tsx title="page.tsx"
44-
import { createTypeTable } from 'fumadocs-typescript/ui';
44+
import { createGenerator } from 'fumadocs-typescript';
45+
import { AutoTypeTable } from 'fumadocs-typescript/ui';
4546
import defaultMdxComponents from 'fumadocs-ui/mdx';
4647

47-
const { AutoTypeTable } = createTypeTable();
48-
49-
<MDX
50-
components={{
51-
...defaultMdxComponents,
52-
AutoTypeTable,
53-
}}
54-
/>;
48+
const generator = createGenerator();
49+
50+
return (
51+
<MDX
52+
components={{
53+
...defaultMdxComponents,
54+
AutoTypeTable: (props) => (
55+
<AutoTypeTable {...props} generator={generator} />
56+
),
57+
}}
58+
/>
59+
);
5560
```
5661

5762
### From File

packages/typescript/src/lib/base.ts

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import {
22
type ExportedDeclarations,
3-
type Project,
3+
Project,
44
type Symbol as TsSymbol,
55
ts,
66
type Type,
77
} from 'ts-morph';
88
import { getProject, type TypescriptConfig } from '@/get-project';
9+
import fs from 'node:fs';
910

1011
export interface GeneratedDoc {
1112
name: string;
@@ -49,44 +50,68 @@ export interface GenerateOptions {
4950
transform?: Transformer;
5051
}
5152

52-
export interface GenerateDocumentationOptions extends GenerateOptions {
53-
/**
54-
* Typescript configurations
55-
*/
56-
config?: TypescriptConfig;
57-
project?: Project;
53+
export type Generator = ReturnType<typeof createGenerator>;
54+
55+
export function createGenerator(config?: TypescriptConfig | Project) {
56+
const project = config instanceof Project ? config : getProject(config);
57+
58+
return {
59+
generateDocumentation(
60+
file: {
61+
path: string;
62+
content?: string;
63+
},
64+
name: string | undefined,
65+
options: GenerateOptions = {},
66+
) {
67+
const sourceFile = project.createSourceFile(
68+
file.path,
69+
file.content ?? fs.readFileSync(file.path).toString(),
70+
{
71+
overwrite: true,
72+
},
73+
);
74+
const out: GeneratedDoc[] = [];
75+
76+
for (const [k, d] of sourceFile.getExportedDeclarations()) {
77+
if (name && name !== k) continue;
78+
79+
if (d.length > 1)
80+
console.warn(
81+
`export ${k} should not have more than one type declaration.`,
82+
);
83+
84+
out.push(generate(project, k, d[0], options));
85+
}
86+
87+
return out;
88+
},
89+
};
5890
}
5991

6092
/**
6193
* Generate documentation for properties in an exported type/interface
94+
*
95+
* @deprecated use `createGenerator` instead
6296
*/
6397
export function generateDocumentation(
6498
file: string,
6599
name: string | undefined,
66100
content: string,
67-
options: GenerateDocumentationOptions = {},
101+
options: GenerateOptions & {
102+
/**
103+
* Typescript configurations
104+
*/
105+
config?: TypescriptConfig;
106+
project?: Project;
107+
} = {},
68108
): GeneratedDoc[] {
69-
const project = options.project ?? getProject(options.config);
70-
const sourceFile = project.createSourceFile(file, content, {
71-
overwrite: true,
72-
});
73-
const out: GeneratedDoc[] = [];
74-
75-
for (const [k, d] of sourceFile.getExportedDeclarations()) {
76-
if (name && name !== k) continue;
77-
78-
if (d.length > 1)
79-
console.warn(
80-
`export ${k} should not have more than one type declaration.`,
81-
);
82-
83-
out.push(generate(project, k, d[0], options));
84-
}
109+
const gen = createGenerator(options.project ?? options.config);
85110

86-
return out;
111+
return gen.generateDocumentation({ path: file, content }, name, options);
87112
}
88113

89-
export function generate(
114+
function generate(
90115
program: Project,
91116
name: string,
92117
declaration: ExportedDeclarations,

packages/typescript/src/lib/file.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import * as path from 'node:path';
22
import { mkdir, writeFile, readFile } from 'node:fs/promises';
33
import fg from 'fast-glob';
4-
import { getProject } from '@/get-project';
54
import { generateMDX, type GenerateMDXOptions } from './mdx';
5+
import type { Generator } from '@/lib/base';
66

77
export interface GenerateFilesOptions {
88
input: string | string[];
@@ -20,11 +20,10 @@ export interface GenerateFilesOptions {
2020
}
2121

2222
export async function generateFiles(
23+
generator: Generator,
2324
options: GenerateFilesOptions,
2425
): Promise<void> {
2526
const files = await fg(options.input, options.globOptions);
26-
const project =
27-
options.options?.project ?? getProject(options.options?.config);
2827

2928
const produce = files.map(async (file) => {
3029
const absolutePath = path.resolve(file);
@@ -37,10 +36,9 @@ export async function generateFiles(
3736
);
3837

3938
const content = (await readFile(absolutePath)).toString();
40-
let result = generateMDX(content, {
39+
let result = generateMDX(generator, content, {
4140
basePath: path.dirname(absolutePath),
4241
...options.options,
43-
project,
4442
});
4543

4644
if (options.transformOutput) {

packages/typescript/src/lib/mdx.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
import * as path from 'node:path';
2-
import fs from 'node:fs';
3-
import { getProject } from '@/get-project';
42
import {
53
type DocEntry,
64
type GeneratedDoc,
7-
generateDocumentation,
8-
type GenerateDocumentationOptions,
5+
type Generator,
6+
type GenerateOptions,
97
} from './base';
108

119
interface Templates {
1210
block: (doc: GeneratedDoc, children: string) => string;
1311
property: (entry: DocEntry) => string;
1412
}
1513

16-
export interface GenerateMDXOptions extends GenerateDocumentationOptions {
14+
export interface GenerateMDXOptions extends GenerateOptions {
1715
/**
1816
* a root directory to resolve relative file paths
1917
*/
@@ -49,23 +47,23 @@ ${Object.entries(c.tags)
4947
};
5048

5149
export function generateMDX(
50+
generator: Generator,
5251
source: string,
5352
{ basePath = './', templates: overrides, ...rest }: GenerateMDXOptions = {},
5453
): string {
5554
const templates = { ...defaultTemplates, ...overrides };
56-
const project = rest.project ?? getProject(rest.config);
5755

5856
return source.replace(regex, (...args) => {
5957
const groups = args[args.length - 1] as {
6058
file: string;
6159
name: string | undefined;
6260
};
6361
const file = path.resolve(basePath, groups.file);
64-
const content = fs.readFileSync(file);
65-
const docs = generateDocumentation(file, groups.name, content.toString(), {
66-
...rest,
67-
project,
68-
});
62+
const docs = generator.generateDocumentation(
63+
{ path: file },
64+
groups.name,
65+
rest,
66+
);
6967

7068
return docs
7169
.map((doc) =>

0 commit comments

Comments
 (0)