@crashbytes/contentful-richtext-editor 1.0.11 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +273 -120
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -1,179 +1,332 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @crashbytes/contentful-richtext-editor
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A modern, Tiptap-based rich text editor that's fully compatible with Contentful's rich text format. Provides the same editing experience as Contentful's native editor while maintaining perfect compatibility with Contentful's document structure.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## ✨ Features
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- ✅ **Full Contentful Compatibility** - Seamless conversion between Contentful and Tiptap formats
|
|
8
|
+
- ✅ **Modern UI** - Clean, intuitive interface matching Contentful's design
|
|
9
|
+
- ✅ **TypeScript Support** - Complete type safety with Contentful's rich text types
|
|
10
|
+
- ✅ **Extensible** - Built on Tiptap v2 for easy customization
|
|
11
|
+
- ✅ **Lightweight** - Tree-shakeable, only import what you need
|
|
12
|
+
- ✅ **Responsive** - Works on desktop and mobile devices
|
|
13
|
+
- ✅ **Customizable Borders** - Control editor appearance with `showBorder` prop
|
|
8
14
|
|
|
9
|
-
|
|
10
|
-
- **📝 Inline Entry Support**: Added support for inline embedded entries (as configured in Contentful)
|
|
11
|
-
- **⌨️ Keyboard Shortcuts**: Built-in shortcuts for common actions (`Cmd/Ctrl + Shift + E` for entries, `Cmd/Ctrl + Shift + A` for assets, etc.)
|
|
12
|
-
- **🔍 Enhanced TypeScript Support**: Comprehensive type definitions and better developer experience
|
|
13
|
-
- **📊 Content Analysis Utilities**: New utilities for word counting, plain text extraction, and content validation
|
|
15
|
+
## 🚀 Installation
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- **Better Error Handling**: Improved error messages and validation
|
|
19
|
-
- **Performance Optimizations**: Faster rendering and better memory usage
|
|
20
|
-
- **Accessibility Improvements**: Enhanced ARIA support and keyboard navigation
|
|
21
|
-
|
|
22
|
-
### 🎨 Developer Experience
|
|
17
|
+
```bash
|
|
18
|
+
npm install @crashbytes/contentful-richtext-editor
|
|
19
|
+
```
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
- **Mock Configuration**: Easy testing with `createMockFieldConfig()`
|
|
26
|
-
- **Backward Compatibility**: Existing manual configuration still works
|
|
27
|
-
- **Comprehensive Documentation**: Updated with examples and API reference
|
|
21
|
+
## 📖 Quick Start
|
|
28
22
|
|
|
29
|
-
|
|
23
|
+
```tsx
|
|
24
|
+
import React, { useState } from 'react';
|
|
25
|
+
import { ContentfulRichTextEditor } from '@crashbytes/contentful-richtext-editor';
|
|
26
|
+
import '@crashbytes/contentful-richtext-editor/dist/index.css';
|
|
27
|
+
import { Document } from '@contentful/rich-text-types';
|
|
28
|
+
|
|
29
|
+
function App() {
|
|
30
|
+
const [content, setContent] = useState<Document>();
|
|
31
|
+
|
|
32
|
+
const handleChange = (document: Document) => {
|
|
33
|
+
setContent(document);
|
|
34
|
+
console.log('Contentful document:', document);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div>
|
|
39
|
+
<h1>My Rich Text Editor</h1>
|
|
40
|
+
<ContentfulRichTextEditor
|
|
41
|
+
placeholder="Start writing your content..."
|
|
42
|
+
onChange={handleChange}
|
|
43
|
+
initialValue={content}
|
|
44
|
+
showBorder={true} // Control border visibility
|
|
45
|
+
/>
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
30
49
|
|
|
31
|
-
|
|
32
|
-
npm install @crashbytes/contentful-richtext-editor@2.0.0
|
|
50
|
+
export default App;
|
|
33
51
|
```
|
|
34
52
|
|
|
35
|
-
##
|
|
53
|
+
## 🎨 Border Control
|
|
54
|
+
|
|
55
|
+
Control the editor's border appearance with the `showBorder` prop:
|
|
36
56
|
|
|
37
|
-
### Automatic Configuration (Recommended)
|
|
38
57
|
```tsx
|
|
39
|
-
//
|
|
40
|
-
<ContentfulRichTextEditor
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
58
|
+
// Default - with border (backward compatible)
|
|
59
|
+
<ContentfulRichTextEditor />
|
|
60
|
+
|
|
61
|
+
// Borderless editor for custom layouts
|
|
62
|
+
<ContentfulRichTextEditor
|
|
63
|
+
showBorder={false}
|
|
64
|
+
className="my-custom-editor"
|
|
44
65
|
/>
|
|
45
66
|
|
|
46
|
-
//
|
|
47
|
-
<ContentfulRichTextEditor
|
|
48
|
-
|
|
49
|
-
|
|
67
|
+
// Themed borderless editor
|
|
68
|
+
<ContentfulRichTextEditor
|
|
69
|
+
showBorder={false}
|
|
70
|
+
theme="minimal"
|
|
50
71
|
/>
|
|
51
72
|
```
|
|
52
73
|
|
|
53
|
-
###
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
### Custom Styling with Borderless Mode
|
|
75
|
+
|
|
76
|
+
```css
|
|
77
|
+
/* Custom styling for borderless editor */
|
|
78
|
+
.my-custom-editor {
|
|
79
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
80
|
+
border-radius: 8px;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.my-custom-editor .contentful-toolbar {
|
|
84
|
+
background: linear-gradient(45deg, #667eea, #764ba2);
|
|
64
85
|
}
|
|
65
86
|
```
|
|
66
87
|
|
|
67
|
-
|
|
88
|
+
## 🎯 Supported Features
|
|
89
|
+
|
|
90
|
+
- **Text Formatting**: Bold, italic, underline
|
|
91
|
+
- **Headings**: H1 through H6
|
|
92
|
+
- **Lists**: Ordered and unordered lists
|
|
93
|
+
- **Links**: Hyperlinks with URL validation
|
|
94
|
+
- **Tables**: Full table support with headers
|
|
95
|
+
- **Quotes**: Blockquotes
|
|
96
|
+
- **Embedded Content**: Callbacks for Contentful entries and assets
|
|
97
|
+
- **Undo/Redo**: Full history support
|
|
98
|
+
|
|
99
|
+
## 🔧 Advanced Usage
|
|
100
|
+
|
|
101
|
+
### With Contentful Integration
|
|
102
|
+
|
|
68
103
|
```tsx
|
|
69
|
-
import {
|
|
104
|
+
import { ContentfulRichTextEditor } from '@crashbytes/contentful-richtext-editor';
|
|
105
|
+
import '@crashbytes/contentful-richtext-editor/dist/index.css';
|
|
106
|
+
|
|
107
|
+
function ContentfulEditor() {
|
|
108
|
+
const handleEmbedEntry = async () => {
|
|
109
|
+
// Your logic to select a Contentful entry
|
|
110
|
+
const entry = await openEntrySelector();
|
|
111
|
+
return entry;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const handleEmbedAsset = async () => {
|
|
115
|
+
// Your logic to select a Contentful asset
|
|
116
|
+
const asset = await openAssetSelector();
|
|
117
|
+
return asset;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<ContentfulRichTextEditor
|
|
122
|
+
placeholder="Write your travel tip..."
|
|
123
|
+
onChange={(doc) => saveToContentful(doc)}
|
|
124
|
+
onEmbedEntry={handleEmbedEntry}
|
|
125
|
+
onEmbedAsset={handleEmbedAsset}
|
|
126
|
+
theme="contentful"
|
|
127
|
+
showBorder={true}
|
|
128
|
+
/>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
```
|
|
70
132
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
133
|
+
### Customized Editor
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
<ContentfulRichTextEditor
|
|
137
|
+
placeholder="Simple editor..."
|
|
138
|
+
disabledFeatures={['table', 'embed', 'quote']}
|
|
139
|
+
theme="minimal"
|
|
140
|
+
readonly={false}
|
|
141
|
+
showBorder={false}
|
|
142
|
+
onChange={handleChange}
|
|
143
|
+
/>
|
|
77
144
|
```
|
|
78
145
|
|
|
79
|
-
## 📋
|
|
146
|
+
## 📋 Props Reference
|
|
147
|
+
|
|
148
|
+
| Prop | Type | Default | Description |
|
|
149
|
+
|------|------|---------|-------------|
|
|
150
|
+
| `showBorder` | `boolean` | `true` | Control editor border visibility |
|
|
151
|
+
| `initialValue` | `Document` | `undefined` | Initial Contentful rich text document |
|
|
152
|
+
| `onChange` | `(document: Document) => void` | `undefined` | Callback when content changes |
|
|
153
|
+
| `onEmbedEntry` | `() => Promise<any> \| void` | `undefined` | Callback for embedding Contentful entries |
|
|
154
|
+
| `onEmbedAsset` | `() => Promise<any> \| void` | `undefined` | Callback for embedding Contentful assets |
|
|
155
|
+
| `onEmbedInlineEntry` | `() => Promise<any> \| void` | `undefined` | Callback for embedding inline entries |
|
|
156
|
+
| `placeholder` | `string` | `'Start writing...'` | Placeholder text |
|
|
157
|
+
| `readonly` | `boolean` | `false` | Whether editor is read-only |
|
|
158
|
+
| `className` | `string` | `''` | Additional CSS classes |
|
|
159
|
+
| `theme` | `'default' \| 'minimal' \| 'contentful'` | `'contentful'` | Visual theme |
|
|
160
|
+
| `disabledFeatures` | `Array<string>` | `[]` | Features to disable |
|
|
161
|
+
| `availableHeadings` | `Array<1 \| 2 \| 3 \| 4 \| 5 \| 6>` | `[1,2,3,4,5,6]` | Available heading levels |
|
|
162
|
+
| `availableMarks` | `Array<'bold' \| 'italic' \| 'underline'>` | `['bold','italic','underline']` | Available text formatting |
|
|
163
|
+
|
|
164
|
+
## 🚫 Disabling Features
|
|
165
|
+
|
|
166
|
+
You can disable specific features by passing them in the `disabledFeatures` array:
|
|
167
|
+
|
|
168
|
+
- `'bold'` - Bold text formatting
|
|
169
|
+
- `'italic'` - Italic text formatting
|
|
170
|
+
- `'underline'` - Underline text formatting
|
|
171
|
+
- `'link'` - Hyperlinks
|
|
172
|
+
- `'lists'` - Ordered and unordered lists
|
|
173
|
+
- `'headings'` - All heading levels
|
|
174
|
+
- `'quote'` - Blockquotes
|
|
175
|
+
- `'table'` - Tables
|
|
176
|
+
- `'embed'` - Embedded content
|
|
177
|
+
|
|
178
|
+
## 🛠️ Utility Functions
|
|
80
179
|
|
|
81
|
-
### Content Analysis
|
|
82
180
|
```tsx
|
|
83
|
-
import {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
181
|
+
import {
|
|
182
|
+
contentfulToTiptap,
|
|
183
|
+
tiptapToContentful,
|
|
184
|
+
validateContentfulDocument,
|
|
185
|
+
createEmptyDocument,
|
|
186
|
+
extractPlainText,
|
|
187
|
+
countWords,
|
|
188
|
+
findEmbeddedContent
|
|
88
189
|
} from '@crashbytes/contentful-richtext-editor';
|
|
89
190
|
|
|
191
|
+
// Convert between formats
|
|
192
|
+
const tiptapJson = contentfulToTiptap(contentfulDocument);
|
|
193
|
+
const contentfulDoc = tiptapToContentful(tiptapJson);
|
|
194
|
+
|
|
195
|
+
// Validation and utilities
|
|
196
|
+
const isValid = validateContentfulDocument(someDocument);
|
|
197
|
+
const emptyDoc = createEmptyDocument();
|
|
90
198
|
const plainText = extractPlainText(document);
|
|
91
199
|
const wordCount = countWords(document);
|
|
92
200
|
const embedded = findEmbeddedContent(document);
|
|
93
201
|
```
|
|
94
202
|
|
|
95
|
-
|
|
203
|
+
## 🎨 Styling
|
|
204
|
+
|
|
205
|
+
The editor comes with default styles that match Contentful's design. Import the CSS:
|
|
206
|
+
|
|
96
207
|
```tsx
|
|
97
|
-
import
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
208
|
+
import '@crashbytes/contentful-richtext-editor/dist/index.css';
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Custom Styling
|
|
212
|
+
|
|
213
|
+
You can override the default styles by targeting the CSS classes:
|
|
214
|
+
|
|
215
|
+
```css
|
|
216
|
+
.contentful-editor {
|
|
217
|
+
border: 2px solid #your-color;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.contentful-toolbar {
|
|
221
|
+
background: #your-background;
|
|
222
|
+
}
|
|
101
223
|
|
|
102
|
-
|
|
103
|
-
|
|
224
|
+
.contentful-editor-content {
|
|
225
|
+
font-family: 'Your Font', sans-serif;
|
|
226
|
+
}
|
|
104
227
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
228
|
+
/* Borderless editor styling */
|
|
229
|
+
.contentful-editor--borderless {
|
|
230
|
+
border: none;
|
|
231
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
232
|
+
}
|
|
110
233
|
```
|
|
111
234
|
|
|
112
|
-
|
|
235
|
+
### Themes
|
|
236
|
+
|
|
237
|
+
**Contentful** (default)
|
|
238
|
+
Matches Contentful's native editor appearance.
|
|
239
|
+
|
|
240
|
+
**Minimal**
|
|
241
|
+
Clean, minimal design with reduced visual elements.
|
|
242
|
+
|
|
243
|
+
**Default**
|
|
244
|
+
Standard rich text editor appearance with serif fonts.
|
|
245
|
+
|
|
246
|
+
## 🌐 Next.js Usage
|
|
113
247
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
248
|
+
```tsx
|
|
249
|
+
// pages/editor.tsx or app/editor/page.tsx
|
|
250
|
+
import dynamic from 'next/dynamic';
|
|
251
|
+
|
|
252
|
+
const ContentfulEditor = dynamic(
|
|
253
|
+
() => import('@crashbytes/contentful-richtext-editor').then(mod => mod.ContentfulRichTextEditor),
|
|
254
|
+
{ ssr: false }
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
export default function EditorPage() {
|
|
258
|
+
return (
|
|
259
|
+
<div>
|
|
260
|
+
<ContentfulEditor
|
|
261
|
+
placeholder="Write something amazing..."
|
|
262
|
+
onChange={(doc) => console.log(doc)}
|
|
263
|
+
showBorder={false}
|
|
264
|
+
/>
|
|
265
|
+
</div>
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## 📝 TypeScript Support
|
|
119
271
|
|
|
120
|
-
|
|
272
|
+
This package is written in TypeScript and includes full type definitions. All Contentful rich text types are re-exported for convenience:
|
|
121
273
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
274
|
+
```tsx
|
|
275
|
+
import type {
|
|
276
|
+
Document,
|
|
277
|
+
Block,
|
|
278
|
+
Inline,
|
|
279
|
+
Text,
|
|
280
|
+
ContentfulRichTextEditorProps
|
|
281
|
+
} from '@crashbytes/contentful-richtext-editor';
|
|
282
|
+
```
|
|
127
283
|
|
|
128
|
-
##
|
|
284
|
+
## 🌐 Browser Support
|
|
129
285
|
|
|
130
|
-
-
|
|
131
|
-
-
|
|
132
|
-
-
|
|
133
|
-
-
|
|
286
|
+
- Chrome 80+
|
|
287
|
+
- Firefox 78+
|
|
288
|
+
- Safari 13+
|
|
289
|
+
- Edge 80+
|
|
134
290
|
|
|
135
|
-
##
|
|
291
|
+
## 🔄 Migration
|
|
136
292
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
- **Migration Guide**: Step-by-step upgrade instructions
|
|
140
|
-
- **TypeScript Support**: Full type definitions and examples
|
|
293
|
+
### From v2.0.3 to v2.0.4
|
|
294
|
+
No breaking changes! Simply update and optionally use the new `showBorder` prop:
|
|
141
295
|
|
|
142
|
-
|
|
296
|
+
```tsx
|
|
297
|
+
// Before
|
|
298
|
+
<ContentfulRichTextEditor />
|
|
143
299
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
- Plugin system for custom extensions
|
|
148
|
-
- More keyboard shortcuts and accessibility improvements
|
|
300
|
+
// After (optional)
|
|
301
|
+
<ContentfulRichTextEditor showBorder={false} />
|
|
302
|
+
```
|
|
149
303
|
|
|
150
304
|
## 🤝 Contributing
|
|
151
305
|
|
|
152
|
-
|
|
306
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
153
307
|
|
|
154
|
-
|
|
308
|
+
1. Fork the repository
|
|
309
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
310
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
311
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
312
|
+
5. Open a Pull Request
|
|
155
313
|
|
|
156
|
-
|
|
157
|
-
- [API Reference](docs/API.md) - Detailed prop and method documentation
|
|
158
|
-
- [Examples](examples/) - Implementation examples
|
|
159
|
-
- [Changelog](CHANGELOG.md) - Complete version history
|
|
314
|
+
## 📄 License
|
|
160
315
|
|
|
161
|
-
|
|
316
|
+
MIT © [CrashBytes](https://github.com/CrashBytes)
|
|
162
317
|
|
|
163
|
-
|
|
164
|
-
- **npm**: https://www.npmjs.com/package/@crashbytes/contentful-richtext-editor
|
|
165
|
-
- **Issues**: https://github.com/your-org/contentful-richtext-editor/issues
|
|
166
|
-
- **Discussions**: https://github.com/your-org/contentful-richtext-editor/discussions
|
|
318
|
+
## 🔗 Related Packages
|
|
167
319
|
|
|
168
|
-
|
|
320
|
+
- [@contentful/rich-text-react-renderer](https://www.npmjs.com/package/@contentful/rich-text-react-renderer) - For rendering Contentful rich text
|
|
321
|
+
- [@contentful/rich-text-types](https://www.npmjs.com/package/@contentful/rich-text-types) - Contentful rich text type definitions
|
|
322
|
+
- [@tiptap/react](https://www.npmjs.com/package/@tiptap/react) - The underlying editor framework
|
|
169
323
|
|
|
170
|
-
|
|
171
|
-
- The Contentful team for their excellent Rich Text API
|
|
172
|
-
- The TipTap team for the amazing editor framework
|
|
173
|
-
- All early adopters and contributors who provided feedback
|
|
324
|
+
## 📈 Version History
|
|
174
325
|
|
|
175
|
-
|
|
326
|
+
- **v2.0.4** - Added `showBorder` prop for flexible styling, resolved publishing issues
|
|
327
|
+
- **v2.0.0** - Major release with full Contentful compatibility and modern architecture
|
|
328
|
+
- **v1.x** - Initial releases with basic functionality
|
|
176
329
|
|
|
177
|
-
|
|
330
|
+
---
|
|
178
331
|
|
|
179
|
-
|
|
332
|
+
Made with ❤️ for the Contentful community
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crashbytes/contentful-richtext-editor",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "A Tiptap-based rich text editor compatible with Contentful's rich text format",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"dist"
|
|
11
11
|
],
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
12
15
|
"keywords": [
|
|
13
16
|
"contentful",
|
|
14
17
|
"tiptap",
|