import type { ReactNode } from "react"; import type { Components } from "react-markdown"; import { renderMarkdownToReact } from "@/components/markdown/renderMarkdown"; import { splitContentSegments } from "@/lib/directiveBlocks"; import { expandDyEmojiShortcodes } from "@/lib/dyEmoji"; import type { HideKind } from "@/lib/hideBlocks"; import MdHideBlock from "@/components/markdown/MdHideBlock"; import MdTimeline from "@/components/markdown/MdTimeline"; type MarkdownBodyProps = { content: string; className?: string; components?: Components; /** 详情页解锁门禁需要 */ postId?: number; /** 登录跳转(公告等无 postId 时) */ loginHref?: string; loggedIn?: boolean; }; /** * 站点统一 Markdown 渲染(服务端):GFM + Shiki;支持 [hide] / [timeline]。 */ export default async function MarkdownBody({ content, className = "prose-content", components, postId, loginHref, loggedIn = false, }: MarkdownBodyProps) { const segs = splitContentSegments(expandDyEmojiShortcodes(content || "")); const nodes = []; for (let i = 0; i < segs.length; i++) { const seg = segs[i]; if (seg.type === "md") { if (!seg.text.trim()) continue; nodes.push(
{await renderMarkdownToReact(seg.text, components)}
); continue; } if (seg.type === "timeline") { const bodies: ReactNode[] = []; for (let j = 0; j < seg.items.length; j++) { const it = seg.items[j]; if (!it.body.trim()) { bodies.push(null); continue; } // 条目正文不挂目录 id,避免与块外 headingRenderer 错位 bodies.push(await renderMarkdownToReact(expandDyEmojiShortcodes(it.body))); } nodes.push( bodies[idx]} /> ); continue; } const kind = seg.kind as HideKind; if (seg.locked) { nodes.push( ); continue; } const inner = seg.body.trim() ? await renderMarkdownToReact(expandDyEmojiShortcodes(seg.body)) : null; nodes.push( {inner} ); } return
{nodes}
; }