mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-06-14 06:43:53 +00:00
- Add explicit CJK fonts (PingFang SC, Noto Sans SC, Microsoft YaHei) and programmer fonts (JetBrains Mono, Fira Code, Cascadia Code) to Tailwind config - Bump prose base size from prose-sm (14px) to prose-lg (18px) for sharper CJK rendering - Unify user/assistant message font size at 18px with CJK-aware line-height (1.8) - Replace pure black/white foreground with Apple-style warm grays (#1d1d1f / #f5f5f7) - Override Tailwind Typography colors to use design tokens for consistency - Add negative letter-spacing on headings for tighter, more polished look
88 lines
2.9 KiB
TypeScript
88 lines
2.9 KiB
TypeScript
import ReactMarkdown from "react-markdown";
|
|
import rehypeKatex from "rehype-katex";
|
|
import remarkGfm from "remark-gfm";
|
|
import remarkMath from "remark-math";
|
|
|
|
import { CodeBlock } from "@/components/CodeBlock";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
import "katex/dist/katex.min.css";
|
|
|
|
interface MarkdownTextRendererProps {
|
|
children: string;
|
|
className?: string;
|
|
}
|
|
|
|
/**
|
|
* Heavy markdown stack (GFM, math, KaTeX, syntax highlighting) kept in a
|
|
* separate chunk so the app shell can paint sooner on refresh.
|
|
*/
|
|
export default function MarkdownTextRenderer({
|
|
children,
|
|
className,
|
|
}: MarkdownTextRendererProps) {
|
|
return (
|
|
<div
|
|
className={cn(
|
|
"markdown-content prose prose-lg max-w-none dark:prose-invert",
|
|
"prose-headings:mt-4 prose-headings:mb-2 prose-headings:font-semibold prose-headings:tracking-tight",
|
|
"prose-h1:text-xl prose-h2:text-lg prose-h3:text-base prose-h4:text-sm",
|
|
"prose-p:my-2",
|
|
"prose-ul:my-2 prose-ol:my-2 prose-li:my-0.5",
|
|
"prose-blockquote:my-3 prose-blockquote:border-l-2 prose-blockquote:font-normal",
|
|
"prose-blockquote:not-italic prose-blockquote:text-foreground/80",
|
|
"prose-a:text-primary prose-a:underline-offset-2 hover:prose-a:opacity-80",
|
|
"prose-hr:my-6",
|
|
"prose-pre:my-0 prose-pre:bg-transparent prose-pre:p-0",
|
|
"prose-code:before:content-none prose-code:after:content-none prose-code:font-normal",
|
|
"prose-table:my-3 prose-th:text-left prose-th:font-medium",
|
|
className,
|
|
)}
|
|
style={{ lineHeight: "var(--cjk-line-height)" }}
|
|
>
|
|
<ReactMarkdown
|
|
remarkPlugins={[remarkGfm, remarkMath]}
|
|
rehypePlugins={[rehypeKatex]}
|
|
components={{
|
|
code({ className: cls, children: kids, ...props }) {
|
|
const match = /language-(\w+)/.exec(cls || "");
|
|
if (!match) {
|
|
return (
|
|
<code
|
|
className={cn(
|
|
"rounded bg-muted px-1 py-0.5 font-mono text-[0.85em]",
|
|
cls,
|
|
)}
|
|
{...props}
|
|
>
|
|
{kids}
|
|
</code>
|
|
);
|
|
}
|
|
const code = String(kids).replace(/\n$/, "");
|
|
return <CodeBlock language={match[1]} code={code} className="my-3" />;
|
|
},
|
|
pre({ children: markdownChildren }) {
|
|
return <>{markdownChildren}</>;
|
|
},
|
|
a({ href, children: markdownChildren, ...props }) {
|
|
return (
|
|
<a
|
|
href={href}
|
|
target="_blank"
|
|
rel="noreferrer noopener"
|
|
className="text-primary underline underline-offset-2 hover:opacity-80"
|
|
{...props}
|
|
>
|
|
{markdownChildren}
|
|
</a>
|
|
);
|
|
},
|
|
}}
|
|
>
|
|
{children}
|
|
</ReactMarkdown>
|
|
</div>
|
|
);
|
|
}
|