The MarkdownRenderer component is responsible for rendering markdown content with full GitHub Flavored Markdown (GFM) support and mermaid diagram integration.
Props
The markdown content to render. When empty or null, displays an empty state.
Font scaling factor applied to the rendered markdown (0.5 to 2.0). Updates the --md-scale CSS variable.
Features
GitHub Flavored Markdown
The component uses react-markdown with the remark-gfm plugin to support:
- Tables
- Strikethrough text
- Task lists
- Autolinks
- And all standard markdown features
Mermaid diagram support
Code blocks with the mermaid language identifier are automatically rendered as diagrams using the Mermaid component:
components={{
code({node, inline, className, children, ...props}) {
const match = /language-(\w+)/.exec(className || '');
if (!inline && match && match[1] === 'mermaid') {
return <Mermaid chart={String(children).replace(/\n$/, '')} />;
}
return <code className={className} {...props}>{children}</code>;
}
}}
Font size scaling
The component updates a CSS variable when the font size factor changes:
React.useEffect(() => {
document.documentElement.style.setProperty('--md-scale', fontSizeFactor);
}, [fontSizeFactor]);
This allows dynamic font scaling across all markdown content without re-rendering.
Empty state
When no content is provided, the component displays a friendly empty state:
if (!content) {
return (
<div className="empty-state">
<FileText size={48} className="empty-icon" />
<h2 style={{ marginBottom: '8px', color: 'var(--text-primary)' }}>No file selected</h2>
<p>Open a markdown file from the sidebar or click upload on the toolbar.</p>
</div>
);
}
Implementation example
Here’s how the component is used in the main App:
import MarkdownRenderer from './components/MarkdownRenderer';
function App() {
const [fontSizeFactor, setFontSizeFactor] = useState(1.0);
const activeContent = files.find(f => f.id === activeFileId)?.content || '';
return (
<MarkdownRenderer
content={activeContent}
fontSizeFactor={fontSizeFactor}
/>
);
}
Structure
The rendered output is wrapped in two containers:
<div className="content-scroll">
<div className="markdown-body">
<ReactMarkdown remarkPlugins={[remarkGfm]}>
{content}
</ReactMarkdown>
</div>
</div>
content-scroll: Provides scrollable container
markdown-body: Applies GitHub-style markdown CSS classes