Files
jiang13-bbs/frontend/components/markdown/renderMarkdown.tsx
freefire be47b38370 fix(frontend): 修复 Markdown 代码块折叠空白,收起滚回块顶
避免客户端覆盖 SSR 高亮;空行撑高;收起后 scrollIntoView 到代码块头部。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-16 05:50:40 +08:00

52 lines
1.5 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.
import type { Components } from "react-markdown";
import type { ReactElement } from "react";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import { toJsxRuntime } from "hast-util-to-jsx-runtime";
import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkGfm from "remark-gfm";
import remarkRehype from "remark-rehype";
import rehypePrettyCode from "rehype-pretty-code";
import type { Root } from "hast";
import { mergeMarkdownComponents } from "./mergeComponents";
export const prettyCodeOptions = {
theme: {
light: "github-light",
dark: "github-dark-dimmed",
},
keepBackground: false,
defaultLang: "plaintext",
// 空行在 display:grid 下会塌缩成 0 高,补一个空格撑住行高
onVisitLine(element: { children: unknown[] }) {
if (element.children.length === 0) {
element.children = [{ type: "text", value: " " }];
}
},
} as const;
/** 服务端异步管线:GFM + Shiki 双主题高亮 → React 树 */
export async function renderMarkdownToReact(
content: string,
overrides?: Components
): Promise<ReactElement> {
const processor = unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype)
.use(rehypePrettyCode, { ...prettyCodeOptions });
const mdast = processor.parse(content || "");
const hast = (await processor.run(mdast)) as Root;
return toJsxRuntime(hast, {
Fragment,
jsx,
jsxs,
components: mergeMarkdownComponents(overrides) as Record<
string,
React.ElementType
>,
}) as ReactElement;
}