A React component library for rendering code with live preview and syntax highlighting.
✨ Highlight: Import .md files as React components - write markdown, get interactive demos instantly!
✨ Features
- 📝 Native Markdown Parsing - Import
.mdfiles and render embedded code blocks as interactive components - 🎨 Live Preview - Execute and preview React code in real-time
- ✏️ Editable Code - Built-in code editor with syntax highlighting
- 🔌 Universal Plugin - Works with Webpack, Vite, Rollup, esbuild, and Rspack
- 🎯 TypeScript - Full TypeScript support out of the box
- 📦 Tree-shakeable - Import only what you need
- ⚡ Zero Config - Works out of the box with sensible defaults
✅ Requirements
- Node.js >= 18
- PNPM >= 8 (monorepo managed via PNPM + Turbo)
📦 Installation
# npm npm install @react-code-view/react @react-code-view/unplugin # pnpm pnpm add @react-code-view/react @react-code-view/unplugin # yarn yarn add @react-code-view/react @react-code-view/unplugin
Note:
@react-code-view/unpluginis needed if you want to import.mdfiles directly as React components. For basic CodeView usage without markdown imports, you only need@react-code-view/react.
🚀 Quick Start
⭐ Import Markdown as React Components
The most convenient way - configure once, use everywhere!
1. Configure your build tool (Vite example):
// vite.config.js import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import reactCodeView from '@react-code-view/unplugin/vite'; export default defineConfig({ plugins: [ react(), reactCodeView() // That's it! ] });
2. Create your markdown file (demo.md):
# Interactive Counter Here's a live counter component: <!--start-code--> \`\`\`jsx function Counter() { const [count, setCount] = useState(0); return ( <button onClick={() => setCount(count + 1)}> Clicked {count} times </button> ); } render(<Counter />); \`\`\` <!--end-code--> The code above is **fully interactive**!
3. Import and use like any React component:
import Demo from './demo.md'; function App() { return <Demo />; }
That's it! 🎉 Your markdown is now a React component with:
- ✅ Live, interactive code blocks
- ✅ Automatic syntax highlighting
- ✅ Type-safe imports
- ✅ Full TypeScript support
Alternative: Runtime Parsing (No Build Config)
If you prefer not to configure a build tool:
import { CodeView } from '@react-code-view/react'; import markdown from './demo.md?raw'; <CodeView dependencies={{ useState: React.useState }}> {markdown} </CodeView>
Basic Code Preview
For simple code snippets without markdown:
import { CodeView } from '@react-code-view/react'; const code = ` <button onClick={() => alert('Hello!')}> Click me </button> `; <CodeView language="jsx" editable renderPreview> {code} </CodeView>
📚 Packages
This monorepo contains the following packages:
| Package | Version | Description |
|---|---|---|
@react-code-view/react |
React components | |
@react-code-view/core |
Core transformation utilities | |
@react-code-view/unplugin |
Build tool plugins |
🔧 Build Tool Integration
React Code View supports all major build tools through unplugin.
Once configured, you can import .md files as React components - the most convenient way to create interactive documentation!
Why this is amazing:
- 📝 Write markdown files with code examples
- 🎯 Import them like regular React components
- ⚡ Get live, interactive demos automatically
- 🔒 Full TypeScript support and type safety
- 🎨 Pass props like
theme,dependencies, etc.
Example:
import Demo from './example.md'; function App() { return ( <div> <Demo theme="rcv-theme-dark" /> </div> ); }
Vite
// vite.config.js import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import reactCodeView from '@react-code-view/unplugin/vite'; export default defineConfig({ plugins: [ react(), reactCodeView() ] });
Webpack
// webpack.config.js const ReactCodeViewPlugin = require('@react-code-view/unplugin/webpack'); module.exports = { plugins: [ ReactCodeViewPlugin() ] };
Rollup
// rollup.config.js import reactCodeView from '@react-code-view/unplugin/rollup'; export default { plugins: [ reactCodeView() ] };
esbuild
import * as esbuild from 'esbuild'; import reactCodeView from '@react-code-view/unplugin/esbuild'; await esbuild.build({ plugins: [ reactCodeView() ] });
Rspack
// rspack.config.js const ReactCodeViewPlugin = require('@react-code-view/unplugin/rspack'); module.exports = { plugins: [ ReactCodeViewPlugin() ] };
📖 API Reference
CodeView Props
| Prop | Type | Default | Description |
|---|---|---|---|
children |
string |
- | Source code or markdown content to display |
dependencies |
object |
{} |
Dependencies for code execution (e.g., { useState: React.useState }) |
language |
string |
'jsx' |
Syntax highlighting language |
editable |
boolean |
true |
Enable code editing |
renderPreview |
boolean |
true |
Show live preview |
showLineNumbers |
boolean |
true |
Show line numbers |
showCopyButton |
boolean |
true |
Show copy button |
defaultShowCode |
boolean |
false |
Initially show code section |
theme |
string |
'rcv-theme-default' |
Theme class name |
beforeCompile |
function |
- | Transform code before compile |
afterCompile |
function |
- | Transform code after compile |
onChange |
function |
- | Callback when code changes |
onError |
function |
- | Callback when error occurs |
emptyPreviewContent |
ReactNode |
- | Content to display when preview is empty |
Note: When children contains markdown with <!--start-code--> markers, CodeView automatically parses and renders code blocks as interactive components.
Other Components
Renderer- Syntax-highlighted code displayMarkdownRenderer- Render markdown with syntax highlightingCodeEditor- Editable code componentPreview- Display executed code outputCopyCodeButton- Copy code to clipboard buttonErrorBoundary- Error boundary for code execution
Hooks
-
useCodeExecution- Execute code and capture a rendered elementExample:
"import { useCodeExecution } from '@react-code-view/react'; export function LivePreview({ source }: { source: string }) { const { element, error, code, updateCode } = useCodeExecution(source, { // Optional: inject deps into runtime scope dependencies: { alert }, // Optional: configure transforms (e.g. TS + JSX) transformOptions: { transforms: ['typescript', 'jsx'] }, beforeCompile: (c) => c.trim(), afterCompile: (c) => c, onError: (e) => console.error('Execution error:', e) }); return (