import React from 'react'; interface TacticalMarkdownRendererProps { content: string; isChat?: boolean; } // Inline parser for bold, italic, inline-code, and tags const parseInline = (text: string): React.ReactNode[] => { if (!text) return []; // Match bold (**text**), inline code (`text`), italic (*text* or _text_) const tokens: React.ReactNode[] = []; let remaining = text; let key = 0; while (remaining.length > 0) { // Check for bold **...** or __...__ const boldMatch = remaining.match(/^(\*\*|__)(.*?)\1/); if (boldMatch) { tokens.push( {parseInline(boldMatch[2])} ); remaining = remaining.slice(boldMatch[0].length); continue; } // Check for inline code `...` const codeMatch = remaining.match(/^`([^`]+)`/); if (codeMatch) { tokens.push( {codeMatch[1]} ); remaining = remaining.slice(codeMatch[0].length); continue; } // Check for italic *...* or _..._ const italicMatch = remaining.match(/^(\*|_)(.*?)\1/); if (italicMatch) { tokens.push( {parseInline(italicMatch[2])} ); remaining = remaining.slice(italicMatch[0].length); continue; } // Regular text until the next special character const nextSpecial = remaining.search(/[\*_`]/); if (nextSpecial === -1) { tokens.push(remaining); break; } else if (nextSpecial === 0) { // Stray character, consume it as plain text tokens.push(remaining[0]); remaining = remaining.slice(1); } else { tokens.push(remaining.slice(0, nextSpecial)); remaining = remaining.slice(nextSpecial); } } return tokens; }; export const TacticalMarkdownRenderer: React.FC = ({ content, isChat = false }) => { if (!content) return null; const lines = content.split('\n'); const elements: React.ReactNode[] = []; let currentList: { type: 'ul' | 'ol'; items: React.ReactNode[] } | null = null; let elementKey = 0; const flushList = () => { if (currentList) { if (currentList.type === 'ul') { elements.push( ); } else { elements.push(
    {currentList.items.map((item, idx) => (
  1. {item}
  2. ))}
); } currentList = null; } }; for (let i = 0; i < lines.length; i++) { const rawLine = lines[i]; const trimmed = rawLine.trim(); // Empty lines if (!trimmed) { flushList(); continue; } // Horizontal Rule (--- or *** or ___) if (/^(\-{3,}|\*{3,}|_{3,})$/.test(trimmed)) { flushList(); elements.push(
); continue; } // Headers const h1Match = trimmed.match(/^#\s+(.+)$/); if (h1Match) { flushList(); elements.push(

{parseInline(h1Match[1])}

); continue; } const h2Match = trimmed.match(/^##\s+(.+)$/); if (h2Match) { flushList(); elements.push(

{parseInline(h2Match[1])}

); continue; } const h3Match = trimmed.match(/^###\s+(.+)$/); if (h3Match) { flushList(); elements.push(

{parseInline(h3Match[1])}

); continue; } const h4Match = trimmed.match(/^####\s+(.+)$/); if (h4Match) { flushList(); elements.push(

{parseInline(h4Match[1])}

); continue; } // Unordered List Items (- or * or •) const ulMatch = trimmed.match(/^[-*•]\s+(.+)$/); if (ulMatch) { if (!currentList || currentList.type !== 'ul') { flushList(); currentList = { type: 'ul', items: [] }; } currentList.items.push(parseInline(ulMatch[1])); continue; } // Ordered List Items (1. , 2. ) const olMatch = trimmed.match(/^(\d+)\.\s+(.+)$/); if (olMatch) { if (!currentList || currentList.type !== 'ol') { flushList(); currentList = { type: 'ol', items: [] }; } currentList.items.push(parseInline(olMatch[2])); continue; } // Blockquote (> ...) const bqMatch = trimmed.match(/^>\s*(.+)$/); if (bqMatch) { flushList(); elements.push(
{parseInline(bqMatch[1])}
); continue; } // Regular Paragraph flushList(); elements.push(

{parseInline(trimmed)}

); } flushList(); return (
{elements}
); };