/** Утилиты: извлечение превью-картинки и текстового excerpt из HTML-тела поста. */ const IMG_RE = /]+src=["']([^"']+)["'][^>]*>/i; const TAG_RE = /<[^>]+>/g; const WS_RE = /\s+/g; export function firstImage(html: string): string | null { const m = IMG_RE.exec(html); return m ? m[1] : null; } export function plainText(html: string, max = 320): string { const txt = html .replace(//gi, ' ') .replace(//gi, ' ') .replace(//g, ' ') .replace(TAG_RE, ' ') .replace(/ /g, ' ') .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(WS_RE, ' ') .trim(); if (txt.length <= max) return txt; return txt.slice(0, max).replace(/\s+\S*$/, '') + '…'; } export function formatDateRu(d: Date): string { return d.toLocaleDateString('ru-RU', { day: 'numeric', month: 'long', year: 'numeric', }); }