"use client"; import { type ReactNode, type ReactElement, isValidElement, } from "react"; import { CopyButton } from "./copy-button"; type Props = { children?: ReactNode; className?: string; title?: string; // rehype-pretty-code adds data attributes such as data-language; capture them via index signature [key: string]: unknown; }; const TERMINAL_LANGS = new Set(["bash", "sh", "shell", "zsh"]); const WIZARD_GLYPHS = /^\s*[◆◇◯◐○●]/; function extractText(node: ReactNode): string { if (typeof node === "string") return node; if (typeof node === "number") return String(node); if (Array.isArray(node)) return node.map(extractText).join(""); if (isValidElement(node)) { const props = (node as ReactElement<{ children?: ReactNode }>).props; return extractText(props.children); } return ""; } function detectLanguage(props: Props, children: ReactNode): string | null { const dataLang = props["data-language"]; if (typeof dataLang === "string" && dataLang) return dataLang; const className = typeof props.className === "string" ? props.className : ""; const m = className.match(/language-([\w-]+)/); if (m) return m[1]; if (isValidElement(children)) { const childProps = (children as ReactElement<{ className?: string }>).props; const childClass = typeof childProps.className === "string" ? childProps.className : ""; const cm = childClass.match(/language-([\w-]+)/); if (cm) return cm[1]; } return null; } export function CodeBlock(props: Props) { const { children, title, className: _ignored, ...rest } = props; const language = detectLanguage(props, children); const codeText = extractText(children); const isTerminal = language !== null && TERMINAL_LANGS.has(language); const isOutput = !isTerminal && WIZARD_GLYPHS.test(codeText); const hasTitle = typeof title === "string" && title.length > 0; // Mode A — Terminal (commands the user types) if (isTerminal) { return (
{hasTitle ? title : "zsh"}
          {children}
        
); } // Mode D — Output preview (wizard prompts, terminal output) if (isOutput) { return (
output
          {children}
        
); } // Mode B — VS Code tab (filename present) if (hasTitle) { return (
{title} {language && {language}}
          {children}
        
); } // Mode C — Minimal default return (
{language && {language}}
        {children}
      
); }