TypeScript 97.4%
SQL 1%
JavaScript 0.9%
CSS 0.6%
1"use client";2import * as React from "react";3import ReactMarkdown, { type Components } from "react-markdown";4import remarkGfm from "remark-gfm";5import { CopyButton } from "@/components/ui/misc";6import { cn } from "@/lib/utils";78/**9 * Lightweight Markdown renderer for public pages (share view). GFM, monospace code blocks with a10 * copy button, no syntax highlighting, no raw HTML.11 */1213function textOf(node: React.ReactNode): string {14 if (node == null || typeof node === "boolean") return "";15 if (typeof node === "string" || typeof node === "number") return String(node);16 if (Array.isArray(node)) return node.map(textOf).join("");17 if (React.isValidElement<{ children?: React.ReactNode }>(node)) return textOf(node.props.children);18 return "";19}2021function Pre({ children }: React.HTMLAttributes<HTMLPreElement>) {22 const codeEl = React.Children.toArray(children).find((c) => React.isValidElement(c)) as React.ReactElement<{ className?: string; children?: React.ReactNode }> | undefined;23 const lang = codeEl?.props.className?.match(/language-([\w+-]+)/)?.[1];24 const raw = textOf(codeEl?.props.children ?? children).replace(/\n$/, "");25 return (26 <div className="group relative my-1 overflow-hidden rounded-lg border border-border bg-bg-subtle">27 <div className="flex h-8 items-center justify-between border-b border-border px-3">28 <span className="font-mono text-[11px] text-fg-subtle">{lang ?? "code"}</span>29 <CopyButton value={raw} size="xs" className="-mr-1.5 h-6 text-[11px] text-fg-subtle opacity-70 group-hover:opacity-100" />30 </div>31 <pre className="overflow-x-auto p-3 text-[12.5px] leading-6 scrollbar-thin">32 <code className={cn("font-mono", codeEl?.props.className)}>{codeEl ? codeEl.props.children : children}</code>33 </pre>34 </div>35 );36}3738const components: Components = {39 pre: Pre,40 a: ({ href, children }) => (41 <a href={href} target="_blank" rel="noopener noreferrer nofollow">42 {children}43 </a>44 ),45 table: ({ children }) => (46 <div className="overflow-x-auto">47 <table>{children}</table>48 </div>49 ),50};5152export function SimpleMarkdown({ children, className }: { children: string; className?: string }) {53 return (54 <div className={cn("prose-chat", className)}>55 <ReactMarkdown remarkPlugins={[remarkGfm]} components={components} skipHtml>56 {children}57 </ReactMarkdown>58 </div>59 );60}61