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"; import MdEntries from "@/components/markdown/MdEntries"; import MdDetails from "@/components/markdown/MdDetails"; import MdVideo from "@/components/markdown/MdVideo"; type MarkdownBodyProps = { content: string; className?: string; components?: Components; /** 详情页解锁门禁需要 */ postId?: number; /** 登录跳转(公告等无 postId 时) */ loginHref?: string; loggedIn?: boolean; /** 书级「全章节条目卡模式」:章节内容免写 [entries] 壳 */ entriesAuto?: boolean; /** 按分段索引的条目标题锚点 id(与章内目录共享;阅读页传入,其他场景缺省) */ entriesTitleIds?: (string[] | undefined)[]; }; /** * 站点统一 Markdown 渲染(服务端):GFM + Shiki;支持 [hide] / [timeline] / [entries]。 */ export default async function MarkdownBody({ content, className = "prose-content", components, postId, loginHref, loggedIn = false, entriesAuto = false, entriesTitleIds, }: MarkdownBodyProps) { const segs = splitContentSegments(expandDyEmojiShortcodes(content || ""), { entriesAuto, }); 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(