Version 1.0
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import React from 'react';
|
||||
|
||||
interface MarkdownViewProps {
|
||||
content: string;
|
||||
}
|
||||
|
||||
export const MarkdownView: React.FC<MarkdownViewProps> = ({ content }) => {
|
||||
if (!content) return null;
|
||||
|
||||
// Simple, robust custom Markdown renderer for Mentor responses & challenge specs
|
||||
const lines = content.split('\n');
|
||||
const elements: React.ReactNode[] = [];
|
||||
let inCodeBlock = false;
|
||||
let codeBuffer: string[] = [];
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
if (line.trim().startsWith('```')) {
|
||||
if (inCodeBlock) {
|
||||
elements.push(
|
||||
<pre
|
||||
key={`code-${index}`}
|
||||
className="my-3 p-3 bg-black/70 border border-gray-800 rounded-lg text-xs font-mono text-emerald-400 overflow-x-auto"
|
||||
>
|
||||
<code>{codeBuffer.join('\n')}</code>
|
||||
</pre>
|
||||
);
|
||||
codeBuffer = [];
|
||||
inCodeBlock = false;
|
||||
} else {
|
||||
inCodeBlock = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (inCodeBlock) {
|
||||
codeBuffer.push(line);
|
||||
return;
|
||||
}
|
||||
|
||||
if (line.startsWith('# ')) {
|
||||
elements.push(
|
||||
<h1 key={index} className="text-xl font-bold text-white mt-4 mb-2">
|
||||
{line.replace('# ', '')}
|
||||
</h1>
|
||||
);
|
||||
} else if (line.startsWith('## ')) {
|
||||
elements.push(
|
||||
<h2 key={index} className="text-base font-bold text-blue-400 mt-4 mb-2 border-b border-gray-800 pb-1">
|
||||
{line.replace('## ', '')}
|
||||
</h2>
|
||||
);
|
||||
} else if (line.startsWith('### ')) {
|
||||
elements.push(
|
||||
<h3 key={index} className="text-sm font-bold text-amber-400 mt-3 mb-1">
|
||||
{line.replace('### ', '')}
|
||||
</h3>
|
||||
);
|
||||
} else if (line.startsWith('> ')) {
|
||||
elements.push(
|
||||
<blockquote key={index} className="my-2 p-2 bg-blue-950/40 border-l-4 border-blue-500 rounded-r text-xs text-blue-200 italic">
|
||||
{line.replace('> ', '')}
|
||||
</blockquote>
|
||||
);
|
||||
} else if (line.trim().startsWith('- ') || line.trim().startsWith('* ')) {
|
||||
elements.push(
|
||||
<li key={index} className="ml-4 list-disc text-xs text-gray-300 my-1">
|
||||
{formatInline(line.trim().replace(/^[-*]\s+/, ''))}
|
||||
</li>
|
||||
);
|
||||
} else if (line.trim() === '---') {
|
||||
elements.push(<hr key={index} className="my-3 border-gray-800" />);
|
||||
} else if (line.trim().length > 0) {
|
||||
elements.push(
|
||||
<p key={index} className="text-xs text-gray-300 leading-relaxed my-1.5">
|
||||
{formatInline(line)}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return <div className="space-y-1">{elements}</div>;
|
||||
};
|
||||
|
||||
function formatInline(text: string): React.ReactNode {
|
||||
// Simple bold and inline code formatter
|
||||
const parts = text.split(/(\*\*.*?\*\*|`.*?`)/g);
|
||||
return parts.map((part, i) => {
|
||||
if (part.startsWith('**') && part.endsWith('**')) {
|
||||
return <strong key={i} className="font-semibold text-white">{part.slice(2, -2)}</strong>;
|
||||
}
|
||||
if (part.startsWith('`') && part.endsWith('`')) {
|
||||
return <code key={i} className="px-1.5 py-0.5 bg-gray-800 text-amber-300 font-mono text-[11px] rounded">{part.slice(1, -1)}</code>;
|
||||
}
|
||||
return part;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user