/** * WorthDoing.ai * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai * File: src/components/wd/Markdown.tsx * Description: Sanitized markdown renderer for opportunity reports, with [n] citations linked to evidence. */ "use client"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import type { ReactNode } from "react"; /** Turn bare [n] citation markers inside text nodes into anchor links to #evidence-n. */ function linkCitations(children: ReactNode): ReactNode { const walk = (node: ReactNode, key = 0): ReactNode => { if (typeof node === "string") { const parts = node.split(/(\[\d{1,3}\])/g); if (parts.length === 1) return node; return parts.map((part, i) => { const m = part.match(/^\[(\d{1,3})\]$/); if (!m) return part; return ( {m[1]} ); }); } if (Array.isArray(node)) return node.map((n, i) => walk(n, i)); return node; }; return walk(children); } export function Markdown({ children }: { children: string }) { return (
(

{children}

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

{children}

), p: ({ children }) => (

{linkCitations(children)}

), li: ({ children }) => (
  • {linkCitations(children)}
  • ), a: ({ href, children }) => ( {children} ), strong: ({ children }) => {children}, blockquote: ({ children }) => (
    {children}
    ), code: ({ children }) => ( {children} ), table: ({ children }) => (
    {children}
    ), th: ({ children }) => ( {children} ), td: ({ children }) => ( {linkCitations(children)} ), }} > {children}
    ); }