'use client'; /** * PostPreview — рендерит пост так, как он будет выглядеть в TG / VK / MAX. * Props: * text — текст поста (Markdown-разметка TG) * imageUrl — URL картинки (опционально) * platform — 'telegram' | 'vk' | 'max' * channelName — название канала (для шапки) */ import { useState } from 'react'; import { Eye, EyeOff, MessageCircle, Heart, Share2, Bookmark, ThumbsUp, BarChart2, AlertCircle } from 'lucide-react'; // ── Лимиты платформ ─────────────────────────────────────────────────────────── const LIMITS = { telegram: { text: 4096, caption: 1024, label: 'Telegram' }, vk: { text: 16384, caption: 2048, label: 'ВКонтакте' }, max: { text: 4096, caption: 1024, label: 'MAX' }, }; // ── Парсер разметки → HTML ──────────────────────────────────────────────────── function parseTgMarkdown(text) { // Экранируем HTML-спецсимволы let s = text .replace(/&/g, '&') .replace(//g, '>'); // **bold** или __bold__ s = s.replace(/\*\*(.+?)\*\*/gs, '$1'); s = s.replace(/__(.+?)__/gs, '$1'); // _italic_ или *italic* s = s.replace(/(?$1'); s = s.replace(/(?$1'); // `code` s = s.replace(/`([^`]+)`/g, '$1'); // ```block``` s = s.replace(/```[\w]*\n?([\s\S]*?)```/g, '
$1
'); // [text](url) s = s.replace(/\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g, '$1'); // Переносы строк →
s = s.replace(/\n/g, '
'); return s; } function parseVkMarkdown(text) { // VK не поддерживает Markdown — убираем разметку, оставляем текст let s = text .replace(/\*\*(.+?)\*\*/gs, '$1') .replace(/__(.+?)__/gs, '$1') .replace(/(?/g, '>') .replace(/\n/g, '
'); return s; } function renderMarkdown(text, platform) { if (!text) return ''; if (platform === 'vk') return parseVkMarkdown(text); return parseTgMarkdown(text); // telegram + max } // ── Счётчик символов ────────────────────────────────────────────────────────── function CharCounter({ text, imageUrl, platform }) { const limits = LIMITS[platform] || LIMITS.telegram; const limit = imageUrl ? limits.caption : limits.text; const len = (text || '').length; const pct = Math.min(len / limit, 1); const over = len > limit; const color = over ? 'text-red-400' : pct > 0.85 ? 'text-yellow-400' : 'text-text-mute'; return (
{over && } {len} / {limit}{imageUrl ? ' (caption)' : ''} {over && превышен лимит}
); } // ── TG Preview ──────────────────────────────────────────────────────────────── function TelegramPreview({ text, imageUrl, channelName }) { const html = renderMarkdown(text, 'telegram'); return (
{/* Header */}
{(channelName || 'Z').slice(0, 1).toUpperCase()}
{channelName || 'Канал'}
только что
{/* Контент */}
{imageUrl && ( { e.target.style.display = 'none'; }} /> )}
Текст поста появится здесь…' }} />
{/* Footer */}
1.2K 14
{/* TG inline styles */}
); } // ── VK Preview ──────────────────────────────────────────────────────────────── function VkPreview({ text, imageUrl, channelName }) { const html = renderMarkdown(text, 'vk'); return (
{/* Header */}
{(channelName || 'K').slice(0, 1).toUpperCase()}
{channelName || 'Сообщество'}
только что
···
{/* Контент */}
Текст поста появится здесь…' }} /> {imageUrl && ( { e.target.style.display = 'none'; }} /> )}
{/* Footer */}
891
); } // ── MAX Preview ─────────────────────────────────────────────────────────────── function MaxPreview({ text, imageUrl, channelName }) { const html = renderMarkdown(text, 'max'); return (
{/* Header */}
{(channelName || 'M').slice(0, 1).toUpperCase()}
{channelName || 'Канал MAX'}
только что
{/* Контент */}
{imageUrl && ( { e.target.style.display = 'none'; }} /> )}
Текст поста появится здесь…' }} />
{/* Footer */}
432 18 Опрос
); } // ── Главный экспорт ─────────────────────────────────────────────────────────── const PLATFORM_ORDER = ['telegram', 'vk', 'max']; const PLATFORM_LABELS = { telegram: 'TG', vk: 'VK', max: 'MAX' }; export default function PostPreview({ text, imageUrl, platform: defaultPlatform = 'telegram', channelName }) { const [visible, setVisible] = useState(true); const [platform, setPlatform] = useState(defaultPlatform); if (!visible) { return ( ); } return (
{/* Тулбар */}
Превью
{/* Переключатель платформы */}
{PLATFORM_ORDER.map(p => ( ))}
{/* Скрыть */}
{/* Счётчик символов */} {/* Превью платформы */} {platform === 'telegram' && ( )} {platform === 'vk' && ( )} {platform === 'max' && ( )} {/* Лимит */}
{LIMITS[platform].label}: текст до {LIMITS[platform].text.toLocaleString()} симв. {', caption (с фото) до '}{LIMITS[platform].caption.toLocaleString()} симв.
); }