Files
jiang13-bbs/frontend/components/MarkdownBodyClient.tsx
freefire a83276060f feat: 站点单页、时间线导入与行级 BBCode 短代码
首页右栏接入单页入口与公告置顶/全部页;Markdown 编辑器支持可视化时间线与 Git 导入;隐藏块改为 [hide]/[timeline] 命名闭合,并修复单页/公告 GORM 更新只改 updated_at 的问题。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 19:52:06 +08:00

87 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import ReactMarkdown, { type Components } from "react-markdown";
import remarkGfm from "remark-gfm";
import { mergeMarkdownComponents } from "@/components/markdown/mergeComponents";
import { splitContentSegments } from "@/lib/directiveBlocks";
import type { HideKind } from "@/lib/hideBlocks";
import MdHideBlock from "@/components/markdown/MdHideBlock";
import MdTimeline from "@/components/markdown/MdTimeline";
type MarkdownBodyClientProps = {
content: string;
className?: string;
components?: Components;
postId?: number;
loginHref?: string;
loggedIn?: boolean;
};
/**
* 客户端 Markdown(发帖预览 / 评论):GFM + 隐藏块 / 时间线预览。
*/
export default function MarkdownBodyClient({
content,
className = "prose-content",
components,
postId,
loginHref,
loggedIn = false,
}: MarkdownBodyClientProps) {
const segs = splitContentSegments(content || "");
const mdComponents = mergeMarkdownComponents(components);
return (
<div className={className}>
{segs.map((seg, i) => {
if (seg.type === "md") {
if (!seg.text.trim()) return null;
return (
<ReactMarkdown key={`md-${i}`} remarkPlugins={[remarkGfm]} components={mdComponents}>
{seg.text}
</ReactMarkdown>
);
}
if (seg.type === "timeline") {
return (
<MdTimeline
key={`tl-${i}`}
items={seg.items}
renderBody={(it) =>
it.body.trim() ? (
<ReactMarkdown remarkPlugins={[remarkGfm]} components={mdComponents}>
{it.body}
</ReactMarkdown>
) : null
}
/>
);
}
const kind = seg.kind as HideKind;
if (seg.locked) {
return (
<MdHideBlock
key={`hide-${i}`}
kind={kind}
points={seg.points}
locked
postId={postId}
loginHref={loginHref}
loggedIn={loggedIn}
/>
);
}
return (
<MdHideBlock key={`hide-${i}`} kind={kind} points={seg.points}>
{seg.body.trim() ? (
<ReactMarkdown remarkPlugins={[remarkGfm]} components={mdComponents}>
{seg.body}
</ReactMarkdown>
) : null}
</MdHideBlock>
);
})}
</div>
);
}