turash/bugulma/frontend/components/chatbot/MarkdownRenderer.tsx

61 lines
1.7 KiB
TypeScript

import React, { useMemo } from 'react';
import { Text } from '@/components/ui/Typography';
interface MarkdownRendererProps {
text: string;
}
const MarkdownRenderer = ({ text }: MarkdownRendererProps) => {
const content = useMemo(() => {
if (!text) return null;
const blocks = text.split(/(\n{2,})/g);
return blocks.map((block, i) => {
if (/^\s*$/.test(block)) {
return null;
}
const lines = block.trim().split('\n');
const isList =
lines.length > 0 &&
lines.every((line) => line.trim().startsWith('* ') || line.trim().startsWith('- '));
if (isList) {
return (
<ul key={i} className="list-disc list-outside pl-5 space-y-1 my-2">
{lines.map((line, j) => {
const lineContent = line.trim().substring(2);
const boldRegex = /\*\*(.*?)\*\*/g;
const parts = lineContent.split(boldRegex);
return (
<li key={j}>
{parts.map((part, k) => (k % 2 === 1 ? <strong key={k}>{part}</strong> : part))}
</li>
);
})}
</ul>
);
} else {
const boldRegex = /\*\*(.*?)\*\*/g;
return (
<div key={i}>
{lines.map((line, j) => (
<Text key={j} className="[&:not(:first-child)]:mt-2">
{line
.split(boldRegex)
.map((part, k) => (k % 2 === 1 ? <strong key={k}>{part}</strong> : part))}
</Text>
))}
</div>
);
}
});
}, [text]);
return <>{content}</>;
};
export default React.memo(MarkdownRenderer);