/** * Универсальная система разметки текста для WitLab Funnel * * Поддерживаемые теги: * **текст** - жирный текст * * Примеры использования: * "Добро пожаловать в **WitLab**!" → "Добро пожаловать в WitLab!" * "**50%** скидка только сегодня" → "50% скидка только сегодня" */ export interface TextMarkupSegment { type: 'text' | 'bold'; content: string; } /** * Парсит текст с разметкой **bold** и возвращает массив сегментов */ export function parseTextMarkup(text: string): TextMarkupSegment[] { if (!text || typeof text !== 'string') { return [{ type: 'text', content: text || '' }]; } const segments: TextMarkupSegment[] = []; const boldRegex = /\*\*(.*?)\*\*/g; let lastIndex = 0; let match; while ((match = boldRegex.exec(text)) !== null) { const matchStart = match.index; const matchEnd = boldRegex.lastIndex; const boldContent = match[1]; // Добавляем обычный текст перед жирным (если есть) if (matchStart > lastIndex) { const normalText = text.slice(lastIndex, matchStart); if (normalText) { segments.push({ type: 'text', content: normalText }); } } // Добавляем жирный текст if (boldContent) { segments.push({ type: 'bold', content: boldContent }); } lastIndex = matchEnd; } // Добавляем оставшийся обычный текст if (lastIndex < text.length) { const remainingText = text.slice(lastIndex); if (remainingText) { segments.push({ type: 'text', content: remainingText }); } } // Если нет жирного текста, возвращаем весь текст как обычный if (segments.length === 0) { segments.push({ type: 'text', content: text }); } return segments; } /** * Проверяет, содержит ли текст разметку */ export function hasTextMarkup(text: string): boolean { return /\*\*(.*?)\*\*/g.test(text || ''); } /** * Убирает разметку из текста, оставляя только чистый текст */ export function stripTextMarkup(text: string): string { if (!text || typeof text !== 'string') { return text || ''; } return text.replace(/\*\*(.*?)\*\*/g, '$1'); } /** * Примеры для тестирования */ export const MARKUP_EXAMPLES = [ { input: "Добро пожаловать в **WitLab**!", description: "Выделение названия продукта" }, { input: "**50%** скидка только сегодня", description: "Выделение процента скидки" }, { input: "Ваш **идеальный партнер** найден!", description: "Выделение ключевой фразы" }, { input: "**Анализ завершен** - переходим к результатам", description: "Выделение статуса" }, { input: "Поздравляем, **Анна**! Ваш портрет готов.", description: "Выделение имени пользователя" } ] as const;