@crashbytes/contentful-richtext-editor 2.0.4 → 2.0.5

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.
Files changed (2) hide show
  1. package/README.md +156 -97
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,24 +1,39 @@
1
- # @crashbytes/contentful-richtext-editor
1
+ # Contentful Rich Text 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
8
+ - ✅ **Automatic Configuration** - Reads Contentful field settings to auto-configure the editor *(NEW in v2.0)*
9
+ - ✅ **Modern UI** - Clean, intuitive interface matching Contentful's design
9
10
  - ✅ **TypeScript Support** - Complete type safety with Contentful's rich text types
10
11
  - ✅ **Extensible** - Built on Tiptap v2 for easy customization
11
12
  - ✅ **Lightweight** - Tree-shakeable, only import what you need
12
13
  - ✅ **Responsive** - Works on desktop and mobile devices
13
- - ✅ **Customizable Borders** - Control editor appearance with `showBorder` prop
14
+ - ✅ **Keyboard Shortcuts** - Built-in shortcuts for common actions *(NEW in v2.0)*
14
15
 
15
- ## 🚀 Installation
16
+ ### Supported Features
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
16
29
 
17
30
  ```bash
18
31
  npm install @crashbytes/contentful-richtext-editor
19
32
  ```
20
33
 
21
- ## 📖 Quick Start
34
+ ## 🚀 Quick Start
35
+
36
+ ### Basic Usage
22
37
 
23
38
  ```tsx
24
39
  import React, { useState } from 'react';
@@ -41,7 +56,6 @@ function App() {
41
56
  placeholder="Start writing your content..."
42
57
  onChange={handleChange}
43
58
  initialValue={content}
44
- showBorder={true} // Control border visibility
45
59
  />
46
60
  </div>
47
61
  );
@@ -50,55 +64,41 @@ function App() {
50
64
  export default App;
51
65
  ```
52
66
 
53
- ## 🎨 Border Control
67
+ ### Automatic Configuration (NEW in v2.0)
54
68
 
55
- Control the editor's border appearance with the `showBorder` prop:
69
+ The editor can automatically configure itself based on your Contentful field settings:
56
70
 
57
71
  ```tsx
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"
65
- />
66
-
67
- // Themed borderless editor
68
- <ContentfulRichTextEditor
69
- showBorder={false}
70
- theme="minimal"
71
- />
72
- ```
72
+ import {
73
+ ContentfulRichTextEditor,
74
+ fetchContentfulFieldConfig
75
+ } from '@crashbytes/contentful-richtext-editor';
76
+ import '@crashbytes/contentful-richtext-editor/dist/index.css';
73
77
 
74
- ### Custom Styling with Borderless Mode
78
+ function AutoConfiguredEditor() {
79
+ const [fieldConfig, setFieldConfig] = useState();
75
80
 
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
- }
81
+ useEffect(() => {
82
+ // Fetch configuration from Contentful Management API
83
+ fetchContentfulFieldConfig(
84
+ 'your-space-id',
85
+ 'your-content-type-id',
86
+ 'your-field-id',
87
+ 'your-management-token'
88
+ ).then(setFieldConfig);
89
+ }, []);
82
90
 
83
- .my-custom-editor .contentful-toolbar {
84
- background: linear-gradient(45deg, #667eea, #764ba2);
91
+ return (
92
+ <ContentfulRichTextEditor
93
+ fieldConfiguration={fieldConfig}
94
+ placeholder="Auto-configured based on Contentful settings!"
95
+ onChange={handleChange}
96
+ />
97
+ );
85
98
  }
86
99
  ```
87
100
 
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
101
+ ### Advanced Usage with Embeds
102
102
 
103
103
  ```tsx
104
104
  import { ContentfulRichTextEditor } from '@crashbytes/contentful-richtext-editor';
@@ -112,25 +112,31 @@ 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
+
120
126
  return (
121
127
  <ContentfulRichTextEditor
122
128
  placeholder="Write your travel tip..."
123
129
  onChange={(doc) => saveToContentful(doc)}
124
130
  onEmbedEntry={handleEmbedEntry}
125
131
  onEmbedAsset={handleEmbedAsset}
132
+ onEmbedInlineEntry={handleEmbedInlineEntry}
126
133
  theme="contentful"
127
- showBorder={true}
128
134
  />
129
135
  );
130
136
  }
131
137
  ```
132
138
 
133
- ### Customized Editor
139
+ ### Minimal Configuration
134
140
 
135
141
  ```tsx
136
142
  <ContentfulRichTextEditor
@@ -143,25 +149,58 @@ function ContentfulEditor() {
143
149
  />
144
150
  ```
145
151
 
146
- ## 📋 Props Reference
152
+ ### With Initial Content
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
147
185
 
148
186
  | Prop | Type | Default | Description |
149
187
  |------|------|---------|-------------|
150
- | `showBorder` | `boolean` | `true` | Control editor border visibility |
188
+ | `availableHeadings` | `Array<1\|2\|3\|4\|5\|6>` | `[1,2,3,4,5,6]` | Available heading levels (fallback when no fieldConfiguration) |
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) |
151
193
  | `initialValue` | `Document` | `undefined` | Initial Contentful rich text document |
152
194
  | `onChange` | `(document: Document) => void` | `undefined` | Callback when content changes |
153
- | `onEmbedEntry` | `() => Promise<any> \| void` | `undefined` | Callback for embedding Contentful entries |
154
195
  | `onEmbedAsset` | `() => Promise<any> \| void` | `undefined` | Callback for embedding Contentful assets |
155
- | `onEmbedInlineEntry` | `() => Promise<any> \| void` | `undefined` | Callback for embedding inline entries |
196
+ | `onEmbedEntry` | `() => Promise<any> \| void` | `undefined` | Callback for embedding Contentful entries |
197
+ | `onEmbedInlineEntry` | `() => Promise<any> \| void` | `undefined` | **NEW v2.0** - Callback for embedding inline entries |
156
198
  | `placeholder` | `string` | `'Start writing...'` | Placeholder text |
157
199
  | `readonly` | `boolean` | `false` | Whether editor is read-only |
158
- | `className` | `string` | `''` | Additional CSS classes |
200
+ | `showBorder` | `boolean` | `true` | Whether to show border around the editor |
159
201
  | `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
202
 
164
- ## 🚫 Disabling Features
203
+ ### Disabled Features
165
204
 
166
205
  You can disable specific features by passing them in the `disabledFeatures` array:
167
206
 
@@ -175,6 +214,20 @@ You can disable specific features by passing them in the `disabledFeatures` arra
175
214
  - `'table'` - Tables
176
215
  - `'embed'` - Embedded content
177
216
 
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
+
178
231
  ## 🛠️ Utility Functions
179
232
 
180
233
  ```tsx
@@ -183,23 +236,47 @@ import {
183
236
  tiptapToContentful,
184
237
  validateContentfulDocument,
185
238
  createEmptyDocument,
186
- extractPlainText,
187
- countWords,
188
- findEmbeddedContent
239
+ extractPlainText, // NEW v2.0
240
+ countWords, // NEW v2.0
241
+ findEmbeddedContent, // NEW v2.0
242
+ sanitizeContentfulDocument // NEW v2.0
189
243
  } from '@crashbytes/contentful-richtext-editor';
190
244
 
191
245
  // Convert between formats
192
246
  const tiptapJson = contentfulToTiptap(contentfulDocument);
193
247
  const contentfulDoc = tiptapToContentful(tiptapJson);
194
248
 
195
- // Validation and utilities
249
+ // Validation
196
250
  const isValid = validateContentfulDocument(someDocument);
251
+
252
+ // Create empty document
197
253
  const emptyDoc = createEmptyDocument();
198
- const plainText = extractPlainText(document);
199
- const wordCount = countWords(document);
200
- const embedded = findEmbeddedContent(document);
254
+
255
+ // NEW v2.0 - Content analysis
256
+ const plainText = extractPlainText(contentfulDocument);
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
+ );
201
266
  ```
202
267
 
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
+
203
280
  ## 🎨 Styling
204
281
 
205
282
  The editor comes with default styles that match Contentful's design. Import the CSS:
@@ -208,8 +285,6 @@ The editor comes with default styles that match Contentful's design. Import the
208
285
  import '@crashbytes/contentful-richtext-editor/dist/index.css';
209
286
  ```
210
287
 
211
- ### Custom Styling
212
-
213
288
  You can override the default styles by targeting the CSS classes:
214
289
 
215
290
  ```css
@@ -225,25 +300,27 @@ You can override the default styles by targeting the CSS classes:
225
300
  font-family: 'Your Font', sans-serif;
226
301
  }
227
302
 
228
- /* Borderless editor styling */
229
- .contentful-editor--borderless {
230
- border: none;
231
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
303
+ /* NEW v2.0 - Inline entries */
304
+ .contentful-inline-embedded-entry {
305
+ background: #e8f4fd;
306
+ padding: 2px 4px;
307
+ border-radius: 3px;
308
+ font-weight: 600;
232
309
  }
233
310
  ```
234
311
 
235
312
  ### Themes
236
313
 
237
- **Contentful** (default)
314
+ **`contentful`** (default)
238
315
  Matches Contentful's native editor appearance.
239
316
 
240
- **Minimal**
317
+ **`minimal`**
241
318
  Clean, minimal design with reduced visual elements.
242
319
 
243
- **Default**
320
+ **`default`**
244
321
  Standard rich text editor appearance with serif fonts.
245
322
 
246
- ## 🌐 Next.js Usage
323
+ ## ⚛️ Next.js Integration
247
324
 
248
325
  ```tsx
249
326
  // pages/editor.tsx or app/editor/page.tsx
@@ -260,14 +337,13 @@ export default function EditorPage() {
260
337
  <ContentfulEditor
261
338
  placeholder="Write something amazing..."
262
339
  onChange={(doc) => console.log(doc)}
263
- showBorder={false}
264
340
  />
265
341
  </div>
266
342
  );
267
343
  }
268
344
  ```
269
345
 
270
- ## 📝 TypeScript Support
346
+ ## 🔷 TypeScript Support
271
347
 
272
348
  This package is written in TypeScript and includes full type definitions. All Contentful rich text types are re-exported for convenience:
273
349
 
@@ -277,7 +353,9 @@ import type {
277
353
  Block,
278
354
  Inline,
279
355
  Text,
280
- ContentfulRichTextEditorProps
356
+ ContentfulRichTextEditorProps,
357
+ ContentfulFieldConfiguration, // NEW v2.0
358
+ ParsedEditorConfig // NEW v2.0
281
359
  } from '@crashbytes/contentful-richtext-editor';
282
360
  ```
283
361
 
@@ -288,19 +366,6 @@ import type {
288
366
  - Safari 13+
289
367
  - Edge 80+
290
368
 
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
-
304
369
  ## 🤝 Contributing
305
370
 
306
371
  Contributions are welcome! Please feel free to submit a Pull Request.
@@ -321,12 +386,6 @@ MIT © [CrashBytes](https://github.com/CrashBytes)
321
386
  - [@contentful/rich-text-types](https://www.npmjs.com/package/@contentful/rich-text-types) - Contentful rich text type definitions
322
387
  - [@tiptap/react](https://www.npmjs.com/package/@tiptap/react) - The underlying editor framework
323
388
 
324
- ## 📈 Version History
325
-
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
329
-
330
389
  ---
331
390
 
332
391
  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": "2.0.4",
3
+ "version": "2.0.5",
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,7 +9,7 @@
9
9
  "files": [
10
10
  "dist"
11
11
  ],
12
- "publishConfig": {
12
+ "publishConfig": {
13
13
  "access": "public"
14
14
  },
15
15
  "keywords": [