ui/ markdown support
This commit is contained in:
@@ -5,6 +5,100 @@ import { Button } from "@/components/ui/button";
|
||||
import { UserProfile } from "@/components/auth/user-profile";
|
||||
import { useSession } from "@/lib/auth-client";
|
||||
import { useState, type ReactNode } from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import type { Components } from "react-markdown";
|
||||
import type { CodeComponent } from "react-markdown/lib/ast-to-react";
|
||||
|
||||
const H1: React.FC<React.HTMLAttributes<HTMLHeadingElement>> = (props) => (
|
||||
<h1 className="mt-2 mb-3 text-2xl font-bold" {...props} />
|
||||
);
|
||||
const H2: React.FC<React.HTMLAttributes<HTMLHeadingElement>> = (props) => (
|
||||
<h2 className="mt-2 mb-2 text-xl font-semibold" {...props} />
|
||||
);
|
||||
const H3: React.FC<React.HTMLAttributes<HTMLHeadingElement>> = (props) => (
|
||||
<h3 className="mt-2 mb-2 text-lg font-semibold" {...props} />
|
||||
);
|
||||
const Paragraph: React.FC<React.HTMLAttributes<HTMLParagraphElement>> = (
|
||||
props
|
||||
) => <p className="mb-3 leading-7 text-sm" {...props} />;
|
||||
const UL: React.FC<React.HTMLAttributes<HTMLUListElement>> = (props) => (
|
||||
<ul className="mb-3 ml-5 list-disc space-y-1 text-sm" {...props} />
|
||||
);
|
||||
const OL: React.FC<React.OlHTMLAttributes<HTMLOListElement>> = (props) => (
|
||||
<ol className="mb-3 ml-5 list-decimal space-y-1 text-sm" {...props} />
|
||||
);
|
||||
const LI: React.FC<React.LiHTMLAttributes<HTMLLIElement>> = (props) => (
|
||||
<li className="leading-6" {...props} />
|
||||
);
|
||||
const Anchor: React.FC<React.AnchorHTMLAttributes<HTMLAnchorElement>> = (
|
||||
props
|
||||
) => (
|
||||
<a
|
||||
className="underline underline-offset-2 text-primary hover:opacity-90"
|
||||
rel="noreferrer noopener"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
const Blockquote: React.FC<React.BlockquoteHTMLAttributes<HTMLElement>> = (
|
||||
props
|
||||
) => (
|
||||
<blockquote
|
||||
className="mb-3 border-l-2 border-border pl-3 text-muted-foreground"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
const Code: CodeComponent = ({ inline, children, ...props }) => {
|
||||
if (inline) {
|
||||
return (
|
||||
<code className="rounded bg-muted px-1 py-0.5 text-xs" {...props}>
|
||||
{children}
|
||||
</code>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<pre className="mb-3 w-full overflow-x-auto rounded-md bg-muted p-3">
|
||||
<code className="text-xs leading-5" {...props}>
|
||||
{children}
|
||||
</code>
|
||||
</pre>
|
||||
);
|
||||
};
|
||||
const HR: React.FC<React.HTMLAttributes<HTMLHRElement>> = (props) => (
|
||||
<hr className="my-4 border-border" {...props} />
|
||||
);
|
||||
const Table: React.FC<React.TableHTMLAttributes<HTMLTableElement>> = (
|
||||
props
|
||||
) => (
|
||||
<div className="mb-3 overflow-x-auto">
|
||||
<table className="w-full border-collapse text-sm" {...props} />
|
||||
</div>
|
||||
);
|
||||
const TH: React.FC<React.ThHTMLAttributes<HTMLTableCellElement>> = (props) => (
|
||||
<th
|
||||
className="border border-border bg-muted px-2 py-1 text-left"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
const TD: React.FC<React.TdHTMLAttributes<HTMLTableCellElement>> = (props) => (
|
||||
<td className="border border-border px-2 py-1" {...props} />
|
||||
);
|
||||
|
||||
const markdownComponents: Components = {
|
||||
h1: H1,
|
||||
h2: H2,
|
||||
h3: H3,
|
||||
p: Paragraph,
|
||||
ul: UL,
|
||||
ol: OL,
|
||||
li: LI,
|
||||
a: Anchor,
|
||||
blockquote: Blockquote,
|
||||
code: Code,
|
||||
hr: HR,
|
||||
table: Table,
|
||||
th: TH,
|
||||
td: TD,
|
||||
};
|
||||
|
||||
type TextPart = { type?: string; text?: string };
|
||||
type MaybePartsMessage = {
|
||||
@@ -21,7 +115,15 @@ function renderMessageContent(message: MaybePartsMessage): ReactNode {
|
||||
? message.content
|
||||
: [];
|
||||
return parts.map((p, idx) =>
|
||||
p?.type === "text" && p.text ? <span key={idx}>{p.text}</span> : null
|
||||
p?.type === "text" && p.text ? (
|
||||
<ReactMarkdown
|
||||
key={idx}
|
||||
linkTarget="_blank"
|
||||
components={markdownComponents}
|
||||
>
|
||||
{p.text}
|
||||
</ReactMarkdown>
|
||||
) : null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user