"use client"; import { isValidElement, type ReactNode } from "react"; import remarkGfm from "remark-gfm"; import remarkBreaks from "remark-breaks"; import remarkGemoji from "remark-gemoji"; import { InlineCode } from "@/components/task/chat/messages/inline-code"; import { CodeBlock } from "@/components/task/chat/messages/code-block"; /** Shared remark plugins used by all markdown renderers */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export const remarkPlugins: any[] = [remarkGfm, remarkBreaks, remarkGemoji]; /** * Recursively extracts text content from React children. * Optimized with fast paths for common cases (string/number). */ export function getTextContent(children: ReactNode): string { if (typeof children === "string") return children; if (typeof children === "number") return String(children); if (children == null) return ""; if (Array.isArray(children)) { let result = ""; for (let i = 0; i < children.length; i++) { result += getTextContent(children[i]); } return result; } if (isValidElement(children)) { const props = children.props as { children?: ReactNode }; if (props.children) { return getTextContent(props.children); } } return ""; } /** * Shared markdown component overrides for ReactMarkdown. * Used by both chat messages and PR comment/review rendering. */ export const markdownComponents = { code: ({ className, children }: { className?: string; children?: ReactNode }) => { const content = getTextContent(children).replace(/\n$/, ""); const hasLanguage = className?.startsWith("language-"); const hasNewlines = content.includes("\n"); if (hasLanguage || hasNewlines) { return {content}; } return {content}; }, ol: ({ children }: { children?: ReactNode }) => (
    {children}
), ul: ({ children }: { children?: ReactNode }) => ( ), li: ({ children }: { children?: ReactNode }) =>
  • {children}
  • , a: ({ href, children }: { href?: string; children?: ReactNode }) => ( {children} ), p: ({ children }: { children?: ReactNode }) =>

    {children}

    , h1: ({ children }: { children?: ReactNode }) => (

    {children}

    ), h2: ({ children }: { children?: ReactNode }) => (

    {children}

    ), h3: ({ children }: { children?: ReactNode }) => (

    {children}

    ), h4: ({ children }: { children?: ReactNode }) => (

    {children}

    ), h5: ({ children }: { children?: ReactNode }) => (
    {children}
    ), hr: ({ children }: { children?: ReactNode }) =>
    {children}, table: ({ children }: { children?: ReactNode }) => (
    {children}
    ), thead: ({ children }: { children?: ReactNode }) => ( {children} ), tbody: ({ children }: { children?: ReactNode }) => ( {children} ), tr: ({ children }: { children?: ReactNode }) => ( {children} ), th: ({ children }: { children?: ReactNode }) => ( {children} ), td: ({ children }: { children?: ReactNode }) => ( {children} ), };