import { ReactElement } from "react"; import SyntaxHighlighter from "react-syntax-highlighter"; import createElement from "react-syntax-highlighter/dist/esm/create-element"; import { atomOneDark } from "react-syntax-highlighter/dist/esm/styles/hljs"; import { cn } from "@/app/common/utils"; import { capitalizeFirstLetter } from "@/app/common/string-utils"; type CodeHighlighterProps = { /** * The code to highlight. */ code: string; /** * The language of the code. */ language?: string; /** * Should the element be rounded? */ rounded?: boolean; }; /** * Render the rows with the ability to render links. * * @param rows the rows to render * @param stylesheet the stylesheet to use * @param useInlineStyles should inline styles be used * @returns the rendered rows */ function rowRenderer({ rows, stylesheet, useInlineStyles, }: { rows: any; stylesheet: { [key: string]: React.CSSProperties }; useInlineStyles: boolean; }) { return rows.map((node: any, i: number) => { node.children = node.children.map((children: any) => { const text = children?.children?.[0]?.value; if (typeof text === "string" && text.startsWith('"http')) { return { ...children, tagName: "a", properties: { ...children.properties, href: text.slice(1, -1), // in JSON strings are enclosed with ", they need to be removed target: "_blank", // Tailwind CSS classes class: "underline !text-primary hover:!text-muted-foreground transition-all", }, }; } return children; }); return createElement({ node, stylesheet, useInlineStyles, key: `code-segement${i}`, }); }); } export function CodeHighlighter({ code, language = "json", rounded = true }: CodeHighlighterProps): ReactElement { return (
{/* Language */}
{capitalizeFirstLetter(language)}
{/* Code */} {code}
); }