react-markdown-fences
v1.1.0
Published
Render interactive fence dialects (buttons, charts, diagrams) inside Markdown for React applications
Maintainers
Readme
react-markdown-fences
A React package for rendering interactive fence dialects (buttons, charts, diagrams) inside Markdown for React applications.
Features
- 🎯 Whitelist-only rendering - Only renders known fence types for security
- 🔒 Schema validation - Uses Zod for type-safe payload validation
- ⚡ Lazy loading - Heavy libraries (Chart.js, Mermaid) load only when needed
- 🎨 Customizable - Easy to add new fence renderers
- 📱 SSR friendly - Works with Next.js and other React frameworks
- 🎛️ Clean API - Simple
onActioncallback for user interactions
Installation
npm install react-markdown-fencesRequired Dependencies
npm install react react-dom react-markdown remark-gfm zodOptional Dependencies (for charts/diagrams)
npm install chart.js mermaidQuick Start
import { ChatMarkdown } from 'react-markdown-fences';
function ChatMessage({ content }: { content: string }) {
const handleAction = (actionId: string, payload?: unknown) => {
console.log('Action:', actionId, payload);
// Handle user interactions (API calls, state updates, etc.)
};
return (
<ChatMarkdown
markdown={content}
onAction={handleAction}
/>
);
}Supported Fence Types
Buttons
```button
{"label":"Get Started","action":"demo:start","variant":"primary","size":"lg"}
**Variants:** `primary`, `success`, `warning`, `destructive`
**Sizes:** `xs`, `sm`, `md`, `lg`
### Button Groups
```markdown
```buttongroup
[
{"label":"Accept","action":"demo:accept","variant":"success"},
{"label":"Decline","action":"demo:decline","variant":"destructive"}
]
### Charts (Chart.js)
```markdown
```chartjs
{
"type": "line",
"data": {
"labels": ["Jan", "Feb", "Mar"],
"datasets": [{"label": "Users", "data": [12, 19, 7]}]
},
"options": {"responsive": true}
}
### Diagrams (Mermaid)
```markdown
```mermaid
graph TD
A[User] --> B{Clicks Button}
B -->|Accept| C[Success]
B -->|Decline| D[Cancelled]
## API Reference
### ChatMarkdown Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `markdown` | `string` | - | The markdown content to render |
| `onAction` | `(actionId: string, payload?: unknown) => void` | - | Callback for user interactions |
| `fences` | `FenceMap` | `defaultFences` | Custom fence renderers |
| `showUnknown` | `boolean` | `true` | Whether to show unknown fence types as code blocks |
| `buttonDefaults` | `ButtonDefaults` | - | Default styling for all buttons |
| `chartDefaults` | `ChartDefaults` | - | Default configuration for all charts |
### Developer Customization
#### Button Defaults
Customize the appearance of all buttons in your application:
```tsx
<ChatMarkdown
markdown={content}
onAction={handleAction}
buttonDefaults={{
backgroundColor: "#6366f1",
color: "#ffffff",
borderRadius: "12px",
fontSize: "16px",
padding: "12px 24px",
fontWeight: "600",
hoverBackgroundColor: "#4f46e5",
hoverColor: "#f0f0f0",
hoverTransform: "scale(1.05)"
}}
/>Available button customization options:
backgroundColor- Button background colorcolor- Text colorborderColor- Border colorborderRadius- Border radius (e.g., "8px", "12px")fontSize- Font size (e.g., "14px", "16px")padding- Padding (e.g., "8px 16px")fontWeight- Font weight (e.g., "500", "600", "bold")hoverBackgroundColor- Background color on hoverhoverColor- Text color on hoverhoverTransform- CSS transform on hover (e.g., "scale(1.05)")
Chart Defaults
Customize the appearance of all charts:
<ChatMarkdown
markdown={content}
onAction={handleAction}
chartDefaults={{
width: "100%",
height: "400px",
backgroundColor: "#f9fafb",
borderColor: "#6366f1",
gridColor: "#e5e7eb",
fontFamily: "Inter, sans-serif",
fontSize: 12
}}
/>Available chart customization options:
width- Chart container width (e.g., "100%", "600px")height- Chart container height (e.g., "320px", "400px")backgroundColor- Chart background colorborderColor- Default border color for datasetsgridColor- Grid line colorfontFamily- Font family for labelsfontSize- Font size for labels (number)
Supported Chart Types
Only bar and line charts are supported. Attempting to use other chart types will display an error message.
Types
interface ButtonSpec {
label: string;
action: string;
variant?: 'primary' | 'success' | 'warning' | 'destructive';
size?: 'xs' | 'sm' | 'md' | 'lg';
payload?: unknown;
}
interface ChartJSSpec {
type: string;
data: Record<string, any>;
options?: Record<string, any>;
}Extending with Custom Fences
Add your own fence renderers:
import { ChatMarkdown, defaultFences } from 'react-markdown-fences';
const customFences = {
...defaultFences,
'my-custom': ({ raw, onAction }) => {
const data = JSON.parse(raw);
return <MyCustomComponent data={data} onAction={onAction} />;
}
};
<ChatMarkdown
markdown={content}
fences={customFences}
onAction={handleAction}
/>Security
- Whitelist-only: Only renders known fence types
- Schema validation: All payloads validated with Zod
- No inline JS: Actions are strings handled by your app
- Strict mode: Mermaid runs in strict security mode
Development
# Install dependencies
npm install
# Build package
npm run build
# Run tests
npm test
# Type checking
npm run type-checkLicense
MIT
