'use client'; import { BlogApi } from "@/lib/api"; import { base62 } from "@/lib/utils"; import { useParams } from "next/navigation"; import { useEffect, useState } from "react"; import useSWR from "swr"; import { unified } from 'unified'; import remarkParse from 'remark-parse'; import remarkRehype from 'remark-rehype'; import rehypeHighlight from 'rehype-highlight'; import rehypeStringify from 'rehype-stringify'; export default function Blog() { const params = useParams(); const hex = Array.from(base62.decode(params.id as string)).map(b => b.toString(16).padStart(2, '0')).join(''); const id = [ hex.slice(0, 8), hex.slice(8, 12), hex.slice(12, 16), hex.slice(16, 20), hex.slice(20, 32) ].join('-'); const [markdownHTML, setMarkdownHTML] = useState(null); const { data, error, isLoading } = useSWR( `/api/blog/${id}`, () => BlogApi.get(id), ) useEffect(() => { if (data?.content) { (async () => { try { const processed = unified() .use(remarkParse) // 解析 Markdown .use(remarkRehype) // 转换为 HTML AST .use(rehypeHighlight) // 高亮代码块 .use(rehypeStringify); // 输出 HTML 字符串 const result = await processed.process(data.content); setMarkdownHTML(result.toString()); } catch (err) { console.error("Failed to parse markdown", err); setMarkdownHTML("

无法加载内容

"); } })(); } }, [data]); return (
{data && (

{data.title}

{/* 渲染 Markdown HTML */} {markdownHTML && (
)}

发布于:{new Date(data.createdAt).toLocaleString()}

)}
) }