@windrun-huaiin/third-ui 20.1.0 → 22.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.
- package/LICENSE +1 -1
- package/dist/ai/ai-markdown.js +1 -1
- package/dist/ai/ai-markdown.mjs +1 -1
- package/dist/clerk/clerk-page-context-generator.js +3 -2
- package/dist/clerk/clerk-page-context-generator.mjs +3 -2
- package/dist/clerk/clerk-page-generator.d.ts +0 -8
- package/dist/clerk/clerk-page-generator.js +4 -3
- package/dist/clerk/clerk-page-generator.mjs +4 -3
- package/dist/fuma/base/custom-header.d.ts +1 -1
- package/dist/fuma/base/custom-header.js +38 -36
- package/dist/fuma/base/custom-header.mjs +25 -23
- package/dist/fuma/base/custom-home-layout.d.ts +1 -1
- package/dist/fuma/base/custom-home-layout.js +1 -1
- package/dist/fuma/base/custom-home-layout.mjs +1 -1
- package/dist/fuma/base/header-theme-switch.d.ts +5 -0
- package/dist/fuma/base/header-theme-switch.js +42 -0
- package/dist/fuma/base/header-theme-switch.mjs +40 -0
- package/dist/fuma/base/index.d.ts +1 -0
- package/dist/fuma/base/index.js +7 -0
- package/dist/fuma/base/index.mjs +1 -0
- package/dist/fuma/base/site-layout.d.ts +116 -0
- package/dist/fuma/base/site-layout.js +72 -0
- package/dist/fuma/base/site-layout.mjs +65 -0
- package/dist/fuma/fuma-banner-suit.js +9 -6
- package/dist/fuma/fuma-banner-suit.mjs +10 -7
- package/dist/fuma/fuma-page-genarator.d.ts +2 -2
- package/dist/fuma/fuma-page-genarator.js +21 -8
- package/dist/fuma/fuma-page-genarator.mjs +21 -8
- package/dist/fuma/heavy/image-grid.d.ts +6 -0
- package/dist/fuma/heavy/image-grid.js +17 -0
- package/dist/fuma/heavy/image-grid.mjs +15 -0
- package/dist/fuma/heavy/image-zoom.d.ts +22 -0
- package/dist/fuma/heavy/image-zoom.js +39 -0
- package/dist/fuma/heavy/image-zoom.mjs +37 -0
- package/dist/fuma/heavy/index.d.ts +4 -0
- package/dist/fuma/heavy/index.js +15 -0
- package/dist/fuma/heavy/index.mjs +5 -0
- package/dist/fuma/heavy/math.d.ts +17 -0
- package/dist/fuma/heavy/math.js +60 -0
- package/dist/fuma/heavy/math.mjs +57 -0
- package/dist/fuma/heavy/mermaid.d.ts +13 -0
- package/dist/fuma/heavy/mermaid.js +360 -0
- package/dist/fuma/heavy/mermaid.mjs +358 -0
- package/dist/fuma/llm-copy-handler.js +3 -2
- package/dist/fuma/llm-copy-handler.mjs +3 -2
- package/dist/fuma/mdx/features.d.ts +8 -0
- package/dist/fuma/mdx/features.js +92 -0
- package/dist/fuma/mdx/features.mjs +85 -0
- package/dist/fuma/mdx/index.d.ts +0 -4
- package/dist/fuma/mdx/index.js +0 -8
- package/dist/fuma/mdx/index.mjs +0 -4
- package/dist/fuma/mdx/markdown-component-map.js +7 -1
- package/dist/fuma/mdx/markdown-component-map.mjs +7 -1
- package/dist/fuma/mdx/math.d.ts +17 -0
- package/dist/fuma/mdx/math.js +60 -0
- package/dist/fuma/mdx/math.mjs +57 -0
- package/dist/fuma/mdx/site-mdx-components.d.ts +13 -0
- package/dist/fuma/mdx/site-mdx-components.js +19 -0
- package/dist/fuma/mdx/site-mdx-components.mjs +17 -0
- package/dist/fuma/mdx/site-mdx-presets.d.ts +13 -0
- package/dist/fuma/mdx/site-mdx-presets.js +49 -0
- package/dist/fuma/mdx/site-mdx-presets.mjs +45 -0
- package/dist/fuma/mdx/toc-clerk-portable.js +9 -5
- package/dist/fuma/mdx/toc-clerk-portable.mjs +8 -4
- package/dist/fuma/mdx/zia-card.js +1 -1
- package/dist/fuma/mdx/zia-card.mjs +1 -1
- package/dist/fuma/mdx/zia-file.js +1 -0
- package/dist/fuma/mdx/zia-file.mjs +1 -0
- package/dist/fuma/server/optional-features.d.ts +8 -0
- package/dist/fuma/server/optional-features.js +111 -0
- package/dist/fuma/server/optional-features.mjs +104 -0
- package/dist/fuma/server/site-mdx-components.d.ts +13 -0
- package/dist/fuma/server/site-mdx-components.js +19 -0
- package/dist/fuma/server/site-mdx-components.mjs +17 -0
- package/dist/fuma/server/site-mdx-presets.d.ts +194 -0
- package/dist/fuma/server/site-mdx-presets.js +46 -0
- package/dist/fuma/server/site-mdx-presets.mjs +42 -0
- package/dist/fuma/share/index.d.ts +1 -0
- package/dist/fuma/share/index.js +7 -0
- package/dist/fuma/share/index.mjs +1 -0
- package/dist/fuma/share/markdown-component-map.d.ts +3 -0
- package/dist/fuma/share/markdown-component-map.js +79 -0
- package/dist/fuma/share/markdown-component-map.mjs +77 -0
- package/dist/lib/fuma-schema-check-util.js +19 -5
- package/dist/lib/fuma-schema-check-util.mjs +19 -5
- package/dist/lib/seo-metadata.d.ts +10 -0
- package/dist/main/x-button.js +2 -2
- package/dist/main/x-button.mjs +2 -2
- package/package.json +31 -8
- package/src/ai/ai-markdown.tsx +1 -1
- package/src/clerk/clerk-page-context-generator.tsx +6 -3
- package/src/clerk/clerk-page-generator.tsx +7 -13
- package/src/fuma/base/custom-header.tsx +32 -35
- package/src/fuma/base/custom-home-layout.tsx +2 -2
- package/src/fuma/base/header-theme-switch.tsx +88 -0
- package/src/fuma/base/index.ts +1 -0
- package/src/fuma/base/site-layout.tsx +289 -0
- package/src/fuma/fuma-banner-suit.tsx +30 -28
- package/src/fuma/fuma-page-genarator.tsx +27 -10
- package/src/fuma/{mdx → heavy}/image-grid.tsx +1 -1
- package/src/fuma/heavy/index.ts +7 -0
- package/src/fuma/heavy/math.tsx +130 -0
- package/src/fuma/llm-copy-handler.ts +3 -3
- package/src/fuma/mdx/index.ts +0 -4
- package/src/fuma/mdx/toc-clerk-portable.tsx +27 -24
- package/src/fuma/mdx/zia-card.tsx +1 -0
- package/src/fuma/mdx/zia-file.tsx +3 -1
- package/src/fuma/server/optional-features.tsx +168 -0
- package/src/fuma/server/site-mdx-components.tsx +48 -0
- package/src/fuma/server/site-mdx-presets.ts +80 -0
- package/src/fuma/share/index.ts +1 -0
- package/src/fuma/{mdx → share}/markdown-component-map.tsx +1 -1
- package/src/lib/fuma-schema-check-util.ts +22 -6
- package/src/lib/seo-metadata.ts +47 -0
- package/src/main/language-detector.tsx +0 -8
- package/src/main/x-button.tsx +2 -2
- package/src/styles/fuma.css +3 -7
- package/src/styles/third-ui.css +0 -4
- package/dist/main/ads-alert-dialog.d.ts +0 -15
- package/dist/main/ads-alert-dialog.js +0 -21
- package/dist/main/ads-alert-dialog.mjs +0 -19
- /package/src/fuma/{mdx → heavy}/image-zoom.tsx +0 -0
- /package/src/fuma/{mdx → heavy}/mermaid.tsx +0 -0
|
@@ -13,7 +13,7 @@ interface FumaPageParams {
|
|
|
13
13
|
/*
|
|
14
14
|
* The source of the mdx content
|
|
15
15
|
*/
|
|
16
|
-
mdxContentSource: any;
|
|
16
|
+
mdxContentSource: any | (() => Promise<any>);
|
|
17
17
|
/*
|
|
18
18
|
* The mdx components handler, refer to fumadocs
|
|
19
19
|
*/
|
|
@@ -81,11 +81,20 @@ export function createFumaPage({
|
|
|
81
81
|
localePrefixAsNeeded = true,
|
|
82
82
|
defaultLocale = 'en',
|
|
83
83
|
}: FumaPageParams) {
|
|
84
|
+
const getSource = async () => {
|
|
85
|
+
if (typeof mdxContentSource === 'function') {
|
|
86
|
+
return await mdxContentSource();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return mdxContentSource;
|
|
90
|
+
};
|
|
91
|
+
|
|
84
92
|
const Page = async function Page({ params }: { params: Promise<{ locale: string; slug?: string[] }> }) {
|
|
85
93
|
const { slug, locale } = await params;
|
|
86
|
-
const
|
|
94
|
+
const source = await getSource();
|
|
95
|
+
const page = source.getPage(slug, locale);
|
|
87
96
|
if (!page) {
|
|
88
|
-
console.log('[FumaPage] missing page', { slug, locale, available:
|
|
97
|
+
console.log('[FumaPage] missing page', { slug, locale, available: source.pageTree?.[locale]?.children?.map((c: any) => c.url) });
|
|
89
98
|
return <FallbackPage siteIcon={siteIcon} />;
|
|
90
99
|
}
|
|
91
100
|
|
|
@@ -103,7 +112,14 @@ export function createFumaPage({
|
|
|
103
112
|
/>
|
|
104
113
|
);
|
|
105
114
|
|
|
106
|
-
const
|
|
115
|
+
const content =
|
|
116
|
+
typeof page.data.load === 'function'
|
|
117
|
+
? await page.data.load(getMDXComponents())
|
|
118
|
+
: {
|
|
119
|
+
body: await page.data.body({ components: getMDXComponents() }),
|
|
120
|
+
toc: page.data.toc ?? [],
|
|
121
|
+
};
|
|
122
|
+
|
|
107
123
|
return (
|
|
108
124
|
<DocsPage
|
|
109
125
|
breadcrumb={{enabled: showBreadcrumb}}
|
|
@@ -112,7 +128,7 @@ export function createFumaPage({
|
|
|
112
128
|
single: false,
|
|
113
129
|
component: (
|
|
114
130
|
<PortableClerkTOC
|
|
115
|
-
toc={
|
|
131
|
+
toc={content.toc}
|
|
116
132
|
footer={tocFooterElement}
|
|
117
133
|
/>
|
|
118
134
|
),
|
|
@@ -120,25 +136,26 @@ export function createFumaPage({
|
|
|
120
136
|
tableOfContentPopover={{
|
|
121
137
|
enabled: false,
|
|
122
138
|
}}
|
|
123
|
-
toc={
|
|
124
|
-
|
|
139
|
+
toc={content.toc}
|
|
140
|
+
className="max-sm:pb-16"
|
|
125
141
|
>
|
|
126
142
|
<DocsTitle>{page.data.title}</DocsTitle>
|
|
127
143
|
<DocsDescription className="mb-2">{page.data.description}</DocsDescription>
|
|
128
144
|
<DocsBody className="text-fd-foreground/80">
|
|
129
|
-
|
|
145
|
+
{content.body}
|
|
130
146
|
</DocsBody>
|
|
131
147
|
</DocsPage>
|
|
132
148
|
);
|
|
133
149
|
};
|
|
134
150
|
|
|
135
151
|
function generateStaticParams() {
|
|
136
|
-
return
|
|
152
|
+
return getSource().then((source) => source.generateParams('slug', 'locale'));
|
|
137
153
|
}
|
|
138
154
|
|
|
139
155
|
async function generateMetadata(props: { params: Promise<{ slug?: string[]; locale?: string }> }) {
|
|
140
156
|
const { slug, locale } = await props.params;
|
|
141
|
-
const
|
|
157
|
+
const source = await getSource();
|
|
158
|
+
const page = source.getPage(slug, locale);
|
|
142
159
|
if (!page) {
|
|
143
160
|
return {
|
|
144
161
|
title: '404 - Page Not Found',
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import katex from 'katex';
|
|
2
|
+
import { cn } from '@windrun-huaiin/lib/utils';
|
|
3
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
type MathSourceProps = {
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
math?: string;
|
|
8
|
+
formula?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type Align = 'left' | 'center' | 'right';
|
|
12
|
+
|
|
13
|
+
export type MathBlockProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'> &
|
|
14
|
+
MathSourceProps & {
|
|
15
|
+
title?: ReactNode;
|
|
16
|
+
titleAlign?: Align;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type InlineMathProps = Omit<HTMLAttributes<HTMLSpanElement>, 'children'> &
|
|
20
|
+
MathSourceProps & {
|
|
21
|
+
align?: Align;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const alignClassMap: Record<Align, string> = {
|
|
25
|
+
left: 'text-left justify-start',
|
|
26
|
+
center: 'text-center justify-center',
|
|
27
|
+
right: 'text-right justify-end',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const textAlignClassMap: Record<Align, string> = {
|
|
31
|
+
left: 'text-left',
|
|
32
|
+
center: 'text-center',
|
|
33
|
+
right: 'text-right',
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function getMathSource({ children, math, formula }: MathSourceProps): string {
|
|
37
|
+
if (typeof math === 'string' && math.trim() !== '') return math.trim();
|
|
38
|
+
if (typeof formula === 'string' && formula.trim() !== '') return formula.trim();
|
|
39
|
+
if (typeof children === 'string' && children.trim() !== '') return children.trim();
|
|
40
|
+
|
|
41
|
+
if (Array.isArray(children)) {
|
|
42
|
+
const text = children
|
|
43
|
+
.map((item) => (typeof item === 'string' ? item : ''))
|
|
44
|
+
.join('')
|
|
45
|
+
.trim();
|
|
46
|
+
|
|
47
|
+
if (text !== '') return text;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return '';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function renderMath(source: string, displayMode: boolean) {
|
|
54
|
+
if (source === '') return '';
|
|
55
|
+
|
|
56
|
+
return katex.renderToString(source, {
|
|
57
|
+
displayMode,
|
|
58
|
+
throwOnError: false,
|
|
59
|
+
output: 'html',
|
|
60
|
+
strict: 'ignore',
|
|
61
|
+
trust: false,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function MathBlock({
|
|
66
|
+
title,
|
|
67
|
+
titleAlign = 'center',
|
|
68
|
+
children,
|
|
69
|
+
math,
|
|
70
|
+
formula,
|
|
71
|
+
className,
|
|
72
|
+
...props
|
|
73
|
+
}: MathBlockProps) {
|
|
74
|
+
const source = getMathSource({ children, math, formula });
|
|
75
|
+
const html = renderMath(source, true);
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<div
|
|
79
|
+
{...props}
|
|
80
|
+
className={cn(
|
|
81
|
+
'not-prose my-6 overflow-x-auto rounded-xl border bg-fd-card p-4 text-fd-card-foreground',
|
|
82
|
+
className,
|
|
83
|
+
)}
|
|
84
|
+
>
|
|
85
|
+
{title ? (
|
|
86
|
+
<div
|
|
87
|
+
className={cn(
|
|
88
|
+
'mb-3 text-sm font-medium text-fd-muted-foreground',
|
|
89
|
+
alignClassMap[titleAlign].split(' ')[0],
|
|
90
|
+
)}
|
|
91
|
+
>
|
|
92
|
+
{title}
|
|
93
|
+
</div>
|
|
94
|
+
) : null}
|
|
95
|
+
{html ? (
|
|
96
|
+
<div
|
|
97
|
+
className="min-w-fit [&_.katex-display]:my-0 [&_.katex-display]:overflow-x-auto [&_.katex-display]:overflow-y-hidden"
|
|
98
|
+
dangerouslySetInnerHTML={{ __html: html }}
|
|
99
|
+
/>
|
|
100
|
+
) : (
|
|
101
|
+
<div className="text-sm text-fd-muted-foreground">Empty math block.</div>
|
|
102
|
+
)}
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function InlineMath({
|
|
108
|
+
children,
|
|
109
|
+
math,
|
|
110
|
+
formula,
|
|
111
|
+
align = 'center',
|
|
112
|
+
className,
|
|
113
|
+
...props
|
|
114
|
+
}: InlineMathProps) {
|
|
115
|
+
const source = getMathSource({ children, math, formula });
|
|
116
|
+
const html = renderMath(source, false);
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<span
|
|
120
|
+
{...props}
|
|
121
|
+
className={cn(
|
|
122
|
+
'mx-1 inline-flex max-w-full align-middle rounded-md bg-neutral-200 px-2 py-0.5 text-sm leading-none dark:bg-white/20 [&_.katex]:text-inherit',
|
|
123
|
+
textAlignClassMap[align],
|
|
124
|
+
className,
|
|
125
|
+
)}
|
|
126
|
+
>
|
|
127
|
+
<span dangerouslySetInnerHTML={{ __html: html }} />
|
|
128
|
+
</span>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
@@ -42,8 +42,8 @@ export async function LLMCopyHandler(options: LLMCopyHandlerOptions): Promise<{
|
|
|
42
42
|
return { error: 'Page file path information missing', status: 500 };
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
const title = page.title;
|
|
46
|
-
const description = page.description;
|
|
45
|
+
const title = page.data?.title ?? page.title;
|
|
46
|
+
const description = page.data?.description ?? page.description;
|
|
47
47
|
const relativeMdxFilePath = page.path;
|
|
48
48
|
const absoluteFilePath = nodePath.join(process.cwd(), sourceDir, relativeMdxFilePath);
|
|
49
49
|
console.log(`[LLMCopy] Attempting to read MDX content from: ${absoluteFilePath}`);
|
|
@@ -90,4 +90,4 @@ export async function LLMCopyHandler(options: LLMCopyHandlerOptions): Promise<{
|
|
|
90
90
|
console.error('[LLMCopy] General Error object details:', JSON.stringify(error, Object.getOwnPropertyNames(error), 2));
|
|
91
91
|
return { error: 'Internal Server Error', status: 500 };
|
|
92
92
|
}
|
|
93
|
-
}
|
|
93
|
+
}
|
package/src/fuma/mdx/index.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
export * from './mermaid';
|
|
4
|
-
export * from './image-zoom';
|
|
5
3
|
export * from './trophy-card';
|
|
6
|
-
export * from './image-grid';
|
|
7
4
|
export * from './zia-card';
|
|
8
5
|
export * from './gradient-button';
|
|
9
6
|
export * from './toc-base';
|
|
@@ -13,4 +10,3 @@ export * from './toc-footer-wrapper';
|
|
|
13
10
|
export * from './toc-clerk-portable';
|
|
14
11
|
export * from './banner';
|
|
15
12
|
export * from './suno-embed';
|
|
16
|
-
export * from './markdown-component-map';
|
|
@@ -6,12 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import * as Primitive from 'fumadocs-core/toc';
|
|
8
8
|
import {
|
|
9
|
-
PageTOC,
|
|
10
|
-
PageTOCPopover,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} from 'fumadocs-ui/layouts/docs/page';
|
|
9
|
+
TOC as PageTOC,
|
|
10
|
+
TOCPopover as PageTOCPopover,
|
|
11
|
+
type TOCProps as PageTOCProps,
|
|
12
|
+
type TOCPopoverProps as PageTOCPopoverProps,
|
|
13
|
+
} from 'fumadocs-ui/layouts/docs/page/slots/toc';
|
|
15
14
|
import {
|
|
16
15
|
type ComponentProps,
|
|
17
16
|
type ReactNode,
|
|
@@ -85,14 +84,20 @@ export function PortableClerkTOC({
|
|
|
85
84
|
className,
|
|
86
85
|
}: PortableClerkTOCProps) {
|
|
87
86
|
return (
|
|
88
|
-
<PageTOC
|
|
89
|
-
|
|
90
|
-
{
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
87
|
+
<PageTOC
|
|
88
|
+
style="clerk"
|
|
89
|
+
container={{ className }}
|
|
90
|
+
header={
|
|
91
|
+
<>
|
|
92
|
+
{header}
|
|
93
|
+
{title ?? null}
|
|
94
|
+
</>
|
|
95
|
+
}
|
|
96
|
+
footer={footer}
|
|
97
|
+
list={{
|
|
98
|
+
children: <PortableClerkTOCItems toc={toc} emptyLabel={emptyLabel} />,
|
|
99
|
+
} as PageTOCProps['list']}
|
|
100
|
+
/>
|
|
96
101
|
);
|
|
97
102
|
}
|
|
98
103
|
|
|
@@ -103,16 +108,14 @@ export function PortableClerkTOCPopover({
|
|
|
103
108
|
emptyLabel = 'No headings',
|
|
104
109
|
}: Omit<PortableClerkTOCProps, 'title' | 'className'>) {
|
|
105
110
|
return (
|
|
106
|
-
<PageTOCPopover
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
</PageTOCPopoverContent>
|
|
115
|
-
</PageTOCPopover>
|
|
111
|
+
<PageTOCPopover
|
|
112
|
+
style="clerk"
|
|
113
|
+
header={header}
|
|
114
|
+
footer={footer}
|
|
115
|
+
list={{
|
|
116
|
+
children: <PortableClerkTOCItems toc={toc} emptyLabel={emptyLabel} />,
|
|
117
|
+
} as PageTOCPopoverProps['list']}
|
|
118
|
+
/>
|
|
116
119
|
);
|
|
117
120
|
}
|
|
118
121
|
|
|
@@ -22,6 +22,7 @@ export function ZiaCard({ icon, title, description, ...props }: ZiaCardProps) {
|
|
|
22
22
|
return (
|
|
23
23
|
<Link
|
|
24
24
|
href={props.href!}
|
|
25
|
+
prefetch={false}
|
|
25
26
|
data-card
|
|
26
27
|
className={cn(
|
|
27
28
|
'block rounded-lg border bg-fd-card p-4 text-fd-card-foreground shadow-md transition-colors @max-lg:col-span-full',
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
1
3
|
import { FileIcon, FolderOpenIcon, FolderIcon } from '@windrun-huaiin/base-ui/icons';
|
|
2
4
|
import { type HTMLAttributes, type ReactNode, useState } from 'react';
|
|
3
5
|
import { cn } from '@windrun-huaiin/lib/utils';
|
|
@@ -81,4 +83,4 @@ export function ZiaFolder({
|
|
|
81
83
|
</CollapsibleContent>
|
|
82
84
|
</Collapsible>
|
|
83
85
|
);
|
|
84
|
-
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import type { MDXComponents, MDXProps } from 'mdx/types';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import { CodeBlock, Pre } from 'fumadocs-ui/components/codeblock';
|
|
4
|
+
import { TypeTable } from 'fumadocs-ui/components/type-table';
|
|
5
|
+
import {
|
|
6
|
+
CSSIcon,
|
|
7
|
+
CSVIcon,
|
|
8
|
+
DiffIcon,
|
|
9
|
+
HtmlIcon,
|
|
10
|
+
HttpIcon,
|
|
11
|
+
JavaIcon,
|
|
12
|
+
JsonIcon,
|
|
13
|
+
LogIcon,
|
|
14
|
+
MDXIcon,
|
|
15
|
+
RegexIcon,
|
|
16
|
+
SQLIcon,
|
|
17
|
+
SchemeIcon,
|
|
18
|
+
SquareDashedBottomCodeIcon,
|
|
19
|
+
TxtIcon,
|
|
20
|
+
XMLIcon,
|
|
21
|
+
YamlIcon,
|
|
22
|
+
} from '@windrun-huaiin/base-ui/icons';
|
|
23
|
+
import { baseMarkdownComponents } from '../share/markdown-component-map';
|
|
24
|
+
import { Mermaid, ImageGrid, ImageZoom, MathBlock, InlineMath } from '../heavy';
|
|
25
|
+
import { TrophyCard } from '../mdx/trophy-card';
|
|
26
|
+
import { ZiaCard } from '../mdx/zia-card';
|
|
27
|
+
import { GradientButton } from '../mdx/gradient-button';
|
|
28
|
+
import { ZiaFile, ZiaFolder } from '../mdx/zia-file';
|
|
29
|
+
import { SunoEmbed } from '../mdx/suno-embed';
|
|
30
|
+
|
|
31
|
+
const defaultCodeLanguageIconMap: Record<string, ReactNode> = {
|
|
32
|
+
css: <CSSIcon />,
|
|
33
|
+
csv: <CSVIcon />,
|
|
34
|
+
diff: <DiffIcon />,
|
|
35
|
+
html: <HtmlIcon />,
|
|
36
|
+
http: <HttpIcon />,
|
|
37
|
+
java: <JavaIcon />,
|
|
38
|
+
json: <JsonIcon />,
|
|
39
|
+
jsonc: <SquareDashedBottomCodeIcon />,
|
|
40
|
+
log: <LogIcon />,
|
|
41
|
+
mdx: <MDXIcon />,
|
|
42
|
+
plaintext: <TxtIcon />,
|
|
43
|
+
regex: <RegexIcon />,
|
|
44
|
+
scheme: <SchemeIcon />,
|
|
45
|
+
sql: <SQLIcon />,
|
|
46
|
+
text: <TxtIcon />,
|
|
47
|
+
txt: <TxtIcon />,
|
|
48
|
+
xml: <XMLIcon />,
|
|
49
|
+
yaml: <YamlIcon />,
|
|
50
|
+
yml: <YamlIcon />,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function tryToMatchIcon(
|
|
54
|
+
props: Readonly<MDXProps & { 'data-language'?: string; title?: string }>,
|
|
55
|
+
iconMap: Record<string, ReactNode>,
|
|
56
|
+
): ReactNode | undefined {
|
|
57
|
+
let lang: string | undefined;
|
|
58
|
+
|
|
59
|
+
const dataLanguage = props['data-language'] as string | undefined;
|
|
60
|
+
|
|
61
|
+
if (dataLanguage && dataLanguage.trim() !== '') {
|
|
62
|
+
lang = dataLanguage.trim().toLowerCase();
|
|
63
|
+
} else {
|
|
64
|
+
const title = props.title as string | undefined;
|
|
65
|
+
if (title) {
|
|
66
|
+
const titleParts = title.split('.');
|
|
67
|
+
if (titleParts.length > 1 && titleParts[0] !== '') {
|
|
68
|
+
const extension = titleParts.pop()?.toLowerCase();
|
|
69
|
+
if (extension) {
|
|
70
|
+
lang = extension;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (lang && iconMap[lang]) {
|
|
77
|
+
return iconMap[lang];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function createBaseMdxComponents(
|
|
84
|
+
imageFallbackSrc?: string,
|
|
85
|
+
): MDXComponents {
|
|
86
|
+
return {
|
|
87
|
+
...baseMarkdownComponents,
|
|
88
|
+
img: (props) => (
|
|
89
|
+
<ImageZoom
|
|
90
|
+
{...(props as any)}
|
|
91
|
+
fallbackSrc={imageFallbackSrc}
|
|
92
|
+
/>
|
|
93
|
+
),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function createCodeMdxComponents(
|
|
98
|
+
iconMap: Record<string, ReactNode> = {},
|
|
99
|
+
): MDXComponents {
|
|
100
|
+
const mergedIconMap = {
|
|
101
|
+
...defaultCodeLanguageIconMap,
|
|
102
|
+
...iconMap,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
pre: (props) => {
|
|
107
|
+
const customIcon = tryToMatchIcon(props as MDXProps & { 'data-language'?: string; title?: string }, mergedIconMap);
|
|
108
|
+
return (
|
|
109
|
+
<CodeBlock
|
|
110
|
+
{...props}
|
|
111
|
+
{...(customIcon && { icon: customIcon })}
|
|
112
|
+
>
|
|
113
|
+
<Pre>{props.children}</Pre>
|
|
114
|
+
</CodeBlock>
|
|
115
|
+
);
|
|
116
|
+
},
|
|
117
|
+
CodeBlock,
|
|
118
|
+
Pre,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function createMathMdxComponents(): MDXComponents {
|
|
123
|
+
return {
|
|
124
|
+
MathBlock,
|
|
125
|
+
InlineMath,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function createMermaidMdxComponents(
|
|
130
|
+
watermarkEnabled?: boolean,
|
|
131
|
+
watermarkText?: string,
|
|
132
|
+
): MDXComponents {
|
|
133
|
+
return {
|
|
134
|
+
Mermaid: (props) => (
|
|
135
|
+
<Mermaid
|
|
136
|
+
{...props}
|
|
137
|
+
watermarkEnabled={watermarkEnabled}
|
|
138
|
+
watermarkText={watermarkText}
|
|
139
|
+
/>
|
|
140
|
+
),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function createTypeTableMdxComponents(): MDXComponents {
|
|
145
|
+
return {
|
|
146
|
+
TypeTable,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function createWidgetMdxComponents(
|
|
151
|
+
cdnBaseUrl?: string,
|
|
152
|
+
imageFallbackSrc?: string,
|
|
153
|
+
): MDXComponents {
|
|
154
|
+
return {
|
|
155
|
+
TrophyCard,
|
|
156
|
+
ZiaCard,
|
|
157
|
+
GradientButton,
|
|
158
|
+
ZiaFile,
|
|
159
|
+
ZiaFolder,
|
|
160
|
+
SunoEmbed,
|
|
161
|
+
ImageGrid: (props) => (
|
|
162
|
+
<ImageGrid {...props} cdnBaseUrl={cdnBaseUrl} />
|
|
163
|
+
),
|
|
164
|
+
ImageZoom: (props) => (
|
|
165
|
+
<ImageZoom {...props} fallbackSrc={imageFallbackSrc} />
|
|
166
|
+
),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { MDXComponents } from 'mdx/types';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import type { SiteMdxFeature } from '@windrun-huaiin/contracts/mdx';
|
|
4
|
+
import {
|
|
5
|
+
composeSiteMdxComponents,
|
|
6
|
+
createSiteFeatureComponentMap,
|
|
7
|
+
DEFAULT_SITE_MDX_FEATURES,
|
|
8
|
+
} from './site-mdx-presets';
|
|
9
|
+
|
|
10
|
+
export interface SiteMdxComponentsOptions {
|
|
11
|
+
imageFallbackSrc?: string;
|
|
12
|
+
cdnBaseUrl?: string;
|
|
13
|
+
watermarkEnabled?: boolean;
|
|
14
|
+
watermarkText?: string;
|
|
15
|
+
additionalComponents?: MDXComponents;
|
|
16
|
+
iconMap?: Record<string, ReactNode>;
|
|
17
|
+
features?: SiteMdxFeature[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function createSiteMdxComponents(
|
|
21
|
+
options: SiteMdxComponentsOptions,
|
|
22
|
+
) {
|
|
23
|
+
const {
|
|
24
|
+
additionalComponents,
|
|
25
|
+
cdnBaseUrl,
|
|
26
|
+
features = DEFAULT_SITE_MDX_FEATURES,
|
|
27
|
+
iconMap = {},
|
|
28
|
+
imageFallbackSrc,
|
|
29
|
+
watermarkEnabled,
|
|
30
|
+
watermarkText,
|
|
31
|
+
} = options;
|
|
32
|
+
const featureMap = createSiteFeatureComponentMap({
|
|
33
|
+
cdnBaseUrl,
|
|
34
|
+
iconMap,
|
|
35
|
+
imageFallbackSrc,
|
|
36
|
+
watermarkEnabled,
|
|
37
|
+
watermarkText,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return function getMDXComponents(components?: MDXComponents): MDXComponents {
|
|
41
|
+
return composeSiteMdxComponents(
|
|
42
|
+
features,
|
|
43
|
+
featureMap,
|
|
44
|
+
additionalComponents,
|
|
45
|
+
components,
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
|
2
|
+
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
|
3
|
+
import { Callout } from 'fumadocs-ui/components/callout';
|
|
4
|
+
import { File, Folder, Files } from 'fumadocs-ui/components/files';
|
|
5
|
+
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
|
|
6
|
+
import type { MDXComponents } from 'mdx/types';
|
|
7
|
+
import {
|
|
8
|
+
createBaseMdxComponents,
|
|
9
|
+
createCodeMdxComponents,
|
|
10
|
+
createMathMdxComponents,
|
|
11
|
+
createMermaidMdxComponents,
|
|
12
|
+
createTypeTableMdxComponents,
|
|
13
|
+
createWidgetMdxComponents,
|
|
14
|
+
} from './optional-features';
|
|
15
|
+
import { SiteX } from '../site-x';
|
|
16
|
+
import type { SiteMdxComponentsOptions } from './site-mdx-components';
|
|
17
|
+
import type { SiteMdxFeature } from '@windrun-huaiin/contracts/mdx';
|
|
18
|
+
|
|
19
|
+
const defaultFumaUiComponents: MDXComponents = {
|
|
20
|
+
Callout,
|
|
21
|
+
File,
|
|
22
|
+
Folder,
|
|
23
|
+
Files,
|
|
24
|
+
Accordion,
|
|
25
|
+
Accordions,
|
|
26
|
+
Tab,
|
|
27
|
+
Tabs,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const DEFAULT_SITE_MDX_FEATURES: SiteMdxFeature[] = [
|
|
31
|
+
'base',
|
|
32
|
+
'code',
|
|
33
|
+
'math',
|
|
34
|
+
'mermaid',
|
|
35
|
+
'type-table',
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
export function createSiteFeatureComponentMap(
|
|
39
|
+
options: SiteMdxComponentsOptions,
|
|
40
|
+
) {
|
|
41
|
+
const {
|
|
42
|
+
cdnBaseUrl,
|
|
43
|
+
iconMap = {},
|
|
44
|
+
imageFallbackSrc,
|
|
45
|
+
watermarkEnabled,
|
|
46
|
+
watermarkText,
|
|
47
|
+
} = options;
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
base: {
|
|
51
|
+
...defaultFumaUiComponents,
|
|
52
|
+
SiteX,
|
|
53
|
+
...createBaseMdxComponents(imageFallbackSrc),
|
|
54
|
+
...createWidgetMdxComponents(cdnBaseUrl, imageFallbackSrc),
|
|
55
|
+
},
|
|
56
|
+
code: createCodeMdxComponents(iconMap),
|
|
57
|
+
math: createMathMdxComponents(),
|
|
58
|
+
mermaid: createMermaidMdxComponents(watermarkEnabled, watermarkText),
|
|
59
|
+
'type-table': createTypeTableMdxComponents(),
|
|
60
|
+
} satisfies Record<SiteMdxFeature, MDXComponents>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function composeSiteMdxComponents(
|
|
64
|
+
features: readonly SiteMdxFeature[],
|
|
65
|
+
featureMap: Record<SiteMdxFeature, MDXComponents>,
|
|
66
|
+
additionalComponents?: MDXComponents,
|
|
67
|
+
components?: MDXComponents,
|
|
68
|
+
): MDXComponents {
|
|
69
|
+
return {
|
|
70
|
+
...defaultMdxComponents,
|
|
71
|
+
...features.reduce<MDXComponents>((acc, feature) => {
|
|
72
|
+
return {
|
|
73
|
+
...acc,
|
|
74
|
+
...featureMap[feature],
|
|
75
|
+
};
|
|
76
|
+
}, {}),
|
|
77
|
+
...additionalComponents,
|
|
78
|
+
...components,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './markdown-component-map';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { cn } from '@windrun-huaiin/lib/utils';
|
|
2
2
|
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
|
3
3
|
import { type ComponentType } from 'react';
|
|
4
|
-
import { ImageZoom } from '
|
|
4
|
+
import { ImageZoom } from '../heavy';
|
|
5
5
|
|
|
6
6
|
export type MarkdownComponentMap = Record<string, ComponentType<any>>;
|
|
7
7
|
|