feat(compose): 正文内嵌隐藏块并升级 Markdown 编辑器

去掉整帖可见性表单,改为 :::hide 按块脱敏;工具栏补齐代码块、链接/图片对话框与粘贴拖拽上传。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-17 04:58:20 +08:00
parent d1155cbd64
commit 01e2fd05ca
19 changed files with 1867 additions and 471 deletions

View File

@@ -3,30 +3,64 @@
import ReactMarkdown, { type Components } from "react-markdown";
import remarkGfm from "remark-gfm";
import { mergeMarkdownComponents } from "@/components/markdown/mergeComponents";
import { splitHideSegments, type HideKind } from "@/lib/hideBlocks";
import MdHideBlock from "@/components/markdown/MdHideBlock";
type MarkdownBodyClientProps = {
content: string;
className?: string;
components?: Components;
postId?: number;
loggedIn?: boolean;
};
/**
* 客户端 Markdown(发帖预览 / 评论):GFM + 图箱 / 代码折叠复制。
* 语法高亮在 MdCodeBlock 内按需用 Shiki 补齐。
* 客户端 Markdown(发帖预览 / 评论):GFM + 隐藏块徽章预览。
*/
export default function MarkdownBodyClient({
content,
className = "prose-content",
components,
postId,
loggedIn = false,
}: MarkdownBodyClientProps) {
const segs = splitHideSegments(content || "");
const mdComponents = mergeMarkdownComponents(components);
return (
<div className={className}>
<ReactMarkdown
remarkPlugins={[remarkGfm]}
components={mergeMarkdownComponents(components)}
>
{content || ""}
</ReactMarkdown>
{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>
);
}
const kind = seg.kind as HideKind;
if (seg.locked) {
return (
<MdHideBlock
key={`hide-${i}`}
kind={kind}
points={seg.points}
locked
postId={postId}
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>
);
}