UNPKG

plazbot

Version:

Official Plazbot SDK for creating AI agents for WhatsApp, portals, and developers.

130 lines (129 loc) 5.33 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useMemo } from 'react'; import { usePlazbotContext } from '../../context/PlazbotContext'; function tokenize(text) { const tokens = []; const lines = text.split('\n'); let i = 0; while (i < lines.length) { const line = lines[i]; // Bloque de codigo if (line.trimStart().startsWith('```')) { const lang = line.trimStart().slice(3).trim(); const codeLines = []; i++; while (i < lines.length && !lines[i].trimStart().startsWith('```')) { codeLines.push(lines[i]); i++; } tokens.push({ type: 'codeblock', content: codeLines.join('\n'), language: lang || undefined }); i++; continue; } // Heading const headingMatch = line.match(/^(#{1,3})\s+(.+)/); if (headingMatch) { tokens.push({ type: 'heading', content: headingMatch[2], level: headingMatch[1].length }); i++; continue; } // Lista const listMatch = line.match(/^[\s]*[-*]\s+(.+)/); if (listMatch) { tokens.push({ type: 'listitem', content: listMatch[1] }); i++; continue; } // Lista numerada const numListMatch = line.match(/^[\s]*\d+\.\s+(.+)/); if (numListMatch) { tokens.push({ type: 'listitem', content: numListMatch[1] }); i++; continue; } // Linea vacia if (line.trim() === '') { tokens.push({ type: 'br', content: '' }); i++; continue; } // Texto con inline formatting tokens.push({ type: 'text', content: line }); i++; } return tokens; } function renderInline(text, theme) { const result = []; // Patron: bold, italic, code, links const regex = /(\*\*(.+?)\*\*)|(\*(.+?)\*)|(`([^`]+?)`)|(\[(.+?)\]\((.+?)\))/g; let lastIndex = 0; let match; let key = 0; while ((match = regex.exec(text)) !== null) { // Texto antes del match if (match.index > lastIndex) { result.push(text.slice(lastIndex, match.index)); } if (match[2]) { // Bold result.push(_jsx("strong", { children: match[2] }, key++)); } else if (match[4]) { // Italic result.push(_jsx("em", { children: match[4] }, key++)); } else if (match[6]) { // Inline code result.push(_jsx("code", { style: { backgroundColor: 'rgba(0,0,0,0.06)', padding: '2px 6px', borderRadius: '4px', fontSize: '0.9em', fontFamily: 'monospace', }, children: match[6] }, key++)); } else if (match[8] && match[9]) { // Link result.push(_jsx("a", { href: match[9], target: "_blank", rel: "noopener noreferrer", style: { color: theme.primaryColor, textDecoration: 'underline' }, children: match[8] }, key++)); } lastIndex = match.index + match[0].length; } if (lastIndex < text.length) { result.push(text.slice(lastIndex)); } return result.length > 0 ? result : [text]; } export function MarkdownRenderer({ content, className, style }) { const { theme } = usePlazbotContext(); const elements = useMemo(() => { const tokens = tokenize(content); return tokens.map((token, i) => { switch (token.type) { case 'heading': { const fontSize = token.level === 1 ? '1.3em' : token.level === 2 ? '1.15em' : '1.05em'; return (_jsx("div", { style: { fontSize, fontWeight: 600, margin: '8px 0 4px' }, children: renderInline(token.content, theme) }, i)); } case 'codeblock': return (_jsx("pre", { style: { backgroundColor: 'rgba(0,0,0,0.06)', padding: '12px', borderRadius: '6px', overflow: 'auto', fontSize: '0.85em', fontFamily: 'monospace', margin: '8px 0', whiteSpace: 'pre-wrap', wordBreak: 'break-word', }, children: _jsx("code", { children: token.content }) }, i)); case 'listitem': return (_jsxs("div", { style: { display: 'flex', gap: '8px', margin: '2px 0', paddingLeft: '4px' }, children: [_jsx("span", { style: { color: theme.textSecondary }, children: "\u2022" }), _jsx("span", { children: renderInline(token.content, theme) })] }, i)); case 'br': return _jsx("div", { style: { height: '8px' } }, i); default: return (_jsx("div", { style: { margin: '2px 0', lineHeight: 1.6 }, children: renderInline(token.content, theme) }, i)); } }); }, [content, theme]); return (_jsx("div", { className: className, style: { wordBreak: 'break-word', ...style }, children: elements })); }