refactor(pages) migrate custom pages to using fumadocs
This commit is contained in:
parent
543798e2c1
commit
c477aae333
@ -200,42 +200,42 @@ export const posts = defineCollection({
|
||||
* slug: /pages/privacy-policy
|
||||
* slugAsParams: privacy-policy
|
||||
*/
|
||||
export const pages = defineCollection({
|
||||
name: 'page',
|
||||
directory: 'content/pages',
|
||||
include: '**/*.mdx',
|
||||
schema: (z) => ({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
date: z.string().datetime(),
|
||||
published: z.boolean().default(true),
|
||||
}),
|
||||
transform: async (data, context) => {
|
||||
// Use Fumadocs transformMDX for consistent MDX processing
|
||||
const transformedData = await transformMDX(data, context);
|
||||
// export const pages = defineCollection({
|
||||
// name: 'page',
|
||||
// directory: 'content/pages',
|
||||
// include: '**/*.mdx',
|
||||
// schema: (z) => ({
|
||||
// title: z.string(),
|
||||
// description: z.string(),
|
||||
// date: z.string().datetime(),
|
||||
// published: z.boolean().default(true),
|
||||
// }),
|
||||
// transform: async (data, context) => {
|
||||
// // Use Fumadocs transformMDX for consistent MDX processing
|
||||
// const transformedData = await transformMDX(data, context);
|
||||
|
||||
// Get the filename from the path
|
||||
const filePath = data._meta.path;
|
||||
const fileName = filePath.split(path.sep).pop() || '';
|
||||
// // Get the filename from the path
|
||||
// const filePath = data._meta.path;
|
||||
// const fileName = filePath.split(path.sep).pop() || '';
|
||||
|
||||
// Extract locale and base from filename
|
||||
const { locale, base } = extractLocaleAndBase(fileName);
|
||||
// console.log(`page processed: ${fileName}, base=${base}, locale=${locale}`);
|
||||
// // Extract locale and base from filename
|
||||
// const { locale, base } = extractLocaleAndBase(fileName);
|
||||
// // console.log(`page processed: ${fileName}, base=${base}, locale=${locale}`);
|
||||
|
||||
// Create the slug and slugAsParams
|
||||
const slug = `/pages/${base}`;
|
||||
const slugAsParams = base;
|
||||
// // Create the slug and slugAsParams
|
||||
// const slug = `/pages/${base}`;
|
||||
// const slugAsParams = base;
|
||||
|
||||
return {
|
||||
...data,
|
||||
locale,
|
||||
slug,
|
||||
slugAsParams,
|
||||
body: transformedData.body,
|
||||
toc: transformedData.toc,
|
||||
};
|
||||
},
|
||||
});
|
||||
// return {
|
||||
// ...data,
|
||||
// locale,
|
||||
// slug,
|
||||
// slugAsParams,
|
||||
// body: transformedData.body,
|
||||
// toc: transformedData.toc,
|
||||
// };
|
||||
// },
|
||||
// });
|
||||
|
||||
/**
|
||||
* Releases collection for changelog
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Cookie Policy
|
||||
description: How we use cookies and similar technologies on our website
|
||||
date: 2025-03-10T00:00:00.000Z
|
||||
date: "2025-03-10T00:00:00.000Z"
|
||||
published: true
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Cookie 政策
|
||||
description: 我们如何在网站上使用 Cookie 和类似技术
|
||||
date: 2025-03-10T00:00:00.000Z
|
||||
date: "2025-03-10T00:00:00.000Z"
|
||||
published: true
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Privacy Policy
|
||||
description: Our commitment to protecting your privacy and personal data
|
||||
date: 2025-03-10T00:00:00.000Z
|
||||
date: "2025-03-10T00:00:00.000Z"
|
||||
published: true
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 隐私政策
|
||||
description: 我们致力于保护您的隐私和个人数据
|
||||
date: 2025-03-10T00:00:00.000Z
|
||||
date: "2025-03-10T00:00:00.000Z"
|
||||
published: true
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Terms of Service
|
||||
description: The terms and conditions governing the use of our services
|
||||
date: 2025-03-10T00:00:00.000Z
|
||||
date: "2025-03-10T00:00:00.000Z"
|
||||
published: true
|
||||
---
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 服务条款
|
||||
description: 管理我们服务使用的条款和条件
|
||||
date: 2025-03-10T00:00:00.000Z
|
||||
date: "2025-03-10T00:00:00.000Z"
|
||||
published: true
|
||||
---
|
||||
|
||||
|
@ -42,3 +42,17 @@ export const changelog = defineCollections({
|
||||
published: z.boolean().default(true),
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* Pages
|
||||
*/
|
||||
export const pages = defineCollections({
|
||||
type: 'doc',
|
||||
dir: 'content/pages',
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
date: z.string().datetime(),
|
||||
published: z.boolean().default(true),
|
||||
}),
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { CustomPage } from '@/components/page/custom-page';
|
||||
import { pagesSource } from '@/lib/docs/source';
|
||||
import { constructMetadata } from '@/lib/metadata';
|
||||
import { getPage } from '@/lib/page/get-page';
|
||||
import { getUrlWithLocale } from '@/lib/urls/urls';
|
||||
import type { NextPageProps } from '@/types/next-page-props';
|
||||
import type { Metadata } from 'next';
|
||||
@ -14,7 +14,7 @@ export async function generateMetadata({
|
||||
params: Promise<{ locale: Locale }>;
|
||||
}): Promise<Metadata | undefined> {
|
||||
const { locale } = await params;
|
||||
const page = await getPage('cookie-policy', locale);
|
||||
const page = pagesSource.getPage(['cookie-policy'], locale);
|
||||
|
||||
if (!page) {
|
||||
console.warn(
|
||||
@ -26,8 +26,8 @@ export async function generateMetadata({
|
||||
const t = await getTranslations({ locale, namespace: 'Metadata' });
|
||||
|
||||
return constructMetadata({
|
||||
title: page.title + ' | ' + t('title'),
|
||||
description: page.description,
|
||||
title: page.data.title + ' | ' + t('title'),
|
||||
description: page.data.description,
|
||||
canonicalUrl: getUrlWithLocale('/cookie', locale),
|
||||
});
|
||||
}
|
||||
@ -39,18 +39,11 @@ export default async function CookiePolicyPage(props: NextPageProps) {
|
||||
}
|
||||
|
||||
const locale = params.locale as string;
|
||||
const page = await getPage('cookie-policy', locale);
|
||||
const page = pagesSource.getPage(['cookie-policy'], locale);
|
||||
|
||||
if (!page) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<CustomPage
|
||||
title={page.title}
|
||||
description={page.description}
|
||||
date={page.date}
|
||||
content={page.body}
|
||||
/>
|
||||
);
|
||||
return <CustomPage page={page} />;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { CustomPage } from '@/components/page/custom-page';
|
||||
import { pagesSource } from '@/lib/docs/source';
|
||||
import { constructMetadata } from '@/lib/metadata';
|
||||
import { getPage } from '@/lib/page/get-page';
|
||||
import { getUrlWithLocale } from '@/lib/urls/urls';
|
||||
import type { NextPageProps } from '@/types/next-page-props';
|
||||
import type { Metadata } from 'next';
|
||||
@ -14,7 +14,7 @@ export async function generateMetadata({
|
||||
params: Promise<{ locale: Locale }>;
|
||||
}): Promise<Metadata | undefined> {
|
||||
const { locale } = await params;
|
||||
const page = await getPage('privacy-policy', locale);
|
||||
const page = pagesSource.getPage(['privacy-policy'], locale);
|
||||
|
||||
if (!page) {
|
||||
console.warn(
|
||||
@ -26,8 +26,8 @@ export async function generateMetadata({
|
||||
const t = await getTranslations({ locale, namespace: 'Metadata' });
|
||||
|
||||
return constructMetadata({
|
||||
title: page.title + ' | ' + t('title'),
|
||||
description: page.description,
|
||||
title: page.data.title + ' | ' + t('title'),
|
||||
description: page.data.description,
|
||||
canonicalUrl: getUrlWithLocale('/privacy', locale),
|
||||
});
|
||||
}
|
||||
@ -39,18 +39,11 @@ export default async function PrivacyPolicyPage(props: NextPageProps) {
|
||||
}
|
||||
|
||||
const locale = params.locale as string;
|
||||
const page = await getPage('privacy-policy', locale);
|
||||
const page = pagesSource.getPage(['privacy-policy'], locale);
|
||||
|
||||
if (!page) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<CustomPage
|
||||
title={page.title}
|
||||
description={page.description}
|
||||
date={page.date}
|
||||
content={page.body}
|
||||
/>
|
||||
);
|
||||
return <CustomPage page={page} />;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { CustomPage } from '@/components/page/custom-page';
|
||||
import { pagesSource } from '@/lib/docs/source';
|
||||
import { constructMetadata } from '@/lib/metadata';
|
||||
import { getPage } from '@/lib/page/get-page';
|
||||
import { getUrlWithLocale } from '@/lib/urls/urls';
|
||||
import type { NextPageProps } from '@/types/next-page-props';
|
||||
import type { Metadata } from 'next';
|
||||
@ -14,7 +14,7 @@ export async function generateMetadata({
|
||||
params: Promise<{ locale: Locale }>;
|
||||
}): Promise<Metadata | undefined> {
|
||||
const { locale } = await params;
|
||||
const page = await getPage('terms-of-service', locale);
|
||||
const page = pagesSource.getPage(['terms-of-service'], locale);
|
||||
|
||||
if (!page) {
|
||||
console.warn(
|
||||
@ -26,8 +26,8 @@ export async function generateMetadata({
|
||||
const t = await getTranslations({ locale, namespace: 'Metadata' });
|
||||
|
||||
return constructMetadata({
|
||||
title: page.title + ' | ' + t('title'),
|
||||
description: page.description,
|
||||
title: page.data.title + ' | ' + t('title'),
|
||||
description: page.data.description,
|
||||
canonicalUrl: getUrlWithLocale('/terms', locale),
|
||||
});
|
||||
}
|
||||
@ -39,18 +39,11 @@ export default async function TermsOfServicePage(props: NextPageProps) {
|
||||
}
|
||||
|
||||
const locale = params.locale as string;
|
||||
const page = await getPage('terms-of-service', locale);
|
||||
const page = pagesSource.getPage(['terms-of-service'], locale);
|
||||
|
||||
if (!page) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<CustomPage
|
||||
title={page.title}
|
||||
description={page.description}
|
||||
date={page.date}
|
||||
content={page.body}
|
||||
/>
|
||||
);
|
||||
return <CustomPage page={page} />;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ReleaseCard } from '@/components/changelog/release-card';
|
||||
import Container from '@/components/layout/container';
|
||||
import { ReleaseCard } from '@/components/release/release-card';
|
||||
import { changelogSource } from '@/lib/docs/source';
|
||||
import { constructMetadata } from '@/lib/metadata';
|
||||
import { getUrlWithLocale } from '@/lib/urls/urls';
|
||||
|
@ -3,13 +3,14 @@ import { Card, CardContent, CardHeader } from '@/components/ui/card';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import type { changelogSource } from '@/lib/docs/source';
|
||||
import { formatDate } from '@/lib/formatter';
|
||||
import type { InferPageType } from 'fumadocs-core/source';
|
||||
import { CalendarIcon, TagIcon } from 'lucide-react';
|
||||
import { getMDXComponents } from '../custom/mdx-components';
|
||||
|
||||
type ChangelogPage = ReturnType<typeof changelogSource.getPages>[number];
|
||||
type ChangelogRelease = InferPageType<typeof changelogSource>;
|
||||
|
||||
interface ReleaseCardProps {
|
||||
releaseItem: ChangelogPage;
|
||||
releaseItem: ChangelogRelease;
|
||||
}
|
||||
|
||||
export function ReleaseCard({ releaseItem }: ReleaseCardProps) {
|
@ -1,22 +1,20 @@
|
||||
import { CustomMDXContent } from '@/components/shared/custom-mdx-content';
|
||||
import type { pagesSource } from '@/lib/docs/source';
|
||||
import { formatDate } from '@/lib/formatter';
|
||||
import type { InferPageType } from 'fumadocs-core/source';
|
||||
import { CalendarIcon } from 'lucide-react';
|
||||
import { getMDXComponents } from '../custom/mdx-components';
|
||||
import { Card, CardContent } from '../ui/card';
|
||||
|
||||
type Page = InferPageType<typeof pagesSource>;
|
||||
|
||||
interface CustomPageProps {
|
||||
title: string;
|
||||
description: string;
|
||||
date: string;
|
||||
content: any; // MDX content
|
||||
page: Page;
|
||||
}
|
||||
|
||||
export function CustomPage({
|
||||
title,
|
||||
description,
|
||||
date,
|
||||
content,
|
||||
}: CustomPageProps) {
|
||||
export function CustomPage({ page }: CustomPageProps) {
|
||||
const { title, description, date } = page.data;
|
||||
const formattedDate = formatDate(new Date(date));
|
||||
const MDX = page.data.body;
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto space-y-8">
|
||||
@ -38,7 +36,7 @@ export function CustomPage({
|
||||
<Card className="mb-8">
|
||||
<CardContent>
|
||||
<div className="max-w-none prose prose-neutral dark:prose-invert prose-img:rounded-lg">
|
||||
<CustomMDXContent code={content} />
|
||||
<MDX components={getMDXComponents()} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
@ -2,7 +2,7 @@ import { loader } from 'fumadocs-core/source';
|
||||
import { createMDXSource } from 'fumadocs-mdx';
|
||||
import * as LucideIcons from 'lucide-react';
|
||||
import { createElement } from 'react';
|
||||
import { changelog, docs } from '../../../.source';
|
||||
import { changelog, docs, pages } from '../../../.source';
|
||||
import { docsI18nConfig } from './i18n';
|
||||
|
||||
/**
|
||||
@ -39,3 +39,12 @@ export const changelogSource = loader({
|
||||
i18n: docsI18nConfig,
|
||||
source: createMDXSource(changelog),
|
||||
});
|
||||
|
||||
/**
|
||||
* Pages source
|
||||
*/
|
||||
export const pagesSource = loader({
|
||||
baseUrl: '/pages',
|
||||
i18n: docsI18nConfig,
|
||||
source: createMDXSource(pages),
|
||||
});
|
||||
|
@ -1,26 +0,0 @@
|
||||
import { allPages } from 'content-collections';
|
||||
import type { Locale } from 'next-intl';
|
||||
|
||||
/**
|
||||
* Gets a page from the content collection
|
||||
* @param type The type of page to get (e.g., 'privacy-policy', 'terms-of-service')
|
||||
* @param locale The locale to get the page for
|
||||
* @returns The page or undefined if not found
|
||||
*/
|
||||
export async function getPage(type: string, locale: Locale) {
|
||||
// Find page with matching slug and locale
|
||||
const page = allPages.find(
|
||||
(page) => page.slugAsParams === `${type}` && page.locale === locale
|
||||
);
|
||||
|
||||
if (!page) {
|
||||
// If no page found with the current locale, try to find one with any locale
|
||||
const defaultPage = allPages.find(
|
||||
(page) => page.slugAsParams === `${type}`
|
||||
);
|
||||
|
||||
return defaultPage;
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
Loading…
Reference in New Issue
Block a user