@@ -10,6 +10,8 @@ import type { BlogMeta, BlogPost, TagWithCount } from '@/lib/blog/schema'
1010import { AuthorSchema , BlogFrontmatterSchema } from '@/lib/blog/schema'
1111import { AUTHORS_DIR , BLOG_DIR , byDateDesc , ensureContentDirs , toIsoDate } from '@/lib/blog/utils'
1212
13+ const postComponentsRegistry : Record < string , Record < string , React . ComponentType > > = { }
14+
1315let cachedMeta : BlogMeta [ ] | null = null
1416let cachedAuthors : Record < string , any > | null = null
1517
@@ -99,6 +101,21 @@ export async function getAllTags(): Promise<TagWithCount[]> {
99101 . sort ( ( a , b ) => b . count - a . count || a . tag . localeCompare ( b . tag ) )
100102}
101103
104+ async function loadPostComponents ( slug : string ) : Promise < Record < string , React . ComponentType > > {
105+ if ( postComponentsRegistry [ slug ] ) {
106+ return postComponentsRegistry [ slug ]
107+ }
108+
109+ try {
110+ const postComponents = await import ( `@/content/blog/${ slug } /components` )
111+ postComponentsRegistry [ slug ] = postComponents
112+ return postComponents
113+ } catch {
114+ postComponentsRegistry [ slug ] = { }
115+ return { }
116+ }
117+ }
118+
102119export async function getPostBySlug ( slug : string ) : Promise < BlogPost > {
103120 const meta = await scanFrontmatters ( )
104121 const found = meta . find ( ( m ) => m . slug === slug )
@@ -107,9 +124,13 @@ export async function getPostBySlug(slug: string): Promise<BlogPost> {
107124 const raw = await fs . readFile ( mdxPath , 'utf-8' )
108125 const { content, data } = matter ( raw )
109126 const fm = BlogFrontmatterSchema . parse ( data )
127+
128+ const postComponents = await loadPostComponents ( slug )
129+ const mergedComponents = { ...mdxComponents , ...postComponents }
130+
110131 const compiled = await compileMDX ( {
111132 source : content ,
112- components : mdxComponents as any ,
133+ components : mergedComponents as any ,
113134 options : {
114135 parseFrontmatter : false ,
115136 mdxOptions : {
0 commit comments