import { cva } from "class-variance-authority"; import React, { Suspense } from "react"; import { violet } from "tailwindcss/colors"; import { customColors } from "@sparkle/lib/colors"; const SyntaxHighlighter = React.lazy( () => import("react-syntax-highlighter/dist/esm/default-highlight") ); export const codeInlineVariants = cva( [ "s-mx-0.5 s-my-0.5 s-cursor-text s-rounded-md s-border s-px-1 s-py-0.5", "s-border-border dark:s-border-border-night", "s-text-[0.90em]", "s-text-golden-600 dark:s-text-golden-600-night", ], { variants: { variant: { surface: ["s-bg-muted/70 dark:s-bg-muted-night/70"], }, }, defaultVariants: { variant: "surface", }, } ); export const codeBlockVariants = cva( [ "s-mx-0.5 s-my-0.5 s-cursor-text s-rounded-md s-border s-p-2", "s-border-border dark:s-border-border-night", "s-text-[0.90em]", ], { variants: { variant: { surface: ["s-bg-muted/70 dark:s-bg-muted-night/70"], }, }, defaultVariants: { variant: "surface", }, } ); type CodeBlockProps = { children?: React.ReactNode; className?: string; inline?: boolean; variant?: "surface"; wrapLongLines?: boolean; showLineNumber?: boolean; }; export function CodeBlock({ children, className, inline, variant = "surface", wrapLongLines = false, showLineNumber = false, }: CodeBlockProps): JSX.Element { const match = /language-(\w+)/.exec(className || ""); const language = match ? match[1] : "text"; const languageOverrides: { [key: string]: string } = { jsx: "javascript", tsx: "typescript", py: "python", }; const languageToUse = languageOverrides[language] || language; const codeStyle = { hljs: { display: "block", overflowX: "auto", padding: "1em", color: "var(--s-foreground)", backgroundColor: "transparent", fontSize: "0.875rem", }, "hljs-ln": { color: "var(--s-muted-foreground)", fontSize: "0.75rem", paddingRight: "1em", textAlign: "right", userSelect: "none", }, "hljs-keyword": { // function, const, let, if, return color: violet[500], }, "hljs-function": { color: customColors.blue[600], }, "hljs-title": { // Function names color: customColors.blue[600], }, "hljs-built_in": { // document, console, Date color: customColors.golden[500], }, "hljs-string": { // Regular strings color: customColors.green[500], }, "hljs-variable": { // Regular variables color: "var(--s-foreground)", }, "hljs-literal": { // true, false, null color: customColors.golden[500], }, "hljs-number": { // Numeric values color: customColors.golden[500], }, "hljs-comment": { // Comments color: customColors.golden[700], }, "hljs-template-variable": { // Template literal variables ${...} color: customColors.rose[500], }, "hljs-property": { // Object properties color: "var(--s-foreground)", }, "hljs-punctuation": { // Brackets, dots, etc color: "var(--s-foreground)", }, "hljs-operator": { // =, +, -, etc color: violet[500], }, "hljs-method": { // Method calls color: customColors.blue[600], }, "hljs-tag": { // HTML tags color: customColors.rose[500], }, "hljs-name": { // Tag names color: customColors.rose[500], }, "hljs-attr": { // HTML attributes color: customColors.golden[500], }, "hljs-params": { // Function parameters color: "var(--s-foreground)", }, // Typography styles "hljs-emphasis": { fontStyle: "italic", }, "hljs-strong": { fontWeight: "bold", }, }; return !inline ? ( }>
{String(children).replace(/\n$/, "")}
) : ( {children} ); }