Skip to main content
The MarkdownRenderer component is responsible for rendering markdown content with full GitHub Flavored Markdown (GFM) support and mermaid diagram integration.

Props

content
string
The markdown content to render. When empty or null, displays an empty state.
fontSizeFactor
number
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

Build docs developers (and LLMs) love