mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-26 10:55:57 +00:00
TypeScript: Support props passthrough for type tables
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-typescript': patch
|
||||
---
|
||||
|
||||
Support props passthrough for type tables
|
||||
@@ -5,7 +5,7 @@ description: Auto-generated type table
|
||||
|
||||
<Wrapper>
|
||||
|
||||
<auto-type-table name="AutoTypeTableExample" type='export interface AutoTypeTableExample {
|
||||
<auto-type-table id="example" name="AutoTypeTableExample" type='export interface AutoTypeTableExample {
|
||||
|
||||
/**
|
||||
* Markdown syntax like links, `code` are supported.
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
"hast-util-to-jsx-runtime": "^2.3.6",
|
||||
"remark": "^15.0.1",
|
||||
"remark-rehype": "^11.1.2",
|
||||
"tinyglobby": "^0.2.15",
|
||||
"ts-morph": "^27.0.2",
|
||||
"unified": "^11.0.5",
|
||||
"unist-util-visit": "^5.1.0"
|
||||
@@ -62,7 +61,8 @@
|
||||
"mdast-util-mdx": "^3.0.0",
|
||||
"tsconfig": "workspace:*",
|
||||
"tsdown": "^0.20.3",
|
||||
"typescript": "^5.9.3"
|
||||
"typescript": "^5.9.3",
|
||||
"vfile": "^6.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/estree": "*",
|
||||
|
||||
+2
-7
@@ -1,5 +1,4 @@
|
||||
import fs from 'node:fs/promises';
|
||||
import { createHash } from 'node:crypto';
|
||||
import path from 'node:path';
|
||||
import type { Cache } from '@/cache/index';
|
||||
|
||||
@@ -11,15 +10,11 @@ export function createFileSystemGeneratorCache(dir: string): Cache {
|
||||
});
|
||||
|
||||
return {
|
||||
async write(input, data) {
|
||||
const hash = createHash('SHA256').update(input).digest('hex').slice(0, 12);
|
||||
|
||||
async write(hash, data) {
|
||||
await initDirPromise;
|
||||
await fs.writeFile(path.join(dir, `${hash}.json`), JSON.stringify(data));
|
||||
},
|
||||
async read(input) {
|
||||
const hash = createHash('SHA256').update(input).digest('hex').slice(0, 12);
|
||||
|
||||
async read(hash) {
|
||||
try {
|
||||
return JSON.parse((await fs.readFile(path.join(dir, `${hash}.json`))).toString());
|
||||
} catch {
|
||||
|
||||
+8
-2
@@ -1,4 +1,10 @@
|
||||
import { createHash } from 'node:crypto';
|
||||
|
||||
export interface Cache {
|
||||
read: (key: string) => unknown | undefined | Promise<unknown | undefined>;
|
||||
write: (key: string, value: unknown) => void | Promise<void>;
|
||||
read: (hash: string) => unknown | undefined | Promise<unknown | undefined>;
|
||||
write: (hash: string, value: unknown) => void | Promise<void>;
|
||||
}
|
||||
|
||||
export function generateHash(str: string) {
|
||||
return createHash('SHA256').update(str).digest('hex').slice(0, 12);
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { Project } from 'ts-morph';
|
||||
|
||||
export interface TypescriptConfig {
|
||||
files?: string[];
|
||||
tsconfigPath?: string;
|
||||
/** A root directory to resolve relative path entries in the config file to. e.g. outDir */
|
||||
basePath?: string;
|
||||
}
|
||||
|
||||
export function createProject(options: TypescriptConfig = {}): Project {
|
||||
return new Project({
|
||||
tsConfigFilePath: options.tsconfigPath ?? './tsconfig.json',
|
||||
skipAddingFilesFromTsConfig: true,
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
export * from '@/lib/base';
|
||||
export type { MarkdownRenderer } from './markdown';
|
||||
export { createProject } from './create-project';
|
||||
export * from '@/lib/remark-auto-type-table';
|
||||
export * from './cache/fs-cache';
|
||||
export * from './cache';
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
import {
|
||||
type ExportedDeclarations,
|
||||
Project,
|
||||
type Symbol as TsSymbol,
|
||||
ts,
|
||||
type Type,
|
||||
} from 'ts-morph';
|
||||
import { createProject, type TypescriptConfig } from '@/create-project';
|
||||
import type { ExportedDeclarations, Symbol as TsSymbol, Project, Type } from 'ts-morph';
|
||||
import fs from 'node:fs/promises';
|
||||
import {
|
||||
type BaseTypeTableProps,
|
||||
@@ -13,8 +6,7 @@ import {
|
||||
getTypeTableOutput,
|
||||
} from '@/lib/type-table';
|
||||
import path from 'node:path';
|
||||
import { getSimpleForm } from '@/lib/get-simple-form';
|
||||
import type { Cache } from '@/cache';
|
||||
import { generateHash, type Cache } from '@/cache';
|
||||
import { version as packageVersion } from '../../package.json';
|
||||
|
||||
export interface GeneratedDoc {
|
||||
@@ -23,7 +15,7 @@ export interface GeneratedDoc {
|
||||
*/
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
description?: string;
|
||||
entries: DocEntry[];
|
||||
}
|
||||
|
||||
@@ -44,9 +36,8 @@ export interface RawTag {
|
||||
text: string;
|
||||
}
|
||||
|
||||
interface EntryContext {
|
||||
interface EntryContext extends GenerateOptions {
|
||||
program: Project;
|
||||
transform?: Transformer;
|
||||
type: Type;
|
||||
declaration: ExportedDeclarations;
|
||||
}
|
||||
@@ -85,19 +76,40 @@ export interface GeneratorOptions extends TypescriptConfig {
|
||||
project?: Project;
|
||||
}
|
||||
|
||||
export function createGenerator(config?: GeneratorOptions | Project) {
|
||||
const options =
|
||||
config instanceof Project
|
||||
? {
|
||||
project: config,
|
||||
}
|
||||
: config;
|
||||
export interface TypescriptConfig {
|
||||
tsconfigPath?: string;
|
||||
}
|
||||
|
||||
export async function createProject(options: TypescriptConfig = {}): Promise<Project> {
|
||||
const { Project } = await import('ts-morph');
|
||||
return new Project({
|
||||
tsConfigFilePath: options.tsconfigPath ?? './tsconfig.json',
|
||||
skipAddingFilesFromTsConfig: true,
|
||||
});
|
||||
}
|
||||
|
||||
export function createGenerator(options: GeneratorOptions = {}) {
|
||||
const cache = options?.cache ? options.cache : null;
|
||||
let instance: Project | undefined;
|
||||
let instance: Project | Promise<Project> | undefined = options?.project;
|
||||
|
||||
function getProject() {
|
||||
instance ??= options?.project ?? createProject(options);
|
||||
return instance;
|
||||
if (instance) return instance;
|
||||
return (instance = createProject(options));
|
||||
}
|
||||
|
||||
function getSourceFile(project: Project, filePath: string, fileContent: string) {
|
||||
const ext = path.extname(filePath);
|
||||
const fileBase = filePath.slice(0, -ext.length);
|
||||
let i = 0;
|
||||
let sourceFile = project.getSourceFile(filePath);
|
||||
|
||||
while (sourceFile && sourceFile.getFullText() !== fileContent) {
|
||||
filePath = `${fileBase}.${i++}${ext}`;
|
||||
sourceFile = project.getSourceFile(filePath);
|
||||
}
|
||||
|
||||
if (sourceFile) return sourceFile;
|
||||
return project.createSourceFile(filePath, fileContent, { overwrite: true });
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -109,35 +121,38 @@ export function createGenerator(config?: GeneratorOptions | Project) {
|
||||
name: string | undefined,
|
||||
options: GenerateOptions = {},
|
||||
) {
|
||||
const content = file.content ?? (await fs.readFile(path.resolve(file.path))).toString();
|
||||
const cacheKey = `${file.path}:${name}:${content}:${packageVersion}`;
|
||||
const fullPath = path.resolve(file.path);
|
||||
const content = file.content ?? (await fs.readFile(fullPath)).toString();
|
||||
let cacheKey: string | undefined;
|
||||
if (cache) {
|
||||
cacheKey = generateHash(`${file.path}:${name}:${content}:${packageVersion}`);
|
||||
const cached = (await cache.read(cacheKey)) as GeneratedDoc[] | undefined;
|
||||
if (cached) return cached;
|
||||
}
|
||||
const sourceFile = getProject().createSourceFile(file.path, content, {
|
||||
overwrite: true,
|
||||
});
|
||||
|
||||
const project = await getProject();
|
||||
const sourceFile = getSourceFile(project, fullPath, content);
|
||||
const out: GeneratedDoc[] = [];
|
||||
|
||||
for (const [k, d] of sourceFile.getExportedDeclarations()) {
|
||||
if (name && name !== k) continue;
|
||||
if (d.length === 0 || !name || name !== k) continue;
|
||||
|
||||
if (d.length > 1)
|
||||
console.warn(`export ${k} should not have more than one type declaration.`);
|
||||
|
||||
out.push(
|
||||
generate(
|
||||
encodeURI(`${path.basename(file.path)}-${name}`),
|
||||
getProject(),
|
||||
k,
|
||||
d[0],
|
||||
options,
|
||||
),
|
||||
);
|
||||
const declaration = d[0];
|
||||
const entryContext: EntryContext = {
|
||||
...options,
|
||||
program: project,
|
||||
type: declaration.getType(),
|
||||
declaration,
|
||||
};
|
||||
out.push(await generate(encodeURI(`${path.basename(file.path)}-${name}`), k, entryContext));
|
||||
}
|
||||
|
||||
void cache?.write(cacheKey, out);
|
||||
if (cache && cacheKey) {
|
||||
await cache.write(cacheKey, out);
|
||||
}
|
||||
return out;
|
||||
},
|
||||
generateTypeTable(props: BaseTypeTableProps, options?: GenerateTypeTableOptions) {
|
||||
@@ -146,51 +161,51 @@ export function createGenerator(config?: GeneratorOptions | Project) {
|
||||
};
|
||||
}
|
||||
|
||||
function generate(
|
||||
async function generate(
|
||||
id: string,
|
||||
program: Project,
|
||||
name: string,
|
||||
declaration: ExportedDeclarations,
|
||||
{ allowInternal = false, transform }: GenerateOptions,
|
||||
): GeneratedDoc {
|
||||
const entryContext: EntryContext = {
|
||||
transform,
|
||||
program,
|
||||
type: declaration.getType(),
|
||||
declaration,
|
||||
};
|
||||
entryContext: EntryContext,
|
||||
): Promise<GeneratedDoc> {
|
||||
const { ts } = await import('ts-morph');
|
||||
const { declaration, program } = entryContext;
|
||||
|
||||
const comment = declaration
|
||||
.getSymbol()
|
||||
?.compilerSymbol.getDocumentationComment(program.getTypeChecker().compilerObject);
|
||||
const entries: DocEntry[] = [];
|
||||
for (const prop of declaration.getType().getProperties()) {
|
||||
const out = await getDocEntry(prop, entryContext);
|
||||
if (out) entries.push(out);
|
||||
}
|
||||
|
||||
return {
|
||||
id,
|
||||
name,
|
||||
description: comment ? ts.displayPartsToString(comment) : '',
|
||||
entries: declaration
|
||||
.getType()
|
||||
.getProperties()
|
||||
.map((prop) => getDocEntry(prop, entryContext))
|
||||
.filter((entry) => entry && (allowInternal || !('internal' in entry.tags))) as DocEntry[],
|
||||
description: comment ? ts.displayPartsToString(comment) : undefined,
|
||||
entries,
|
||||
};
|
||||
}
|
||||
|
||||
function getDocEntry(prop: TsSymbol, context: EntryContext): DocEntry | undefined {
|
||||
const { transform, program } = context;
|
||||
async function getDocEntry(prop: TsSymbol, context: EntryContext): Promise<DocEntry | undefined> {
|
||||
const { ts } = await import('ts-morph');
|
||||
const { getSimpleForm } = await import('@/lib/get-simple-form');
|
||||
const { transform, allowInternal = false, program } = context;
|
||||
if (context.type.isClass() && prop.getName().startsWith('#')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const subType = prop.getTypeAtLocation(context.declaration);
|
||||
const isOptional = prop.isOptional();
|
||||
const tags = prop.getJsDocTags().map(
|
||||
(tag) =>
|
||||
({
|
||||
name: tag.getName(),
|
||||
text: ts.displayPartsToString(tag.getText()),
|
||||
}) satisfies RawTag,
|
||||
);
|
||||
const tags: RawTag[] = [];
|
||||
|
||||
for (const tag of prop.getJsDocTags()) {
|
||||
if (!allowInternal && tag.getName() === 'internal') return;
|
||||
|
||||
tags.push({
|
||||
name: tag.getName(),
|
||||
text: ts.displayPartsToString(tag.getText()),
|
||||
});
|
||||
}
|
||||
|
||||
const entry: DocEntry = {
|
||||
name: prop.getName(),
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import * as ts from 'ts-morph';
|
||||
import { Node, Type, TypeChecker, TypeFormatFlags } from 'ts-morph';
|
||||
|
||||
export function getSimpleForm(
|
||||
type: ts.Type,
|
||||
checker: ts.TypeChecker,
|
||||
type: Type,
|
||||
checker: TypeChecker,
|
||||
noUndefined = false,
|
||||
location?: ts.Node,
|
||||
location?: Node,
|
||||
): string {
|
||||
if (type.isUndefined() && noUndefined) return '';
|
||||
|
||||
@@ -60,7 +60,7 @@ export function getSimpleForm(
|
||||
return 'object';
|
||||
}
|
||||
|
||||
return type.getText(location, ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
|
||||
return type.getText(location, TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
|
||||
}
|
||||
|
||||
function dedupe<T>(arr: T[]): T[] {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RawTag } from '@/lib/base';
|
||||
import type { RawTag } from '@/lib/base';
|
||||
|
||||
export interface ParameterTag {
|
||||
name: string;
|
||||
|
||||
@@ -10,7 +10,8 @@ import { type BaseTypeTableProps, type GenerateTypeTableOptions } from '@/lib/ty
|
||||
import { toEstree } from 'hast-util-to-estree';
|
||||
import { type ParameterTag, parseTags } from '@/lib/parse-tags';
|
||||
import type { ResolvedShikiConfig } from 'fumadocs-core/highlight/config';
|
||||
import type { MdxJsxFlowElement } from 'mdast-util-mdx';
|
||||
import type { MdxJsxAttribute, MdxJsxExpressionAttribute, MdxJsxFlowElement } from 'mdast-util-mdx';
|
||||
import type { VFile } from 'vfile';
|
||||
|
||||
function objectBuilder() {
|
||||
const out: ObjectExpression = {
|
||||
@@ -166,64 +167,69 @@ export function remarkAutoTypeTable(
|
||||
if (renderType) renderer.renderTypeToHast = renderType;
|
||||
}
|
||||
|
||||
return async (tree, file) => {
|
||||
const queue: Promise<void>[] = [];
|
||||
async function run(node: object, props: TypeTableProps) {
|
||||
let basePath = props.cwd ? file.cwd : generateOptions.basePath;
|
||||
if (file.dirname) {
|
||||
basePath ??= file.dirname;
|
||||
}
|
||||
async function generate(
|
||||
file: VFile,
|
||||
props: TypeTableProps,
|
||||
attributes: (MdxJsxAttribute | MdxJsxExpressionAttribute)[],
|
||||
) {
|
||||
let basePath = props.cwd ? file.cwd : generateOptions.basePath;
|
||||
if (file.dirname) {
|
||||
basePath ??= file.dirname;
|
||||
}
|
||||
|
||||
const output = await generator.generateTypeTable(props, {
|
||||
...generateOptions,
|
||||
basePath,
|
||||
});
|
||||
const output = await generator.generateTypeTable(props, {
|
||||
...generateOptions,
|
||||
basePath,
|
||||
});
|
||||
const rendered: MdxJsxFlowElement[] = [];
|
||||
|
||||
const rendered = output.map(async (doc): Promise<MdxJsxFlowElement> => {
|
||||
return {
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: outputName,
|
||||
attributes: [
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'id',
|
||||
value: `type-table-${doc.id}`,
|
||||
},
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'type',
|
||||
value: {
|
||||
type: 'mdxJsxAttributeValueExpression',
|
||||
value: remarkStringify ? JSON.stringify(doc, null, 2) : '',
|
||||
data: {
|
||||
estree: {
|
||||
type: 'Program',
|
||||
sourceType: 'module',
|
||||
body: [
|
||||
{
|
||||
type: 'ExpressionStatement',
|
||||
expression: await buildTypeProp(doc.entries, renderer),
|
||||
},
|
||||
],
|
||||
},
|
||||
for (const doc of output) {
|
||||
rendered.push({
|
||||
type: 'mdxJsxFlowElement',
|
||||
name: outputName,
|
||||
attributes: [
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'id',
|
||||
value: `type-table-${doc.id}`,
|
||||
},
|
||||
{
|
||||
type: 'mdxJsxAttribute',
|
||||
name: 'type',
|
||||
value: {
|
||||
type: 'mdxJsxAttributeValueExpression',
|
||||
value: remarkStringify ? JSON.stringify(doc, null, 2) : '',
|
||||
data: {
|
||||
estree: {
|
||||
type: 'Program',
|
||||
sourceType: 'module',
|
||||
body: [
|
||||
{
|
||||
type: 'ExpressionStatement',
|
||||
expression: await buildTypeProp(doc.entries, renderer),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
children: [],
|
||||
};
|
||||
},
|
||||
...attributes,
|
||||
],
|
||||
children: [],
|
||||
});
|
||||
|
||||
Object.assign(node, {
|
||||
type: 'root',
|
||||
attributes: [],
|
||||
children: await Promise.all(rendered),
|
||||
} as Root);
|
||||
}
|
||||
|
||||
return rendered;
|
||||
}
|
||||
|
||||
return async (tree, file) => {
|
||||
const queue: Promise<void>[] = [];
|
||||
|
||||
visit(tree, 'mdxJsxFlowElement', (node) => {
|
||||
if (node.name !== name) return;
|
||||
const props: Record<string, string | true> = {};
|
||||
const props: TypeTableProps = {};
|
||||
const attributes: (MdxJsxAttribute | MdxJsxExpressionAttribute)[] = [];
|
||||
|
||||
const onError = (message: string, cause?: Error) => {
|
||||
const location = node.position
|
||||
? `${file.path}:${node.position.start.line}:${node.position.start.column}`
|
||||
@@ -235,20 +241,41 @@ export function remarkAutoTypeTable(
|
||||
|
||||
for (const attr of node.attributes) {
|
||||
if (attr.type !== 'mdxJsxAttribute') {
|
||||
onError('only named attributes are allowed.');
|
||||
} else if (typeof attr.value === 'string') {
|
||||
props[attr.name] = attr.value;
|
||||
} else if (attr.value === null) {
|
||||
props[attr.name] = true;
|
||||
} else {
|
||||
onError('only string & boolean attributes are allowed.');
|
||||
attributes.push(attr);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (attr.name) {
|
||||
case 'cwd':
|
||||
props.cwd = true;
|
||||
break;
|
||||
case 'path':
|
||||
case 'name':
|
||||
case 'type':
|
||||
if (typeof attr.value === 'string') {
|
||||
props[attr.name] = attr.value;
|
||||
} else {
|
||||
onError(
|
||||
`invalid type for attribute ${attr.name}: ${typeof attr.value}, expected: string`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
attributes.push(attr);
|
||||
}
|
||||
}
|
||||
|
||||
queue.push(
|
||||
run(node, props).catch((err) => {
|
||||
onError('failed to generate type table', err);
|
||||
}),
|
||||
generate(file, props, attributes)
|
||||
.then((children) => {
|
||||
Object.assign(node, {
|
||||
type: 'root',
|
||||
children,
|
||||
} satisfies Root);
|
||||
})
|
||||
.catch((err) => {
|
||||
onError('failed to generate type table', err);
|
||||
}),
|
||||
);
|
||||
return 'skip';
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as fs from 'node:fs/promises';
|
||||
import { type GenerateOptions, type Generator } from '@/lib/base';
|
||||
import { join } from 'node:path';
|
||||
import fs from 'node:fs/promises';
|
||||
import type { GenerateOptions, Generator } from '@/lib/base';
|
||||
import path from 'node:path';
|
||||
|
||||
export interface BaseTypeTableProps {
|
||||
/**
|
||||
@@ -49,7 +49,8 @@ export async function getTypeTableOutput(
|
||||
{ name, type, ...props }: BaseTypeTableProps,
|
||||
options?: GenerateTypeTableOptions,
|
||||
) {
|
||||
const file = props.path && options?.basePath ? join(options.basePath, props.path) : props.path;
|
||||
const file =
|
||||
props.path && options?.basePath ? path.join(options.basePath, props.path) : props.path;
|
||||
let typeName = name;
|
||||
let content = '';
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { type Jsx, toJsxRuntime } from 'hast-util-to-jsx-runtime';
|
||||
import * as runtime from 'react/jsx-runtime';
|
||||
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
||||
import 'server-only';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { ComponentProps, ReactNode } from 'react';
|
||||
import { type BaseTypeTableProps, type GenerateTypeTableOptions } from '@/lib/type-table';
|
||||
import { type Generator } from '@/lib/base';
|
||||
import type { Nodes } from 'hast';
|
||||
@@ -11,25 +11,26 @@ import { parseTags } from '@/lib/parse-tags';
|
||||
import type { ResolvedShikiConfig } from 'fumadocs-core/highlight/config';
|
||||
import { markdownRenderer } from '@/markdown';
|
||||
|
||||
interface JSXMarkdownRenderer {
|
||||
renderMarkdown: (md: string) => Promise<ReactNode>;
|
||||
renderType: (type: string) => Promise<ReactNode>;
|
||||
}
|
||||
|
||||
export interface AutoTypeTableProps extends BaseTypeTableProps, Partial<JSXMarkdownRenderer> {
|
||||
export interface AutoTypeTableProps extends BaseTypeTableProps, ComponentProps<'div'> {
|
||||
generator: Generator;
|
||||
|
||||
/** Shiki configuration when using default `renderMarkdown` & `renderType` */
|
||||
shiki?: ResolvedShikiConfig;
|
||||
options?: GenerateTypeTableOptions;
|
||||
|
||||
renderMarkdown?: (md: string) => Promise<ReactNode>;
|
||||
renderType?: (type: string) => Promise<ReactNode>;
|
||||
}
|
||||
|
||||
export async function AutoTypeTable({
|
||||
generator,
|
||||
options = {},
|
||||
options,
|
||||
renderType,
|
||||
renderMarkdown,
|
||||
shiki,
|
||||
name,
|
||||
path,
|
||||
type,
|
||||
...props
|
||||
}: AutoTypeTableProps) {
|
||||
if (!renderType || !renderMarkdown) {
|
||||
@@ -38,7 +39,7 @@ export async function AutoTypeTable({
|
||||
renderMarkdown ??= async (v) => toJsx(await renderer.renderMarkdownToHast(v));
|
||||
}
|
||||
|
||||
const output = await generator.generateTypeTable(props, options);
|
||||
const output = await generator.generateTypeTable({ name, path, type }, options);
|
||||
|
||||
return output.map(async (item) => {
|
||||
const entries = item.entries.map(async (entry): Promise<[string, TypeNode]> => {
|
||||
@@ -73,6 +74,7 @@ export async function AutoTypeTable({
|
||||
key={item.name}
|
||||
id={`type-table-${item.id}`}
|
||||
type={Object.fromEntries(await Promise.all(entries))}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -82,33 +82,6 @@ function _createMdxContent(props) {
|
||||
})
|
||||
}),
|
||||
"required": true
|
||||
},
|
||||
"privateValue": {
|
||||
"type": _jsx(_components.span, {
|
||||
className: "shiki",
|
||||
children: _jsx(_components.code, {
|
||||
children: _jsx(_components.span, {
|
||||
style: {
|
||||
"--shiki-light": "#24292E",
|
||||
"--shiki-dark": "#E1E4E8"
|
||||
},
|
||||
children: "string"
|
||||
})
|
||||
})
|
||||
}),
|
||||
"typeDescription": _jsx(_components.span, {
|
||||
className: "shiki",
|
||||
children: _jsx(_components.code, {
|
||||
children: _jsx(_components.span, {
|
||||
style: {
|
||||
"--shiki-light": "#24292E",
|
||||
"--shiki-dark": "#E1E4E8"
|
||||
},
|
||||
children: "string"
|
||||
})
|
||||
})
|
||||
}),
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -108,20 +108,6 @@
|
||||
"simplifiedType": "timestamp",
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "privateValue",
|
||||
"description": "",
|
||||
"tags": [
|
||||
{
|
||||
"name": "internal",
|
||||
"text": ""
|
||||
}
|
||||
],
|
||||
"type": "string",
|
||||
"simplifiedType": "string",
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { expect, test } from 'vitest';
|
||||
import { createGenerator, type GeneratorOptions } from '@/lib/base';
|
||||
import { createGenerator } from '@/lib/base';
|
||||
import { getSimpleForm } from '@/lib/get-simple-form';
|
||||
import { createProject } from '@/create-project';
|
||||
import { createProject } from '@/lib/base';
|
||||
import { type Node, ts } from 'ts-morph';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'url';
|
||||
@@ -107,13 +107,9 @@ test('interface members', async () => {
|
||||
`);
|
||||
});
|
||||
|
||||
const tsconfig: GeneratorOptions = {
|
||||
const project = await createProject({
|
||||
tsconfigPath: relative('../tsconfig.json'),
|
||||
basePath: relative('../'),
|
||||
cache: false,
|
||||
};
|
||||
|
||||
const project = createProject(tsconfig);
|
||||
});
|
||||
|
||||
function getSimpleForms(fileName: string, sourceCode: string) {
|
||||
const out: string[] = [];
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
createGenerator,
|
||||
type GeneratorOptions,
|
||||
remarkAutoTypeTable,
|
||||
type RemarkAutoTypeTableOptions,
|
||||
} from '../src';
|
||||
import { createGenerator, remarkAutoTypeTable, type RemarkAutoTypeTableOptions } from '../src';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { expect, test } from 'vitest';
|
||||
import * as path from 'node:path';
|
||||
@@ -12,13 +7,10 @@ import { createProcessor } from '@mdx-js/mdx';
|
||||
|
||||
const relative = (s: string): string => path.resolve(fileURLToPath(new URL(s, import.meta.url)));
|
||||
|
||||
const tsconfig: GeneratorOptions = {
|
||||
const generator = createGenerator({
|
||||
tsconfigPath: relative('../tsconfig.json'),
|
||||
basePath: relative('../'),
|
||||
cache: false,
|
||||
};
|
||||
|
||||
const generator = createGenerator(tsconfig);
|
||||
});
|
||||
|
||||
test('Run', async () => {
|
||||
const file = relative('./fixtures/test.ts');
|
||||
|
||||
Generated
+3
-3
@@ -2782,9 +2782,6 @@ importers:
|
||||
remark-rehype:
|
||||
specifier: ^11.1.2
|
||||
version: 11.1.2
|
||||
tinyglobby:
|
||||
specifier: ^0.2.15
|
||||
version: 0.2.15
|
||||
ts-morph:
|
||||
specifier: ^27.0.2
|
||||
version: 27.0.2
|
||||
@@ -2837,6 +2834,9 @@ importers:
|
||||
typescript:
|
||||
specifier: ^5.9.3
|
||||
version: 5.9.3
|
||||
vfile:
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.3
|
||||
|
||||
packages:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user