refactor(changelog) migrate changelog to use fumadocs
This commit is contained in:
parent
f4d8a09ab6
commit
ec8ce54824
@ -252,43 +252,43 @@ export const pages = defineCollection({
|
||||
* slug: /release/v1-0-0
|
||||
* slugAsParams: v1-0-0
|
||||
*/
|
||||
export const releases = defineCollection({
|
||||
name: 'release',
|
||||
directory: 'content/release',
|
||||
include: '**/*.mdx',
|
||||
schema: (z) => ({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
date: z.string().datetime(),
|
||||
version: z.string(),
|
||||
published: z.boolean().default(true),
|
||||
}),
|
||||
transform: async (data, context) => {
|
||||
// Use Fumadocs transformMDX for consistent MDX processing
|
||||
const transformedData = await transformMDX(data, context);
|
||||
// export const releases = defineCollection({
|
||||
// name: 'release',
|
||||
// directory: 'content/release',
|
||||
// include: '**/*.mdx',
|
||||
// schema: (z) => ({
|
||||
// title: z.string(),
|
||||
// description: z.string(),
|
||||
// date: z.string().datetime(),
|
||||
// version: z.string(),
|
||||
// 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(`release processed: ${fileName}, base=${base}, locale=${locale}`);
|
||||
// // Extract locale and base from filename
|
||||
// const { locale, base } = extractLocaleAndBase(fileName);
|
||||
// // console.log(`release processed: ${fileName}, base=${base}, locale=${locale}`);
|
||||
|
||||
// Create the slug and slugAsParams
|
||||
const slug = `/release/${base}`;
|
||||
const slugAsParams = base;
|
||||
// // Create the slug and slugAsParams
|
||||
// const slug = `/release/${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,
|
||||
// };
|
||||
// },
|
||||
// });
|
||||
|
||||
/**
|
||||
* Helper function to extract locale and base name from filename
|
||||
@ -320,5 +320,5 @@ function extractLocaleAndBase(fileName: string): {
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
collections: [authors, categories, posts, pages, releases],
|
||||
collections: [authors, categories, posts, pages],
|
||||
});
|
||||
|
@ -1,4 +1,9 @@
|
||||
import { defineDocs, frontmatterSchema, metaSchema } from 'fumadocs-mdx/config';
|
||||
import {
|
||||
defineCollections,
|
||||
defineDocs,
|
||||
frontmatterSchema,
|
||||
metaSchema,
|
||||
} from 'fumadocs-mdx/config';
|
||||
import { z } from 'zod';
|
||||
|
||||
const customDocsSchema = frontmatterSchema.extend({
|
||||
@ -11,9 +16,6 @@ const customMetaSchema = metaSchema.extend({
|
||||
});
|
||||
|
||||
/**
|
||||
* frontmatterSchema.extend causes error: Type instantiation is excessively deep,
|
||||
* so we define the schema manually.
|
||||
*
|
||||
* https://fumadocs.dev/docs/mdx/collections#schema-1
|
||||
*/
|
||||
export const docs = defineDocs({
|
||||
@ -25,3 +27,18 @@ export const docs = defineDocs({
|
||||
schema: customMetaSchema,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Changelog releases
|
||||
*/
|
||||
export const releases = defineCollections({
|
||||
type: 'doc',
|
||||
dir: 'content/release',
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
date: z.string().datetime(),
|
||||
version: z.string(),
|
||||
published: z.boolean().default(true),
|
||||
}),
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import Container from '@/components/layout/container';
|
||||
import { ReleaseCard } from '@/components/release/release-card';
|
||||
import { changelog } from '@/lib/docs/source';
|
||||
import { constructMetadata } from '@/lib/metadata';
|
||||
import { getReleases } from '@/lib/release/get-releases';
|
||||
import { getUrlWithLocale } from '@/lib/urls/urls';
|
||||
import type { NextPageProps } from '@/types/next-page-props';
|
||||
import type { Metadata } from 'next';
|
||||
@ -9,7 +10,6 @@ import { getTranslations } from 'next-intl/server';
|
||||
import { notFound } from 'next/navigation';
|
||||
|
||||
import '@/styles/mdx.css';
|
||||
import Container from '@/components/layout/container';
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
@ -34,9 +34,15 @@ export default async function ChangelogPage(props: NextPageProps) {
|
||||
}
|
||||
|
||||
const locale = params.locale as Locale;
|
||||
const releases = await getReleases(locale);
|
||||
const localeReleases = changelog.getPages(locale);
|
||||
const publishedReleases = localeReleases
|
||||
.filter((releaseItem) => releaseItem.data.published)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
new Date(b.data.date).getTime() - new Date(a.data.date).getTime()
|
||||
);
|
||||
|
||||
if (!releases || releases.length === 0) {
|
||||
if (!publishedReleases || publishedReleases.length === 0) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
@ -57,16 +63,20 @@ export default async function ChangelogPage(props: NextPageProps) {
|
||||
|
||||
{/* Releases */}
|
||||
<div className="mt-8">
|
||||
{releases.map((release) => (
|
||||
<ReleaseCard
|
||||
key={release.slug}
|
||||
title={release.title}
|
||||
description={release.description}
|
||||
date={release.date}
|
||||
version={release.version}
|
||||
content={release.body}
|
||||
/>
|
||||
))}
|
||||
{publishedReleases.map((releaseItem) => {
|
||||
const MDX = releaseItem.data.body;
|
||||
|
||||
return (
|
||||
<ReleaseCard
|
||||
key={releaseItem.data.version}
|
||||
title={releaseItem.data.title}
|
||||
description={releaseItem.data.description}
|
||||
date={releaseItem.data.date}
|
||||
version={releaseItem.data.version}
|
||||
content={<MDX />}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { CustomMDXContent } from '@/components/shared/custom-mdx-content';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Card, CardContent, CardHeader } from '@/components/ui/card';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { formatDate } from '@/lib/formatter';
|
||||
import { CalendarIcon, TagIcon } from 'lucide-react';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
interface ReleaseCardProps {
|
||||
title: string;
|
||||
description: string;
|
||||
date: string;
|
||||
version: string;
|
||||
content: any; // MDX content
|
||||
content: ReactNode; // React component
|
||||
}
|
||||
|
||||
export function ReleaseCard({
|
||||
@ -41,7 +41,7 @@ export function ReleaseCard({
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="max-w-none prose prose-neutral dark:prose-invert prose-img:rounded-lg">
|
||||
<CustomMDXContent code={content} />
|
||||
{content}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { loader } from 'fumadocs-core/source';
|
||||
import { createMDXSource } from 'fumadocs-mdx';
|
||||
import * as LucideIcons from 'lucide-react';
|
||||
import { createElement } from 'react';
|
||||
import { docs } from '../../../.source';
|
||||
import { docs, releases } from '../../../.source';
|
||||
import { docsI18nConfig } from './i18n';
|
||||
|
||||
/**
|
||||
@ -29,3 +30,12 @@ export const source = loader({
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Changelog releases source
|
||||
*/
|
||||
export const changelog = loader({
|
||||
baseUrl: '/changelog',
|
||||
i18n: docsI18nConfig,
|
||||
source: createMDXSource(releases),
|
||||
});
|
||||
|
@ -1,28 +0,0 @@
|
||||
import { allReleases } from 'content-collections';
|
||||
import type { Locale } from 'next-intl';
|
||||
/**
|
||||
* Gets all releases for the changelog page
|
||||
* @param locale The locale to get releases for
|
||||
* @returns An array of releases sorted by date (newest first)
|
||||
*/
|
||||
export async function getReleases(locale: Locale) {
|
||||
// Find all published releases with matching locale
|
||||
const releases = allReleases.filter(
|
||||
(release) => release.published && release.locale === locale
|
||||
);
|
||||
|
||||
// If no releases found with the current locale, try to find ones with any locale
|
||||
if (releases.length === 0) {
|
||||
const defaultReleases = allReleases.filter((release) => release.published);
|
||||
|
||||
// Sort by date (newest first)
|
||||
return defaultReleases.sort(
|
||||
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
|
||||
);
|
||||
}
|
||||
|
||||
// Sort by date (newest first)
|
||||
return releases.sort(
|
||||
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user