SPB Git forge

spb/polyllm

Public
15commits 1branches 0releases
2.2 MBsize
maindefault branch
13 days agolast push
TypeScript 97.4% SQL 1% JavaScript 0.9% CSS 0.6%
2.4 KB · 61 lines tsx
Raw Blame History
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