Spaces:
Running
Running
| "use client"; | |
| import type { ReactNode } from "react"; | |
| import ReactMarkdown from "react-markdown"; | |
| import remarkGfm from "remark-gfm"; | |
| import { HelpCircle } from "lucide-react"; | |
| import { Button } from "@/components/ui/button"; | |
| function nodeText(value: ReactNode): string { | |
| if (typeof value === "string" || typeof value === "number") { | |
| return String(value); | |
| } | |
| if (Array.isArray(value)) { | |
| return value.map((item) => nodeText(item)).join(""); | |
| } | |
| if (value && typeof value === "object" && "props" in value) { | |
| return nodeText((value as { props?: { children?: ReactNode } }).props?.children); | |
| } | |
| return ""; | |
| } | |
| export function MarkdownContent(props: { | |
| content: string; | |
| onAskExcerpt?: (excerpt: string) => void; | |
| }) { | |
| const { content, onAskExcerpt } = props; | |
| return ( | |
| <div className="markdown-content text-sm text-foreground"> | |
| <ReactMarkdown | |
| remarkPlugins={[remarkGfm]} | |
| components={ | |
| onAskExcerpt | |
| ? { | |
| p({ children }) { | |
| const excerpt = nodeText(children).trim(); | |
| return ( | |
| <div className="mb-4 space-y-1.5 last:mb-0"> | |
| <p>{children}</p> | |
| {excerpt ? ( | |
| <Button | |
| type="button" | |
| variant="ghost" | |
| className="h-7 rounded-lg px-2 text-[11px] text-muted-foreground" | |
| onClick={() => onAskExcerpt(excerpt)} | |
| > | |
| <HelpCircle className="h-3.5 w-3.5" /> | |
| <span className="ml-1">Ask about this paragraph</span> | |
| </Button> | |
| ) : null} | |
| </div> | |
| ); | |
| }, | |
| li({ children }) { | |
| const excerpt = nodeText(children).trim(); | |
| return ( | |
| <li> | |
| <div className="space-y-1.5"> | |
| <div>{children}</div> | |
| {excerpt ? ( | |
| <Button | |
| type="button" | |
| variant="ghost" | |
| className="h-7 rounded-lg px-2 text-[11px] text-muted-foreground" | |
| onClick={() => onAskExcerpt(excerpt)} | |
| > | |
| <HelpCircle className="h-3.5 w-3.5" /> | |
| <span className="ml-1">Ask about this item</span> | |
| </Button> | |
| ) : null} | |
| </div> | |
| </li> | |
| ); | |
| }, | |
| } | |
| : undefined | |
| } | |
| > | |
| {content} | |
| </ReactMarkdown> | |
| </div> | |
| ); | |
| } | |