import React from "react";
import { parseTextMarkup, hasTextMarkup, type TextMarkupSegment } from "@/lib/text-markup";
import { cn } from "@/lib/utils";
interface MarkupTextProps {
children: string;
className?: string;
as?: keyof React.JSX.IntrinsicElements;
boldClassName?: string;
strikeClassName?: string;
}
/**
* Компонент для рендеринга текста с разметкой **bold** и ~~strike~~
*
* Примеры использования:
* Добро пожаловать в **WitLab**!
* **50%** скидка только сегодня
* Ваш **идеальный партнер** найден!
*/
export function MarkupText({
children,
className,
as: Component = "span",
boldClassName = "font-bold",
strikeClassName = "line-through"
}: MarkupTextProps) {
// Если текста нет, возвращаем пустой элемент
if (!children || typeof children !== 'string') {
return React.createElement(Component as string, { className }, children);
}
// Если нет разметки, возвращаем обычный текст
if (!hasTextMarkup(children)) {
return React.createElement(Component as string, { className }, children);
}
// Парсим разметку и рендерим сегменты
const segments = parseTextMarkup(children);
return React.createElement(
Component as string,
{ className },
segments.map((segment: TextMarkupSegment, index: number) => {
if (segment.type === 'bold') {
return React.createElement(
'strong',
{
key: index,
className: cn(boldClassName)
},
segment.content
);
}
if (segment.type === 'strike') {
return React.createElement(
'span',
{
key: index,
className: cn(strikeClassName)
},
segment.content
);
}
return React.createElement(
React.Fragment,
{ key: index },
segment.content
);
})
);
}
/**
* Хук для проверки наличия разметки в тексте
*/
export function useHasMarkup(text: string): boolean {
return React.useMemo(() => hasTextMarkup(text), [text]);
}
/**
* Компонент для превью разметки в админке
*/
export function MarkupPreview({ text }: { text: string }) {
return (
Превью:
{text}
{hasTextMarkup(text) && (
💡 Разметка обнаружена: Текст в **двойных звездочках** — жирный, в ~~двойных тильдах~~ — зачёркнутый.
)}
);
}