import type { ReactNode } from 'react';
import type { CodeTheme } from '../../lib/code-highlighter';
import { StreamingCodeBlock } from './StreamingCodeBlock';
interface MarkdownContentProps {
content: string;
theme: CodeTheme;
streaming?: boolean;
}
function safeLink(value: string): string | null {
try {
const url = new URL(value, globalThis.location?.href ?? 'https://localhost/');
return url.protocol === 'https:' || url.protocol === 'http:' ? url.href : null;
} catch {
return null;
}
}
function inlineMarkdown(value: string): ReactNode[] {
const parts = value.split(/(`[^`\n]+`|\[[^\]\n]+\]\([^\s)]+\))/g);
return parts.map((part, index) => {
if (part.startsWith('`') && part.endsWith('`')) {
return {part.slice(1, -1)};
}
const link = part.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
if (link) {
const href = safeLink(link[2] ?? '');
if (href) {
return {link[1]};
}
}
return part;
});
}
function renderTextBlock(lines: string[], key: string): ReactNode {
const heading = lines.length === 1 ? lines[0]?.match(/^(#{1,4})\s+(.+)$/) : null;
if (heading) {
const level = heading[1]?.length ?? 2;
const content = inlineMarkdown(heading[2] ?? '');
if (level === 1) return
{inlineMarkdown(lines.map((line) => line.replace(/^>\s?/, '')).join('\n'))}; } return
{lines.flatMap((line, index) => [
...(index > 0 ? [
] : []),
...inlineMarkdown(line),
])}