@crashbytes/contentful-richtext-editor 2.0.5 → 2.0.6
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 +99 -156
- package/dist/index.esm.js +2113 -2140
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2112 -2139
- package/dist/index.js.map +1 -1
- package/package.json +27 -26
package/README.md
CHANGED
|
@@ -1,39 +1,24 @@
|
|
|
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
|
-
- ✅ **
|
|
9
|
-
- ✅ **Modern UI** - Clean, intuitive interface matching Contentful's design
|
|
8
|
+
- ✅ **Modern UI** - Clean, intuitive interface matching Contentful's design
|
|
10
9
|
- ✅ **TypeScript Support** - Complete type safety with Contentful's rich text types
|
|
11
10
|
- ✅ **Extensible** - Built on Tiptap v2 for easy customization
|
|
12
11
|
- ✅ **Lightweight** - Tree-shakeable, only import what you need
|
|
13
12
|
- ✅ **Responsive** - Works on desktop and mobile devices
|
|
14
|
-
- ✅ **
|
|
13
|
+
- ✅ **Optional Border Control** - Customize editor appearance with `showBorder` prop _(New in v2.0.4)_
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- **Text Formatting**: Bold, italic, underline
|
|
19
|
-
- **Headings**: H1 through H6
|
|
20
|
-
- **Lists**: Ordered and unordered lists
|
|
21
|
-
- **Links**: Hyperlinks with URL validation
|
|
22
|
-
- **Tables**: Full table support with headers
|
|
23
|
-
- **Quotes**: Blockquotes
|
|
24
|
-
- **Embedded Content**: Callbacks for Contentful entries and assets
|
|
25
|
-
- **Inline Entries**: Support for inline embedded entries *(NEW in v2.0)*
|
|
26
|
-
- **Undo/Redo**: Full history support
|
|
27
|
-
|
|
28
|
-
## 📦 Installation
|
|
15
|
+
## 🚀 Installation
|
|
29
16
|
|
|
30
17
|
```bash
|
|
31
18
|
npm install @crashbytes/contentful-richtext-editor
|
|
32
19
|
```
|
|
33
20
|
|
|
34
|
-
##
|
|
35
|
-
|
|
36
|
-
### Basic Usage
|
|
21
|
+
## 📖 Quick Start
|
|
37
22
|
|
|
38
23
|
```tsx
|
|
39
24
|
import React, { useState } from 'react';
|
|
@@ -56,6 +41,7 @@ function App() {
|
|
|
56
41
|
placeholder="Start writing your content..."
|
|
57
42
|
onChange={handleChange}
|
|
58
43
|
initialValue={content}
|
|
44
|
+
showBorder={true} // Optional: control border visibility
|
|
59
45
|
/>
|
|
60
46
|
</div>
|
|
61
47
|
);
|
|
@@ -64,41 +50,55 @@ function App() {
|
|
|
64
50
|
export default App;
|
|
65
51
|
```
|
|
66
52
|
|
|
67
|
-
|
|
53
|
+
## 🎨 Border Control (New in v2.0.4)
|
|
68
54
|
|
|
69
|
-
|
|
55
|
+
Control the editor's border appearance with the `showBorder` prop:
|
|
70
56
|
|
|
71
57
|
```tsx
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
fetchContentfulFieldConfig
|
|
75
|
-
} from '@crashbytes/contentful-richtext-editor';
|
|
76
|
-
import '@crashbytes/contentful-richtext-editor/dist/index.css';
|
|
58
|
+
// Default - with border (backward compatible)
|
|
59
|
+
<ContentfulRichTextEditor />
|
|
77
60
|
|
|
78
|
-
|
|
79
|
-
|
|
61
|
+
// Borderless editor for custom layouts
|
|
62
|
+
<ContentfulRichTextEditor
|
|
63
|
+
showBorder={false}
|
|
64
|
+
className="my-custom-editor"
|
|
65
|
+
/>
|
|
80
66
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
'your-management-token'
|
|
88
|
-
).then(setFieldConfig);
|
|
89
|
-
}, []);
|
|
67
|
+
// Themed borderless editor
|
|
68
|
+
<ContentfulRichTextEditor
|
|
69
|
+
showBorder={false}
|
|
70
|
+
theme="minimal"
|
|
71
|
+
/>
|
|
72
|
+
```
|
|
90
73
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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);
|
|
98
85
|
}
|
|
99
86
|
```
|
|
100
87
|
|
|
101
|
-
|
|
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
102
|
|
|
103
103
|
```tsx
|
|
104
104
|
import { ContentfulRichTextEditor } from '@crashbytes/contentful-richtext-editor';
|
|
@@ -112,31 +112,25 @@ function ContentfulEditor() {
|
|
|
112
112
|
};
|
|
113
113
|
|
|
114
114
|
const handleEmbedAsset = async () => {
|
|
115
|
-
// Your logic to select a Contentful asset
|
|
115
|
+
// Your logic to select a Contentful asset
|
|
116
116
|
const asset = await openAssetSelector();
|
|
117
117
|
return asset;
|
|
118
118
|
};
|
|
119
119
|
|
|
120
|
-
const handleEmbedInlineEntry = async () => {
|
|
121
|
-
// NEW v2.0 - Your logic to select an inline entry
|
|
122
|
-
const entry = await openInlineEntrySelector();
|
|
123
|
-
return entry;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
120
|
return (
|
|
127
121
|
<ContentfulRichTextEditor
|
|
128
122
|
placeholder="Write your travel tip..."
|
|
129
123
|
onChange={(doc) => saveToContentful(doc)}
|
|
130
124
|
onEmbedEntry={handleEmbedEntry}
|
|
131
125
|
onEmbedAsset={handleEmbedAsset}
|
|
132
|
-
onEmbedInlineEntry={handleEmbedInlineEntry}
|
|
133
126
|
theme="contentful"
|
|
127
|
+
showBorder={true}
|
|
134
128
|
/>
|
|
135
129
|
);
|
|
136
130
|
}
|
|
137
131
|
```
|
|
138
132
|
|
|
139
|
-
###
|
|
133
|
+
### Customized Editor
|
|
140
134
|
|
|
141
135
|
```tsx
|
|
142
136
|
<ContentfulRichTextEditor
|
|
@@ -149,58 +143,25 @@ function ContentfulEditor() {
|
|
|
149
143
|
/>
|
|
150
144
|
```
|
|
151
145
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
```tsx
|
|
155
|
-
import { createEmptyDocument } from '@crashbytes/contentful-richtext-editor';
|
|
156
|
-
|
|
157
|
-
const initialContent = {
|
|
158
|
-
nodeType: 'document',
|
|
159
|
-
data: {},
|
|
160
|
-
content: [
|
|
161
|
-
{
|
|
162
|
-
nodeType: 'paragraph',
|
|
163
|
-
data: {},
|
|
164
|
-
content: [
|
|
165
|
-
{
|
|
166
|
-
nodeType: 'text',
|
|
167
|
-
value: 'Hello world!',
|
|
168
|
-
marks: [{ type: 'bold' }],
|
|
169
|
-
data: {}
|
|
170
|
-
}
|
|
171
|
-
]
|
|
172
|
-
}
|
|
173
|
-
]
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
<ContentfulRichTextEditor
|
|
177
|
-
initialValue={initialContent}
|
|
178
|
-
onChange={handleChange}
|
|
179
|
-
/>
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
## 📋 API Reference
|
|
183
|
-
|
|
184
|
-
### ContentfulRichTextEditor Props
|
|
146
|
+
## 📋 Props Reference
|
|
185
147
|
|
|
186
148
|
| Prop | Type | Default | Description |
|
|
187
149
|
|------|------|---------|-------------|
|
|
188
|
-
| `
|
|
189
|
-
| `availableMarks` | `Array<'bold'\|'italic'\|'underline'>` | `['bold','italic','underline']` | Available text formatting marks (fallback when no fieldConfiguration) |
|
|
190
|
-
| `className` | `string` | `''` | Additional CSS classes |
|
|
191
|
-
| `disabledFeatures` | `Array<string>` | `[]` | Features to disable |
|
|
192
|
-
| `fieldConfiguration` | `ContentfulFieldConfiguration` | `undefined` | **NEW v2.0** - Contentful field validation config (takes precedence over manual settings) |
|
|
150
|
+
| `showBorder` | `boolean` | `true` | Control editor border visibility _(New in v2.0.4)_ |
|
|
193
151
|
| `initialValue` | `Document` | `undefined` | Initial Contentful rich text document |
|
|
194
152
|
| `onChange` | `(document: Document) => void` | `undefined` | Callback when content changes |
|
|
195
|
-
| `onEmbedAsset` | `() => Promise<any> \| void` | `undefined` | Callback for embedding Contentful assets |
|
|
196
153
|
| `onEmbedEntry` | `() => Promise<any> \| void` | `undefined` | Callback for embedding Contentful entries |
|
|
197
|
-
| `
|
|
154
|
+
| `onEmbedAsset` | `() => Promise<any> \| void` | `undefined` | Callback for embedding Contentful assets |
|
|
155
|
+
| `onEmbedInlineEntry` | `() => Promise<any> \| void` | `undefined` | Callback for embedding inline entries |
|
|
198
156
|
| `placeholder` | `string` | `'Start writing...'` | Placeholder text |
|
|
199
157
|
| `readonly` | `boolean` | `false` | Whether editor is read-only |
|
|
200
|
-
| `
|
|
158
|
+
| `className` | `string` | `''` | Additional CSS classes |
|
|
201
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 |
|
|
202
163
|
|
|
203
|
-
|
|
164
|
+
## 🚫 Disabling Features
|
|
204
165
|
|
|
205
166
|
You can disable specific features by passing them in the `disabledFeatures` array:
|
|
206
167
|
|
|
@@ -214,20 +175,6 @@ You can disable specific features by passing them in the `disabledFeatures` arra
|
|
|
214
175
|
- `'table'` - Tables
|
|
215
176
|
- `'embed'` - Embedded content
|
|
216
177
|
|
|
217
|
-
### Configuration Types (NEW v2.0)
|
|
218
|
-
|
|
219
|
-
```tsx
|
|
220
|
-
interface ContentfulFieldConfiguration {
|
|
221
|
-
validations?: Array<{
|
|
222
|
-
enabledMarks?: string[]; // ['bold', 'italic', 'underline', 'code']
|
|
223
|
-
enabledNodeTypes?: string[]; // ['paragraph', 'heading-1', 'unordered-list', ...]
|
|
224
|
-
}>;
|
|
225
|
-
settings?: {
|
|
226
|
-
helpText?: string;
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
```
|
|
230
|
-
|
|
231
178
|
## 🛠️ Utility Functions
|
|
232
179
|
|
|
233
180
|
```tsx
|
|
@@ -236,47 +183,23 @@ import {
|
|
|
236
183
|
tiptapToContentful,
|
|
237
184
|
validateContentfulDocument,
|
|
238
185
|
createEmptyDocument,
|
|
239
|
-
extractPlainText,
|
|
240
|
-
countWords,
|
|
241
|
-
findEmbeddedContent
|
|
242
|
-
sanitizeContentfulDocument // NEW v2.0
|
|
186
|
+
extractPlainText,
|
|
187
|
+
countWords,
|
|
188
|
+
findEmbeddedContent
|
|
243
189
|
} from '@crashbytes/contentful-richtext-editor';
|
|
244
190
|
|
|
245
191
|
// Convert between formats
|
|
246
192
|
const tiptapJson = contentfulToTiptap(contentfulDocument);
|
|
247
193
|
const contentfulDoc = tiptapToContentful(tiptapJson);
|
|
248
194
|
|
|
249
|
-
// Validation
|
|
195
|
+
// Validation and utilities
|
|
250
196
|
const isValid = validateContentfulDocument(someDocument);
|
|
251
|
-
|
|
252
|
-
// Create empty document
|
|
253
197
|
const emptyDoc = createEmptyDocument();
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const
|
|
257
|
-
const wordCount = countWords(contentfulDocument);
|
|
258
|
-
const embedded = findEmbeddedContent(contentfulDocument);
|
|
259
|
-
|
|
260
|
-
// NEW v2.0 - Sanitize content
|
|
261
|
-
const sanitized = sanitizeContentfulDocument(
|
|
262
|
-
document,
|
|
263
|
-
['paragraph', 'heading-1', 'unordered-list'], // allowed nodes
|
|
264
|
-
['bold', 'italic'] // allowed marks
|
|
265
|
-
);
|
|
198
|
+
const plainText = extractPlainText(document);
|
|
199
|
+
const wordCount = countWords(document);
|
|
200
|
+
const embedded = findEmbeddedContent(document);
|
|
266
201
|
```
|
|
267
202
|
|
|
268
|
-
## ⌨️ Keyboard Shortcuts (NEW v2.0)
|
|
269
|
-
|
|
270
|
-
- `Cmd/Ctrl + B` - Bold
|
|
271
|
-
- `Cmd/Ctrl + I` - Italic
|
|
272
|
-
- `Cmd/Ctrl + U` - Underline
|
|
273
|
-
- `Cmd/Ctrl + K` - Add/edit link
|
|
274
|
-
- `Cmd/Ctrl + Shift + E` - Embed entry
|
|
275
|
-
- `Cmd/Ctrl + Shift + A` - Embed asset
|
|
276
|
-
- `Cmd/Ctrl + Shift + I` - Embed inline entry
|
|
277
|
-
- `Cmd/Ctrl + Z` - Undo
|
|
278
|
-
- `Cmd/Ctrl + Y` / `Cmd/Ctrl + Shift + Z` - Redo
|
|
279
|
-
|
|
280
203
|
## 🎨 Styling
|
|
281
204
|
|
|
282
205
|
The editor comes with default styles that match Contentful's design. Import the CSS:
|
|
@@ -285,6 +208,8 @@ The editor comes with default styles that match Contentful's design. Import the
|
|
|
285
208
|
import '@crashbytes/contentful-richtext-editor/dist/index.css';
|
|
286
209
|
```
|
|
287
210
|
|
|
211
|
+
### Custom Styling
|
|
212
|
+
|
|
288
213
|
You can override the default styles by targeting the CSS classes:
|
|
289
214
|
|
|
290
215
|
```css
|
|
@@ -300,27 +225,25 @@ You can override the default styles by targeting the CSS classes:
|
|
|
300
225
|
font-family: 'Your Font', sans-serif;
|
|
301
226
|
}
|
|
302
227
|
|
|
303
|
-
/*
|
|
304
|
-
.contentful-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
border-radius: 3px;
|
|
308
|
-
font-weight: 600;
|
|
228
|
+
/* Borderless editor styling */
|
|
229
|
+
.contentful-editor--borderless {
|
|
230
|
+
border: none;
|
|
231
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
309
232
|
}
|
|
310
233
|
```
|
|
311
234
|
|
|
312
235
|
### Themes
|
|
313
236
|
|
|
314
|
-
|
|
237
|
+
**Contentful** (default)
|
|
315
238
|
Matches Contentful's native editor appearance.
|
|
316
239
|
|
|
317
|
-
|
|
240
|
+
**Minimal**
|
|
318
241
|
Clean, minimal design with reduced visual elements.
|
|
319
242
|
|
|
320
|
-
|
|
243
|
+
**Default**
|
|
321
244
|
Standard rich text editor appearance with serif fonts.
|
|
322
245
|
|
|
323
|
-
##
|
|
246
|
+
## 🌐 Next.js Usage
|
|
324
247
|
|
|
325
248
|
```tsx
|
|
326
249
|
// pages/editor.tsx or app/editor/page.tsx
|
|
@@ -337,13 +260,14 @@ export default function EditorPage() {
|
|
|
337
260
|
<ContentfulEditor
|
|
338
261
|
placeholder="Write something amazing..."
|
|
339
262
|
onChange={(doc) => console.log(doc)}
|
|
263
|
+
showBorder={false}
|
|
340
264
|
/>
|
|
341
265
|
</div>
|
|
342
266
|
);
|
|
343
267
|
}
|
|
344
268
|
```
|
|
345
269
|
|
|
346
|
-
##
|
|
270
|
+
## 📝 TypeScript Support
|
|
347
271
|
|
|
348
272
|
This package is written in TypeScript and includes full type definitions. All Contentful rich text types are re-exported for convenience:
|
|
349
273
|
|
|
@@ -353,9 +277,7 @@ import type {
|
|
|
353
277
|
Block,
|
|
354
278
|
Inline,
|
|
355
279
|
Text,
|
|
356
|
-
ContentfulRichTextEditorProps
|
|
357
|
-
ContentfulFieldConfiguration, // NEW v2.0
|
|
358
|
-
ParsedEditorConfig // NEW v2.0
|
|
280
|
+
ContentfulRichTextEditorProps
|
|
359
281
|
} from '@crashbytes/contentful-richtext-editor';
|
|
360
282
|
```
|
|
361
283
|
|
|
@@ -366,6 +288,19 @@ import type {
|
|
|
366
288
|
- Safari 13+
|
|
367
289
|
- Edge 80+
|
|
368
290
|
|
|
291
|
+
## 🔄 Migration
|
|
292
|
+
|
|
293
|
+
### From v2.0.3 to v2.0.4
|
|
294
|
+
No breaking changes! Simply update and optionally use the new `showBorder` prop:
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
// Before
|
|
298
|
+
<ContentfulRichTextEditor />
|
|
299
|
+
|
|
300
|
+
// After (optional)
|
|
301
|
+
<ContentfulRichTextEditor showBorder={false} />
|
|
302
|
+
```
|
|
303
|
+
|
|
369
304
|
## 🤝 Contributing
|
|
370
305
|
|
|
371
306
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
@@ -386,6 +321,14 @@ MIT © [CrashBytes](https://github.com/CrashBytes)
|
|
|
386
321
|
- [@contentful/rich-text-types](https://www.npmjs.com/package/@contentful/rich-text-types) - Contentful rich text type definitions
|
|
387
322
|
- [@tiptap/react](https://www.npmjs.com/package/@tiptap/react) - The underlying editor framework
|
|
388
323
|
|
|
324
|
+
## 📈 Version History
|
|
325
|
+
|
|
326
|
+
- **v2.0.4** - Added optional border control with `showBorder` prop
|
|
327
|
+
- **v2.0.3** - Package made publicly accessible
|
|
328
|
+
- **v2.0.2** - Previous release
|
|
329
|
+
- **v2.0.0** - Major feature update with automatic configuration
|
|
330
|
+
- **v1.x** - Initial releases
|
|
331
|
+
|
|
389
332
|
---
|
|
390
333
|
|
|
391
334
|
Made with ❤️ for the Contentful community
|