Skip to content

Commit 05f9c14

Browse files
committed
add renderers
1 parent 7dfc34d commit 05f9c14

5 files changed

Lines changed: 899 additions & 117 deletions

File tree

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
# Document Preview Component
2+
3+
The `DocumentPreview` component displays knowledge documents with support for multiple file formats and custom renderers.
4+
5+
## Supported Formats
6+
7+
- **Markdown** (`.md`) - Standard markdown with basic formatting
8+
- **MDX** (`.mdx`) - Markdown with embedded React components
9+
- **RichText** - PayloadCMS rich text content
10+
- **Text** (`.txt`) - Plain text with preserved formatting
11+
12+
## Usage
13+
14+
### Basic Usage
15+
16+
```tsx
17+
import { DocumentPreview } from './document-preview'
18+
19+
const document = {
20+
id: '1',
21+
title: 'My Document',
22+
format: 'markdown',
23+
content: '# Hello World\n\nThis is **bold** text.',
24+
createdAt: new Date()
25+
}
26+
27+
<DocumentPreview document={document} />
28+
```
29+
30+
### With Custom Renderers
31+
32+
```tsx
33+
import { DocumentPreview } from './document-preview'
34+
import ReactMarkdown from 'react-markdown'
35+
import { RichText } from '@payloadcms/richtext-lexical/react'
36+
37+
const customRenderers = {
38+
markdown: (content: string) => (
39+
<div className="prose prose-slate dark:prose-invert max-w-none">
40+
<ReactMarkdown>{content}</ReactMarkdown>
41+
</div>
42+
),
43+
44+
richtext: (content: string) => {
45+
const richTextData = JSON.parse(content)
46+
return (
47+
<div className="prose prose-slate dark:prose-invert max-w-none">
48+
<RichText data={richTextData} />
49+
</div>
50+
)
51+
},
52+
53+
text: (content: string) => (
54+
<pre className="whitespace-pre-wrap font-mono text-sm">
55+
{content}
56+
</pre>
57+
)
58+
}
59+
60+
<DocumentPreview
61+
document={document}
62+
renderers={customRenderers}
63+
editable={true}
64+
onDocumentUpdate={(updatedDoc) => console.log('Updated:', updatedDoc)}
65+
/>
66+
```
67+
68+
## Available Dependencies
69+
70+
The project already includes these useful dependencies for rendering:
71+
72+
- `@mdx-js/react` - For MDX rendering
73+
- `@payloadcms/richtext-lexical` - For PayloadCMS RichText
74+
- `@tailwindcss/typography` - For typography styling
75+
76+
## Custom Renderer Examples
77+
78+
### React Markdown
79+
80+
```bash
81+
npm install react-markdown remark-gfm rehype-highlight
82+
```
83+
84+
```tsx
85+
import ReactMarkdown from 'react-markdown'
86+
import remarkGfm from 'remark-gfm'
87+
import rehypeHighlight from 'rehype-highlight'
88+
89+
const markdownRenderer = (content: string) => (
90+
<div className="prose prose-slate dark:prose-invert max-w-none">
91+
<ReactMarkdown
92+
remarkPlugins={[remarkGfm]}
93+
rehypePlugins={[rehypeHighlight]}
94+
>
95+
{content}
96+
</ReactMarkdown>
97+
</div>
98+
)
99+
```
100+
101+
### MDX with next-mdx-remote
102+
103+
```bash
104+
npm install next-mdx-remote
105+
```
106+
107+
```tsx
108+
import { MDXRemote } from 'next-mdx-remote'
109+
import { serialize } from 'next-mdx-remote/serialize'
110+
111+
const mdxRenderer = async (content: string) => {
112+
const mdxSource = await serialize(content)
113+
return (
114+
<div className="prose prose-slate dark:prose-invert max-w-none">
115+
<MDXRemote {...mdxSource} />
116+
</div>
117+
)
118+
}
119+
```
120+
121+
### PayloadCMS RichText
122+
123+
```tsx
124+
import { RichText } from '@payloadcms/richtext-lexical/react'
125+
126+
const richTextRenderer = (content: string) => {
127+
try {
128+
const richTextData = JSON.parse(content)
129+
return (
130+
<div className="prose prose-slate dark:prose-invert max-w-none">
131+
<RichText data={richTextData} />
132+
</div>
133+
)
134+
} catch (error) {
135+
return (
136+
<div className="text-red-500 text-sm">
137+
Error parsing RichText content: {error.message}
138+
</div>
139+
)
140+
}
141+
}
142+
```
143+
144+
## Props
145+
146+
### DocumentPreview Props
147+
148+
| Prop | Type | Default | Description |
149+
|------|------|---------|-------------|
150+
| `document` | `KnowledgeDocument` | - | The document to display |
151+
| `editable` | `boolean` | `true` | Whether the document can be edited |
152+
| `renderers` | `DocumentRenderers` | - | Custom renderers for different formats |
153+
| `onDocumentUpdate` | `(doc: KnowledgeDocument) => void` | - | Callback when document is updated |
154+
155+
### DocumentRenderers Type
156+
157+
```tsx
158+
interface DocumentRenderers {
159+
markdown?: (content: string) => ReactNode
160+
mdx?: (content: string) => ReactNode
161+
richtext?: (content: string) => ReactNode
162+
text?: (content: string) => ReactNode
163+
}
164+
```
165+
166+
### KnowledgeDocument Type
167+
168+
```tsx
169+
interface KnowledgeDocument {
170+
id: string
171+
title: string
172+
description?: string
173+
metadata?: Record<string, any>
174+
content?: string
175+
format: 'markdown' | 'mdx' | 'richtext' | 'text'
176+
tags?: string[]
177+
createdAt: Date
178+
updatedAt?: Date
179+
}
180+
```
181+
182+
## Default Renderers
183+
184+
If no custom renderers are provided, the component uses built-in default renderers:
185+
186+
- **Markdown**: Basic HTML conversion with support for headings, bold, italic, and code
187+
- **Text**: Monospace font with preserved whitespace
188+
- **RichText**: Placeholder with raw content display
189+
- **MDX**: Placeholder with basic markdown rendering
190+
191+
## Styling
192+
193+
The component uses Tailwind CSS classes and supports dark mode through CSS variables. Key styling features:
194+
195+
- Responsive design
196+
- Typography classes from `@tailwindcms/typography`
197+
- Dark mode support
198+
- Smooth animations with Framer Motion
199+
- Consistent spacing and borders
200+
201+
## Examples
202+
203+
Check out the Storybook stories for interactive examples:
204+
205+
- `MarkdownWithCustomRenderer` - Markdown with enhanced rendering
206+
- `TextFormat` - Plain text documents
207+
- `RichTextFormat` - PayloadCMS rich content
208+
- `MDXFormat` - MDX with React components
209+
- `AllFormatsComparison` - Side-by-side format comparison

0 commit comments

Comments
 (0)