110 lines
3.3 KiB
TypeScript
110 lines
3.3 KiB
TypeScript
/**
|
||
* Универсальная система разметки текста для WitLab Funnel
|
||
*
|
||
* Поддерживаемые теги:
|
||
* **текст** - жирный текст
|
||
*
|
||
* Примеры использования:
|
||
* "Добро пожаловать в **WitLab**!" → "Добро пожаловать в <strong>WitLab</strong>!"
|
||
* "**50%** скидка только сегодня" → "<strong>50%</strong> скидка только сегодня"
|
||
*/
|
||
|
||
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;
|