Core & UI: Move Typescript integrations to fumadocs-typescript

This commit is contained in:
Fuma Nama
2024-03-01 22:04:50 +08:00
parent 3d1b2b2550
commit 321d1e1fba
27 changed files with 252 additions and 51 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-typescript': major
---
Support markdown in type description
+15
View File
@@ -0,0 +1,15 @@
---
'fumadocs-core': major
'fumadocs-ui': major
---
**Move Typescript integrations to `fumadocs-typescript`**
why: It is now a stable feature
migrate: Use `fumadocs-typescript` instead.
```diff
- import { AutoTypeTable } from "fumadocs-ui/components/auto-type-table"
+ import { AutoTypeTable } from "fumadocs-typescript/ui"
```
-1
View File
@@ -346,7 +346,6 @@ function Hero(): JSX.Element {
baseFrequency="0.6"
numOctaves="1"
seed="15"
stitchTiles="stitch"
result="turbulence"
/>
<feComposite in="SourceGraphic" in2="turbulence" operator="in" />
@@ -12,7 +12,7 @@ Your `tsconfig.json` file in the current working directory will be loaded. You m
It accepts a `path` prop which should be a typescript file, and `name` for the exported type name.
```mdx
import { AutoTypeTable } from 'fumadocs-ui/components/auto-type-table';
import { AutoTypeTable } from 'fumadocs-typescript/ui';
<AutoTypeTable path="./path/to/file.ts" name="MyInterface" />
```
+1 -1
View File
@@ -9,7 +9,7 @@ import type { DocsLayoutProps } from 'fumadocs-ui/layout';
import type { AnchorHTMLAttributes, ComponentPropsWithoutRef } from 'react';
import type { DocsPageProps } from 'fumadocs-ui/page';
import type { RootProviderProps } from 'fumadocs-ui/provider';
import type { AutoTypeTable } from 'fumadocs-ui/components/auto-type-table';
import type { AutoTypeTable } from 'fumadocs-typescript/ui';
export type AccordionsProps = Omit<
ComponentPropsWithoutRef<typeof Accordions>,
+1 -1
View File
@@ -11,7 +11,7 @@ import {
} from 'fumadocs-ui/components/codeblock';
import type { ReactNode } from 'react';
import { Popup, PopupContent, PopupTrigger } from 'fumadocs-ui/twoslash/popup';
import { AutoTypeTable } from 'fumadocs-ui/components/auto-type-table';
import { AutoTypeTable } from 'fumadocs-typescript/ui';
import { Wrapper } from '@/components/preview/wrapper';
import { cn } from './utils/cn';
+1
View File
@@ -19,6 +19,7 @@
"fumadocs-core": "workspace:*",
"fumadocs-mdx": "workspace:*",
"fumadocs-twoslash": "workspace:^",
"fumadocs-typescript": "workspace:^",
"fumadocs-ui": "workspace:*",
"geist": "^1.2.0",
"katex": "^0.16.8",
-7
View File
@@ -44,10 +44,6 @@
"import": "./dist/link.js",
"types": "./dist/link.d.ts"
},
"./typescript": {
"import": "./dist/typescript.js",
"types": "./dist/typescript.d.ts"
},
"./middleware": {
"import": "./dist/middleware.js",
"types": "./dist/middleware.d.ts"
@@ -76,9 +72,6 @@
"toc": [
"./dist/toc.d.ts"
],
"typescript": [
"./dist/typescript.d.ts"
],
"search/client": [
"./dist/search/client.d.ts"
],
+2 -7
View File
@@ -1,12 +1,7 @@
import { defineConfig } from 'tsup';
export default defineConfig({
external: [
'@algolia/client-search',
'algoliasearch',
'unified',
'typescript',
],
external: ['@algolia/client-search', 'algoliasearch', 'unified'],
dts: true,
target: 'es6',
format: 'esm',
@@ -16,6 +11,6 @@ export default defineConfig({
'src/{search,search-algolia}/client.ts',
'src/search/shared.ts',
'src/{search,search-algolia}/server.ts',
'src/{middleware,typescript}.ts',
'src/middleware.ts',
],
});
+1 -1
View File
@@ -5,7 +5,7 @@ A CLI tool to create new Next.js documentation sites with Fumadocs.
```bash
npx create-fumadocs-app
#or
pnpx create-fumadocs-app
pnpm create fumadocs-app
#or
yarn create fumadocs-app
```
+4
View File
@@ -0,0 +1,4 @@
module.exports = {
extends: ['custom/library'],
ignorePatterns: ['*.test.ts'],
};
+3
View File
@@ -0,0 +1,3 @@
# Fumadocs Typescript
Typescript Integration for Fumadocs.
+65
View File
@@ -0,0 +1,65 @@
{
"name": "fumadocs-typescript",
"version": "0.0.0",
"description": "Typescript Integration for Fumadocs",
"keywords": [
"NextJs",
"fumadocs",
"Docs"
],
"homepage": "https://fumadocs.vercel.app",
"repository": "github:fuma-nama/fumadocs",
"license": "MIT",
"author": "Fuma Nama",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./ui": {
"import": "./dist/ui/index.js",
"types": "./dist/ui/index.d.ts"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"typesVersions": {
"*": {
"ui": [
"./dist/ui/index.d.ts"
]
}
},
"files": [
"dist/*"
],
"scripts": {
"build": "tsup",
"clean": "rimraf dist",
"dev": "tsup --watch",
"lint": "eslint .",
"types:check": "tsc --noEmit"
},
"dependencies": {
"hast-util-to-jsx-runtime": "^2.3.0",
"mdast-util-from-markdown": "^2.0.0",
"mdast-util-gfm": "^3.0.0",
"mdast-util-to-hast": "^13.1.0"
},
"devDependencies": {
"@types/hast": "^3.0.4",
"@types/mdast": "^4.0.3",
"@types/react": "18.2.0",
"@types/react-dom": "18.2.1",
"eslint-config-custom": "workspace:*",
"fumadocs-ui": "workspace:*",
"tsconfig": "workspace:*"
},
"peerDependencies": {
"typescript": "*"
},
"publishConfig": {
"access": "public"
}
}
@@ -81,8 +81,9 @@ function getExportedSymbol({
const fileSymbol = checker.getSymbolAtLocation(sourceFile);
if (!fileSymbol) return;
const exports = checker.getExportsOfModule(fileSymbol);
return exports.find((e) => e.getEscapedName().toString() === name);
return checker
.getExportsOfModule(fileSymbol)
.find((e) => e.getEscapedName().toString() === name);
}
/**
+1
View File
@@ -0,0 +1 @@
export * from './generate';
+31
View File
@@ -0,0 +1,31 @@
import { fromMarkdown } from 'mdast-util-from-markdown';
import { gfmFromMarkdown } from 'mdast-util-gfm';
import { toHast } from 'mdast-util-to-hast';
import {
type Jsx,
type Fragment,
toJsxRuntime,
} from 'hast-util-to-jsx-runtime';
import * as runtime from 'react/jsx-runtime';
declare module 'react/jsx-runtime' {
export const Fragment: Fragment;
export const jsx: Jsx;
export const jsxs: Jsx;
}
/**
* @returns html
*/
export function renderMarkdown(md: string): JSX.Element {
const mdast = fromMarkdown(
md.replace(/{@link (?<link>[^}]*)}/g, '$1'), // replace jsdoc links
{ mdastExtensions: [gfmFromMarkdown()] },
);
return toJsxRuntime(toHast(mdast), {
Fragment: runtime.Fragment,
jsx: runtime.jsx,
jsxs: runtime.jsxs,
});
}
@@ -1,8 +1,9 @@
import { Options, generateDocumentation } from 'fumadocs-core/typescript';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { renderMarkdown } from '@/markdown';
import type { Options } from '../generate';
import { generateDocumentation } from '../generate';
import 'server-only';
declare const { TypeTable }: typeof import('./type-table');
/**
* **Server Component Only**
*
@@ -26,7 +27,7 @@ export function AutoTypeTable({
entry.name,
{
type: entry.type,
description: entry.description,
description: renderMarkdown(entry.description),
default: entry.default,
},
]),
+1
View File
@@ -0,0 +1 @@
export * from './auto-type-table';
@@ -31,15 +31,25 @@
}
],
[
{
"name": "file",
"description": "",
"type": "string"
},
{
"name": "name",
"description": "",
"type": "string"
},
{
"name": "url",
"name": "transform",
"description": "Modify output property entry",
"type": "(this: EntryContext, entry: DocEntry, propertyType: Type, propertySymbol: Symbol) => void"
},
{
"name": "options",
"description": "",
"type": "string"
"type": "Partial<{ files: string[]; tsconfigPath: string; basePath: string; }>"
}
]
]
@@ -10,7 +10,7 @@ export type Test2 = Test1 & {
generic: GenericType<string, string, string>;
};
export type { BreadcrumbItem as Test3 } from '@/breadcrumb';
export type { Options as Test3 } from '../../src/generate';
interface GenericType<A, B, C> {
A: A;
@@ -1,4 +1,4 @@
import { generateDocumentation } from '../src/typescript';
import { generateDocumentation } from '../src/generate';
import { fileURLToPath } from 'url';
import { afterEach, describe, expect, test, vi } from 'vitest';
import path from 'node:path';
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "tsconfig/react-library.json",
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["./src/**/*"],
"exclude": ["node_modules", "dist"]
}
+9
View File
@@ -0,0 +1,9 @@
import { defineConfig } from 'tsup';
export default defineConfig({
external: ['server-only', 'fumadocs-ui', 'react'],
dts: true,
target: 'es6',
format: 'esm',
entry: ['src/index.ts', 'src/ui/index.ts'],
});
+9
View File
@@ -0,0 +1,9 @@
import { defineProject } from 'vitest/config';
export default defineProject({
resolve: {
alias: {
'@/': new URL('./src/', import.meta.url).pathname,
},
},
});
+23 -20
View File
@@ -3,6 +3,7 @@
import { InfoIcon } from 'lucide-react';
import Link from 'next/link';
import type { ReactNode } from 'react';
import { cva } from 'class-variance-authority';
import { cn } from '@/utils/cn';
import {
Popover,
@@ -16,7 +17,7 @@ export function Info({ children }: { children: ReactNode }): JSX.Element {
<PopoverTrigger>
<InfoIcon className="size-4" />
</PopoverTrigger>
<PopoverContent className="text-sm">{children}</PopoverContent>
<PopoverContent className="prose text-sm">{children}</PopoverContent>
</Popover>
);
}
@@ -25,7 +26,7 @@ interface ObjectType {
/**
* Additional description of the field
*/
description?: string;
description?: ReactNode;
type: string;
typeDescription?: string;
/**
@@ -35,40 +36,42 @@ interface ObjectType {
default?: string;
}
const th = cva('p-2 font-medium first:pl-0 last:pr-0');
const td = cva('p-2 first:pl-0 last:pr-0');
const field = cva('inline-flex flex-row items-center gap-1');
const code = cva('rounded-md bg-secondary p-1 text-secondary-foreground', {
variants: {
color: { primary: 'bg-primary/10 text-primary' },
},
});
export function TypeTable({
type,
}: {
type: Record<string, ObjectType>;
}): JSX.Element {
const th = cn('p-2 font-medium first:pl-0 last:pr-0');
const td = cn('p-2 first:pl-0 last:pr-0');
const field = cn('inline-flex flex-row items-center gap-1');
const code = cn('rounded-md bg-secondary p-1 text-secondary-foreground');
return (
<div className="not-prose overflow-auto whitespace-nowrap">
<table className="my-4 w-full text-left text-sm text-muted-foreground">
<thead className="border-b">
<tr>
<th className={cn(th, 'w-[45%]')}>Prop</th>
<th className={cn(th, 'w-[30%]')}>Type</th>
<th className={cn(th, 'w-[25%]')}>Default</th>
<th className={cn(th(), 'w-[45%]')}>Prop</th>
<th className={cn(th(), 'w-[30%]')}>Type</th>
<th className={cn(th(), 'w-[25%]')}>Default</th>
</tr>
</thead>
<tbody className="border-collapse divide-y divide-border">
{Object.entries(type).map(([key, value]) => (
<tr key={key}>
<td className={td}>
<div className={field}>
<code className={cn(code, 'bg-primary/10 text-primary')}>
{key}
</code>
<td className={td()}>
<div className={field()}>
<code className={cn(code({ color: 'primary' }))}>{key}</code>
{value.description ? <Info>{value.description}</Info> : null}
</div>
</td>
<td className={td}>
<div className={field}>
<code className={code}>{value.type}</code>
<td className={td()}>
<div className={field()}>
<code className={code()}>{value.type}</code>
{value.typeDescription ? (
<Info>
<pre className="overflow-auto bg-secondary text-secondary-foreground">
@@ -83,9 +86,9 @@ export function TypeTable({
) : null}
</div>
</td>
<td className={td}>
<td className={td()}>
{value.default ? (
<code className={code}>{value.default}</code>
<code className={code()}>{value.default}</code>
) : (
<span>-</span>
)}
-2
View File
@@ -17,14 +17,12 @@ const exportedComponents = [
'card',
'heading',
'codeblock',
'auto-type-table',
'dialog/search',
'dialog/search-default',
'dialog/search-algolia',
];
const injectImports = {
'./src/components/auto-type-table.tsx': './src/components/type-table.tsx',
'./src/page.tsx': './src/page.client.tsx',
'./src/mdx.tsx': './src/mdx.client.tsx',
'./src/layout.tsx': './src/layout.client.tsx',
+47
View File
@@ -73,6 +73,9 @@ importers:
fumadocs-twoslash:
specifier: workspace:^
version: link:../../packages/twoslash
fumadocs-typescript:
specifier: workspace:^
version: link:../../packages/typescript
fumadocs-ui:
specifier: workspace:*
version: link:../../packages/ui
@@ -526,6 +529,46 @@ importers:
specifier: workspace:*
version: link:../tsconfig
packages/typescript:
dependencies:
hast-util-to-jsx-runtime:
specifier: ^2.3.0
version: 2.3.0
mdast-util-from-markdown:
specifier: ^2.0.0
version: 2.0.0
mdast-util-gfm:
specifier: ^3.0.0
version: 3.0.0
mdast-util-to-hast:
specifier: ^13.1.0
version: 13.1.0
typescript:
specifier: '*'
version: 5.3.3
devDependencies:
'@types/hast':
specifier: ^3.0.4
version: 3.0.4
'@types/mdast':
specifier: ^4.0.3
version: 4.0.3
'@types/react':
specifier: 18.2.0
version: 18.2.0
'@types/react-dom':
specifier: 18.2.1
version: 18.2.1
eslint-config-custom:
specifier: workspace:*
version: link:../eslint-config-custom
fumadocs-ui:
specifier: workspace:*
version: link:../ui
tsconfig:
specifier: workspace:*
version: link:../tsconfig
packages/ui:
dependencies:
'@radix-ui/react-accordion':
@@ -1251,6 +1294,10 @@ packages:
peerDependencies:
'@effect-ts/otel-node': '*'
peerDependenciesMeta:
'@effect-ts/core':
optional: true
'@effect-ts/otel':
optional: true
'@effect-ts/otel-node':
optional: true
dependencies: