magic-editor-x 1.0.0

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 (37) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +890 -0
  3. package/dist/_chunks/App-B1FgOsWa.mjs +2143 -0
  4. package/dist/_chunks/App-mtrlABtd.js +2146 -0
  5. package/dist/_chunks/LicensePage-BnyWSrWs.js +375 -0
  6. package/dist/_chunks/LicensePage-CWH-AFR-.mjs +373 -0
  7. package/dist/_chunks/LiveCollaborationPanel-DbDHwr2C.js +222 -0
  8. package/dist/_chunks/LiveCollaborationPanel-ryjcDAA7.mjs +220 -0
  9. package/dist/_chunks/Settings-Bk9bxJTy.js +440 -0
  10. package/dist/_chunks/Settings-D-V2MLVm.mjs +438 -0
  11. package/dist/_chunks/de-CSrHZWEb.mjs +295 -0
  12. package/dist/_chunks/de-CzSo1oD2.js +295 -0
  13. package/dist/_chunks/en-DuQun2v4.mjs +295 -0
  14. package/dist/_chunks/en-DxIkVPUh.js +295 -0
  15. package/dist/_chunks/es-DAQ_97zx.js +273 -0
  16. package/dist/_chunks/es-DEB0CA8S.mjs +273 -0
  17. package/dist/_chunks/fr-Bqkhvdx2.mjs +273 -0
  18. package/dist/_chunks/fr-ChPabvNP.js +273 -0
  19. package/dist/_chunks/getTranslation-C4uWR0DB.mjs +50985 -0
  20. package/dist/_chunks/getTranslation-D35vbDap.js +51001 -0
  21. package/dist/_chunks/index-B5MzUyo0.mjs +2541 -0
  22. package/dist/_chunks/index-BRVqbnOb.mjs +4450 -0
  23. package/dist/_chunks/index-BiLy_f7C.js +2540 -0
  24. package/dist/_chunks/index-CQx7-dFP.js +4472 -0
  25. package/dist/_chunks/pt-BMoYltav.mjs +273 -0
  26. package/dist/_chunks/pt-Cm74LpyZ.js +273 -0
  27. package/dist/_chunks/tools-CjnQJ9w2.mjs +2155 -0
  28. package/dist/_chunks/tools-DNt2tioN.js +2186 -0
  29. package/dist/admin/index.js +3 -0
  30. package/dist/admin/index.mjs +4 -0
  31. package/dist/server/index.js +2554 -0
  32. package/dist/server/index.mjs +2544 -0
  33. package/dist/style.css +164 -0
  34. package/package.json +122 -0
  35. package/pics/collab-magiceditorX.png +0 -0
  36. package/pics/editorX.png +0 -0
  37. package/pics/liveCollabwidget1.png +0 -0
package/README.md ADDED
@@ -0,0 +1,890 @@
1
+ # Magic Editor X
2
+
3
+ **Advanced Block-Based Content Editor for Strapi v5 with Real-Time Collaboration**
4
+
5
+ [![NPM Version](https://img.shields.io/npm/v/magic-editor-x.svg)](https://www.npmjs.com/package/magic-editor-x)
6
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+ [![Strapi v5](https://img.shields.io/badge/Strapi-v5-7C3AED.svg)](https://strapi.io)
8
+ [![Editor.js](https://img.shields.io/badge/Editor.js-2.31.0-000.svg)](https://editorjs.io)
9
+
10
+ ---
11
+
12
+ ## Introduction
13
+
14
+ Magic Editor X is a production-ready Strapi v5 Custom Field that brings the power of Editor.js to your content management workflow. Unlike traditional WYSIWYG replacements or plugins that override Strapi's default editor, Magic Editor X integrates as a **proper Custom Field** in Strapi's Content-Type Builder, giving you complete control over when and where to use it.
15
+
16
+ Built on proven technologies like Editor.js for the editing interface and Y.js for conflict-free real-time collaboration, this plugin provides a modern, extensible content editing experience that scales from solo developers to large editorial teams.
17
+
18
+ ### Why Magic Editor X?
19
+
20
+ **For Developers:**
21
+ - Clean JSON output instead of unstructured HTML
22
+ - 25+ pre-configured Editor.js tools out of the box
23
+ - Type-safe content structure with versioned schemas
24
+ - Real-time collaboration with CRDT (Conflict-free Replicated Data Types)
25
+ - Full TypeScript support with proper type definitions
26
+ - Extensible architecture for custom block types
27
+
28
+ **For Content Teams:**
29
+ - Familiar Medium-style block editor experience
30
+ - Live collaborative editing with presence indicators
31
+ - Keyboard shortcuts for fast content creation
32
+ - Inline formatting without toolbar clutter
33
+ - Media Library integration for asset management
34
+ - AI-powered content suggestions (premium)
35
+
36
+ ---
37
+
38
+ ## Screenshots
39
+
40
+ ### Editor Interface
41
+ ![Magic Editor X Interface](https://raw.githubusercontent.com/Schero94/magic-editor-x/main/pics/editorX.png)
42
+
43
+ ### Real-Time Collaboration
44
+ ![Live Collaboration](https://raw.githubusercontent.com/Schero94/magic-editor-x/main/pics/collab-magiceditorX.png)
45
+
46
+ ### Collaboration Widget
47
+ ![Collaboration Panel](https://raw.githubusercontent.com/Schero94/magic-editor-x/main/pics/liveCollabwidget1.png)
48
+
49
+ ---
50
+
51
+ ## Architecture Overview
52
+
53
+ Magic Editor X follows a clean client-server architecture with three main components:
54
+
55
+ ### Client-Side (Admin Panel)
56
+
57
+ ```
58
+ admin/
59
+ ├── src/
60
+ │ ├── components/
61
+ │ │ ├── EditorJS/ # Main editor component
62
+ │ │ ├── EditorTools/ # Custom tools (Button, Hyperlink, AI)
63
+ │ │ ├── MediaLib/ # Strapi Media Library adapter
64
+ │ │ └── LiveCollaborationPanel.jsx # Collaboration UI
65
+ │ ├── hooks/
66
+ │ │ ├── useMagicCollaboration.js # Y.js & Socket.io integration
67
+ │ │ ├── useAIAssistant.js # AI features
68
+ │ │ └── useLicense.js # License management
69
+ │ ├── config/
70
+ │ │ └── tools.js # Editor.js tools configuration
71
+ │ └── index.js # Plugin registration
72
+ ```
73
+
74
+ **Key Technologies:**
75
+ - **React 18** - UI components with hooks
76
+ - **Editor.js 2.31** - Block-based editor core
77
+ - **Y.js 13.6** - CRDT for real-time sync
78
+ - **Socket.io-client 4.8** - WebSocket communication
79
+ - **IndexedDB** - Local persistence via y-indexeddb
80
+
81
+ ### Server-Side (Strapi Backend)
82
+
83
+ ```
84
+ server/
85
+ ├── src/
86
+ │ ├── controllers/
87
+ │ │ ├── editor-controller.js # Image upload, link previews
88
+ │ │ ├── collaboration-controller.js # Permission management
89
+ │ │ ├── realtime-controller.js # Session tokens
90
+ │ │ └── license-controller.js # License validation
91
+ │ ├── services/
92
+ │ │ ├── realtime-service.js # Y.js document management
93
+ │ │ ├── access-service.js # Permission checks
94
+ │ │ ├── license-service.js # License API
95
+ │ │ └── snapshot-service.js # Document snapshots
96
+ │ ├── routes/
97
+ │ │ ├── admin.js # Admin panel routes
98
+ │ │ └── content-api.js # Public API routes
99
+ │ └── config/
100
+ │ └── index.js # Plugin configuration
101
+ ```
102
+
103
+ **Key Technologies:**
104
+ - **Socket.io 4.8** - WebSocket server
105
+ - **Y.js 13.6** - Server-side CRDT state
106
+ - **Open Graph Scraper** - Link metadata extraction
107
+ - **Strapi 5.31** - Backend framework
108
+
109
+ ### Data Flow
110
+
111
+ 1. **Editor Changes** → Y.js Document (CRDT) → Socket.io → Server → Other Clients
112
+ 2. **Image Upload** → Strapi Controller → Strapi Upload Service → Media Library
113
+ 3. **Link Preview** → Backend Scraper → OpenGraph Metadata → Client
114
+ 4. **Collaboration** → Permission Check → Session Token → WebSocket Connection
115
+
116
+ ---
117
+
118
+ ## Features Deep Dive
119
+
120
+ ### 1. Block-Based Content Structure
121
+
122
+ Magic Editor X stores content as structured JSON, not HTML. Each block has a unique ID, type, and data object:
123
+
124
+ ```json
125
+ {
126
+ "time": 1699999999999,
127
+ "blocks": [
128
+ {
129
+ "id": "abc123",
130
+ "type": "header",
131
+ "data": {
132
+ "text": "Hello World",
133
+ "level": 2
134
+ }
135
+ },
136
+ {
137
+ "id": "def456",
138
+ "type": "paragraph",
139
+ "data": {
140
+ "text": "This is <b>bold</b> and <i>italic</i> text."
141
+ }
142
+ },
143
+ {
144
+ "id": "ghi789",
145
+ "type": "list",
146
+ "data": {
147
+ "style": "unordered",
148
+ "items": [
149
+ {
150
+ "content": "First item",
151
+ "items": []
152
+ },
153
+ {
154
+ "content": "Second item with nested list",
155
+ "items": [
156
+ {
157
+ "content": "Nested item",
158
+ "items": []
159
+ }
160
+ ]
161
+ }
162
+ ]
163
+ }
164
+ }
165
+ ],
166
+ "version": "2.31.0"
167
+ }
168
+ ```
169
+
170
+ **Benefits:**
171
+ - Predictable, type-safe content structure
172
+ - Easy to parse, transform, and render
173
+ - Version control friendly (no HTML diffs)
174
+ - Can be validated against JSON schemas
175
+ - Simple to migrate between systems
176
+
177
+ ### 2. Real-Time Collaboration (CRDT Technology)
178
+
179
+ Magic Editor X uses Y.js, a battle-tested CRDT implementation, to enable true real-time collaboration without conflicts:
180
+
181
+ **How It Works:**
182
+
183
+ 1. **Y.Doc Creation** - Each content entry gets a shared Y.js document
184
+ 2. **Local Changes** - Edits create CRDT operations (not plain text diffs)
185
+ 3. **Sync Protocol** - Operations are sent via Socket.io to the server
186
+ 4. **Server Broadcast** - Server distributes operations to all connected clients
187
+ 5. **Automatic Merge** - Y.js guarantees conflict-free merges (no "last write wins")
188
+ 6. **Persistence** - Changes are stored in IndexedDB for offline capability
189
+
190
+ **Example: Collaborative Editing Flow**
191
+
192
+ ```javascript
193
+ // Client A types "Hello" at position 0
194
+ const update = Y.encodeStateAsUpdate(yDoc);
195
+ socket.emit('collab:update', update);
196
+
197
+ // Server broadcasts to all clients
198
+ socket.broadcast.to(roomId).emit('collab:update', update);
199
+
200
+ // Client B applies the update
201
+ Y.applyUpdate(yDoc, update);
202
+ // Editor automatically re-renders with "Hello"
203
+ ```
204
+
205
+ **Presence & Cursors:**
206
+
207
+ ```javascript
208
+ // Awareness protocol for presence
209
+ awareness.setLocalStateField('cursor', {
210
+ blockId: 'abc123',
211
+ position: 42,
212
+ user: {
213
+ id: 'user-1',
214
+ name: 'John Doe',
215
+ color: '#FF6B6B'
216
+ }
217
+ });
218
+
219
+ // Other clients receive cursor updates
220
+ awareness.on('change', ({ added, updated, removed }) => {
221
+ // Render remote cursor indicators
222
+ renderCursors(awareness.getStates());
223
+ });
224
+ ```
225
+
226
+ ### 3. 25+ Editor.js Tools
227
+
228
+ Magic Editor X comes with a comprehensive collection of tools, categorized for easy reference:
229
+
230
+ #### Block Tools (21 Tools)
231
+
232
+ | Tool | Description | Package | Shortcut |
233
+ |------|-------------|---------|----------|
234
+ | **Header** | H1-H6 headings with alignment | `@editorjs/header` | `CMD+SHIFT+H` |
235
+ | **Paragraph** | Text blocks with inline formatting | `@editorjs/paragraph` | - |
236
+ | **Nested List** | Multi-level ordered/unordered lists | `@editorjs/nested-list` | `CMD+SHIFT+L` |
237
+ | **Checklist** | Interactive todo lists | `@editorjs/checklist` | `CMD+SHIFT+C` |
238
+ | **Quote** | Blockquotes with caption | `@editorjs/quote` | `CMD+SHIFT+Q` |
239
+ | **Warning** | Alert boxes | `@editorjs/warning` | `CMD+SHIFT+W` |
240
+ | **Code** | Basic code blocks | `@editorjs/code` | `CMD+SHIFT+P` |
241
+ | **Code (Highlight)** | Syntax-highlighted code | `@calumk/editorjs-codeflask` | - |
242
+ | **Delimiter** | Visual section separator | `@editorjs/delimiter` | `CMD+SHIFT+D` |
243
+ | **Table** | Create/edit tables | `@editorjs/table` | `CMD+SHIFT+T` |
244
+ | **Embed** | YouTube, Vimeo, Twitter, etc. | `@editorjs/embed` | - |
245
+ | **Raw HTML** | Insert raw HTML | `@editorjs/raw` | - |
246
+ | **Image** | Upload by file or URL | `@editorjs/image` | - |
247
+ | **Simple Image** | Image by URL only | `@editorjs/simple-image` | - |
248
+ | **Link Preview** | Rich link cards with metadata | `@editorjs/link` | - |
249
+ | **Attaches** | File attachments | `@editorjs/attaches` | - |
250
+ | **Media Library** | Strapi Media Library picker | Custom | - |
251
+ | **Personality** | Author/person cards | `@editorjs/personality` | - |
252
+ | **Alert** | Colored alert messages | `editorjs-alert` | `CMD+SHIFT+A` |
253
+ | **Toggle** | Collapsible content blocks | `editorjs-toggle-block` | - |
254
+ | **Button** | CTA buttons | Custom | - |
255
+
256
+ #### Inline Tools (7 Tools)
257
+
258
+ | Tool | Description | Package | Shortcut |
259
+ |------|-------------|---------|----------|
260
+ | **Bold** | Bold text | Built-in | `CMD+B` |
261
+ | **Italic** | Italic text | Built-in | `CMD+I` |
262
+ | **Marker** | Highlight text | `@editorjs/marker` | `CMD+SHIFT+M` |
263
+ | **Inline Code** | Code formatting | `@editorjs/inline-code` | `CMD+SHIFT+I` |
264
+ | **Underline** | Underline text | `@editorjs/underline` | `CMD+U` |
265
+ | **Strikethrough** | Strike through text | `@sotaproject/strikethrough` | `CMD+SHIFT+S` |
266
+ | **Hyperlink** | Links with target/rel | Custom | `CMD+K` |
267
+ | **Tooltip** | Add tooltips to text | `editorjs-tooltip` | - |
268
+
269
+ #### Block Tunes (3 Tunes)
270
+
271
+ | Tune | Description | Package |
272
+ |------|-------------|---------|
273
+ | **Alignment** | Left, center, right, justify | `editorjs-text-alignment-blocktune` |
274
+ | **Indent** | Multi-level indentation | `editorjs-indent-tune` |
275
+ | **Text Variant** | Call-out, citation, details styles | `@editorjs/text-variant-tune` |
276
+
277
+ #### Plugins (2 Plugins)
278
+
279
+ | Plugin | Description | Package |
280
+ |--------|-------------|---------|
281
+ | **Undo/Redo** | History management | `editorjs-undo` |
282
+ | **Drag & Drop** | Reorder blocks by dragging | `editorjs-drag-drop` |
283
+
284
+ ### 4. Media Library Integration
285
+
286
+ Seamless integration with Strapi's built-in Media Library:
287
+
288
+ ```javascript
289
+ // Custom MediaLibAdapter bridges Editor.js and Strapi
290
+ class MediaLibAdapter {
291
+ static get toolbox() {
292
+ return {
293
+ title: 'Media Library',
294
+ icon: '<svg>...</svg>'
295
+ };
296
+ }
297
+
298
+ render() {
299
+ const button = document.createElement('button');
300
+ button.textContent = 'Choose from Media Library';
301
+ button.onclick = () => {
302
+ // Opens Strapi's Media Library modal
303
+ this.config.mediaLibToggleFunc();
304
+ };
305
+ return button;
306
+ }
307
+
308
+ save(blockContent) {
309
+ return {
310
+ url: blockContent.url,
311
+ caption: blockContent.caption,
312
+ alt: blockContent.alt
313
+ };
314
+ }
315
+ }
316
+ ```
317
+
318
+ ### 5. AI-Powered Features (Premium)
319
+
320
+ Built-in AI assistant for content enhancement:
321
+
322
+ **Grammar Check:**
323
+ ```javascript
324
+ // Automatically fix grammar and spelling
325
+ aiAssistant.check(text) → corrected text
326
+ ```
327
+
328
+ **Style Improvement:**
329
+ ```javascript
330
+ // Make text more professional, casual, or friendly
331
+ aiAssistant.rewrite(text, style: 'professional') → improved text
332
+ ```
333
+
334
+ **Content Generation:**
335
+ ```javascript
336
+ // Generate content based on prompts
337
+ aiAssistant.generate(prompt) → generated content
338
+ ```
339
+
340
+ ---
341
+
342
+ ## Installation & Setup
343
+
344
+ ### 1. Install Package
345
+
346
+ ```bash
347
+ npm install magic-editor-x
348
+ # or
349
+ yarn add magic-editor-x
350
+ # or
351
+ pnpm add magic-editor-x
352
+ ```
353
+
354
+ ### 2. Enable Plugin
355
+
356
+ Create or update `config/plugins.ts` (or `.js`):
357
+
358
+ ```typescript
359
+ export default () => ({
360
+ 'magic-editor-x': {
361
+ enabled: true,
362
+ config: {
363
+ // Editor Configuration
364
+ enabledTools: [
365
+ 'header', 'paragraph', 'list', 'checklist', 'quote',
366
+ 'warning', 'code', 'delimiter', 'table', 'embed',
367
+ 'raw', 'image', 'mediaLib', 'linkTool'
368
+ ],
369
+
370
+ // Upload Limits
371
+ maxImageSize: 10 * 1024 * 1024, // 10MB
372
+ allowedImageTypes: [
373
+ 'image/jpeg', 'image/png', 'image/gif',
374
+ 'image/webp', 'image/svg+xml'
375
+ ],
376
+
377
+ // Link Previews
378
+ linkPreviewTimeout: 10000, // 10 seconds
379
+
380
+ // Real-Time Collaboration
381
+ collaboration: {
382
+ enabled: true,
383
+ sessionTTL: 2 * 60 * 1000, // 2 minutes
384
+ wsPath: '/magic-editor-x/realtime',
385
+ wsUrl: null, // Auto-detect or set custom URL
386
+ allowedOrigins: ['http://localhost:1337'],
387
+ allowedAdminRoles: ['strapi-super-admin'],
388
+ allowedAdminUserIds: [],
389
+ },
390
+ },
391
+ },
392
+ });
393
+ ```
394
+
395
+ ### 3. Content Security Policy (Optional)
396
+
397
+ For link previews with external images, update `config/middlewares.ts`:
398
+
399
+ ```typescript
400
+ export default [
401
+ 'strapi::logger',
402
+ 'strapi::errors',
403
+ {
404
+ name: 'strapi::security',
405
+ config: {
406
+ contentSecurityPolicy: {
407
+ useDefaults: true,
408
+ directives: {
409
+ 'connect-src': ["'self'", 'https:'],
410
+ 'img-src': [
411
+ "'self'",
412
+ 'data:',
413
+ 'blob:',
414
+ 'market-assets.strapi.io',
415
+ '*', // Allow external images for link previews
416
+ ],
417
+ 'media-src': [
418
+ "'self'",
419
+ 'data:',
420
+ 'blob:',
421
+ 'market-assets.strapi.io',
422
+ ],
423
+ upgradeInsecureRequests: null,
424
+ },
425
+ },
426
+ },
427
+ },
428
+ 'strapi::cors',
429
+ 'strapi::poweredBy',
430
+ 'strapi::query',
431
+ 'strapi::body',
432
+ 'strapi::session',
433
+ 'strapi::favicon',
434
+ 'strapi::public',
435
+ ];
436
+ ```
437
+
438
+ ### 4. Build & Start
439
+
440
+ ```bash
441
+ # Build admin panel with plugin
442
+ npm run build
443
+
444
+ # Start in development mode
445
+ npm run develop
446
+
447
+ # Or in production
448
+ npm run start
449
+ ```
450
+
451
+ ### 5. Add Field to Content Type
452
+
453
+ 1. Navigate to **Content-Type Builder**
454
+ 2. Select a content type or create a new one
455
+ 3. Click **Add another field**
456
+ 4. Go to the **Custom** tab
457
+ 5. Select **Magic Editor X**
458
+ 6. Configure field name and options
459
+ 7. Click **Finish** and save the content type
460
+
461
+ ---
462
+
463
+ ## Configuration Reference
464
+
465
+ ### Plugin Configuration
466
+
467
+ All options for `config/plugins.ts`:
468
+
469
+ ```typescript
470
+ interface MagicEditorXConfig {
471
+ // Tool Selection
472
+ enabledTools?: string[]; // Default: all tools
473
+
474
+ // Upload Settings
475
+ maxImageSize?: number; // Bytes, default: 10MB
476
+ allowedImageTypes?: string[]; // MIME types
477
+
478
+ // Link Preview Settings
479
+ linkPreviewTimeout?: number; // Milliseconds, default: 10000
480
+
481
+ // Collaboration Settings
482
+ collaboration?: {
483
+ enabled: boolean; // Default: true
484
+ sessionTTL: number; // Milliseconds, default: 120000 (2 min)
485
+ wsPath: string; // WebSocket path, default: '/magic-editor-x/realtime'
486
+ wsUrl: string | null; // Custom WebSocket URL (for proxies)
487
+ allowedOrigins: string[]; // CORS origins
488
+ allowedAdminRoles: string[]; // Roles that can collaborate
489
+ allowedAdminUserIds: number[]; // Specific user IDs
490
+ };
491
+ }
492
+ ```
493
+
494
+ ### Field Options
495
+
496
+ When adding the field in Content-Type Builder:
497
+
498
+ **Base Settings:**
499
+ - **Placeholder** - Placeholder text (default: "Start writing or press Tab...")
500
+ - **Required** - Make field mandatory
501
+ - **Private** - Exclude from API responses
502
+
503
+ **Advanced Settings:**
504
+ - **Minimum Height** - Editor height in pixels (default: 300)
505
+ - **Max Length** - Maximum characters (optional)
506
+ - **Min Length** - Minimum characters (optional)
507
+
508
+ ---
509
+
510
+ ## API Reference
511
+
512
+ ### Public API Endpoints
513
+
514
+ These endpoints are available for content-api usage:
515
+
516
+ #### Fetch Link Metadata
517
+
518
+ ```http
519
+ GET /api/magic-editor-x/link?url=https://example.com
520
+ ```
521
+
522
+ **Response:**
523
+ ```json
524
+ {
525
+ "success": 1,
526
+ "meta": {
527
+ "title": "Example Domain",
528
+ "description": "Example domain for documentation",
529
+ "image": {
530
+ "url": "https://example.com/og-image.jpg"
531
+ }
532
+ }
533
+ }
534
+ ```
535
+
536
+ #### Upload Image by File
537
+
538
+ ```http
539
+ POST /api/magic-editor-x/image/byFile
540
+ Content-Type: multipart/form-data
541
+
542
+ files.image: <file>
543
+ ```
544
+
545
+ **Response:**
546
+ ```json
547
+ {
548
+ "success": 1,
549
+ "file": {
550
+ "url": "https://cdn.example.com/image.jpg",
551
+ "name": "image.jpg",
552
+ "size": 123456
553
+ }
554
+ }
555
+ ```
556
+
557
+ #### Upload Image by URL
558
+
559
+ ```http
560
+ POST /api/magic-editor-x/image/byUrl
561
+ Content-Type: application/json
562
+
563
+ {
564
+ "url": "https://example.com/image.jpg"
565
+ }
566
+ ```
567
+
568
+ **Response:**
569
+ ```json
570
+ {
571
+ "success": 1,
572
+ "file": {
573
+ "url": "https://cdn.example.com/image.jpg",
574
+ "name": "image.jpg",
575
+ "size": 123456
576
+ }
577
+ }
578
+ ```
579
+
580
+ ### Admin API Endpoints
581
+
582
+ These endpoints require authentication and admin permissions:
583
+
584
+ #### License Management
585
+
586
+ ```http
587
+ GET /magic-editor-x/license/status
588
+ GET /magic-editor-x/license/limits
589
+ POST /magic-editor-x/license/auto-create
590
+ POST /magic-editor-x/license/store-key
591
+ ```
592
+
593
+ #### Collaboration Permissions
594
+
595
+ ```http
596
+ GET /magic-editor-x/collaboration/permissions
597
+ POST /magic-editor-x/collaboration/permissions
598
+ PUT /magic-editor-x/collaboration/permissions/:id
599
+ DELETE /magic-editor-x/collaboration/permissions/:id
600
+ ```
601
+
602
+ #### Real-Time Sessions
603
+
604
+ ```http
605
+ POST /magic-editor-x/realtime/session-token
606
+ ```
607
+
608
+ **Request:**
609
+ ```json
610
+ {
611
+ "roomId": "api::article.article|abc123|content",
612
+ "fieldName": "content"
613
+ }
614
+ ```
615
+
616
+ **Response:**
617
+ ```json
618
+ {
619
+ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
620
+ "expiresAt": 1699999999999
621
+ }
622
+ ```
623
+
624
+ ---
625
+
626
+ ## Collaboration System
627
+
628
+ ### Permission Model
629
+
630
+ Magic Editor X uses a flexible role-based permission system:
631
+
632
+ **Roles:**
633
+ - **Owner** - Full control (edit, delete, manage permissions)
634
+ - **Editor** - Can edit content
635
+ - **Viewer** - Read-only access
636
+
637
+ **Permission Scope:**
638
+ - Per content type (e.g., `api::article.article`)
639
+ - Per user or role
640
+ - Inherits from Strapi's built-in RBAC
641
+
642
+ ### Managing Collaborators
643
+
644
+ Navigate to **Plugins > Magic Editor X > Collaboration** to:
645
+
646
+ 1. **Add Collaborator**
647
+ - Select user
648
+ - Choose content type
649
+ - Assign role (Viewer, Editor, Owner)
650
+
651
+ 2. **Update Permission**
652
+ - Change role
653
+ - Modify content type access
654
+
655
+ 3. **Remove Collaborator**
656
+ - Revoke access
657
+
658
+ ### Collaboration Limits
659
+
660
+ Limits are enforced based on your license:
661
+
662
+ | License | Concurrent Collaborators |
663
+ |---------|-------------------------|
664
+ | FREE | 2 |
665
+ | PREMIUM | 10 |
666
+ | ADVANCED | Unlimited |
667
+
668
+ **Note:** The editor itself is completely free. You only pay for extended collaboration features.
669
+
670
+ ---
671
+
672
+ ## Pricing
673
+
674
+ Magic Editor X follows a freemium model:
675
+
676
+ | Feature | FREE | PREMIUM | ADVANCED |
677
+ |---------|------|---------|----------|
678
+ | **Price** | $0 | $9.90/mo | $24.90/mo |
679
+ | Full Editor | Yes | Yes | Yes |
680
+ | All 25+ Tools | Yes | Yes | Yes |
681
+ | Real-Time Sync | Yes | Yes | Yes |
682
+ | Collaborators | 2 | 10 | Unlimited |
683
+ | Version History | - | Yes | Yes |
684
+ | AI Assistant | - | Pay-per-use | Included |
685
+ | Priority Support | - | Email | Email + Chat |
686
+ | Custom Blocks | - | - | Yes |
687
+
688
+ **Get started:** https://store.magicdx.dev/
689
+
690
+ ---
691
+
692
+ ## Development & Extension
693
+
694
+ ### Custom Block Types
695
+
696
+ Create your own block tools:
697
+
698
+ ```javascript
699
+ // custom-tools/MyCustomTool.js
700
+ export default class MyCustomTool {
701
+ static get toolbox() {
702
+ return {
703
+ title: 'My Tool',
704
+ icon: '<svg>...</svg>'
705
+ };
706
+ }
707
+
708
+ constructor({ data, api, config }) {
709
+ this.data = data;
710
+ this.api = api;
711
+ this.config = config;
712
+ }
713
+
714
+ render() {
715
+ const wrapper = document.createElement('div');
716
+ wrapper.classList.add('my-custom-tool');
717
+ // Add your UI
718
+ return wrapper;
719
+ }
720
+
721
+ save(blockContent) {
722
+ return {
723
+ // Your data structure
724
+ text: blockContent.querySelector('input').value
725
+ };
726
+ }
727
+
728
+ static get sanitize() {
729
+ return {
730
+ text: {} // Sanitizer config
731
+ };
732
+ }
733
+ }
734
+ ```
735
+
736
+ **Register in `config/tools.js`:**
737
+
738
+ ```javascript
739
+ import MyCustomTool from './custom-tools/MyCustomTool';
740
+
741
+ export const getTools = ({ mediaLibToggleFunc, pluginId }) => {
742
+ return {
743
+ // ... existing tools
744
+ myCustomTool: {
745
+ class: MyCustomTool,
746
+ config: {
747
+ // Your config
748
+ }
749
+ }
750
+ };
751
+ };
752
+ ```
753
+
754
+ ### Extending Collaboration
755
+
756
+ Hook into collaboration events:
757
+
758
+ ```javascript
759
+ // In your component
760
+ const { awareness } = useMagicCollaboration({
761
+ enabled: true,
762
+ roomId: 'my-room',
763
+ onRemoteUpdate: () => {
764
+ console.log('Remote update received');
765
+ }
766
+ });
767
+
768
+ // Listen to presence changes
769
+ awareness.on('change', ({ added, updated, removed }) => {
770
+ console.log('Users joined:', added);
771
+ console.log('Users updated:', updated);
772
+ console.log('Users left:', removed);
773
+ });
774
+ ```
775
+
776
+ ---
777
+
778
+ ## Troubleshooting
779
+
780
+ ### Common Issues
781
+
782
+ **1. Editor Not Loading**
783
+
784
+ Check browser console for errors. Common causes:
785
+ - Plugin not enabled in `config/plugins.ts`
786
+ - Build not run after installation (`npm run build`)
787
+ - CSP blocking external resources
788
+
789
+ **2. Image Upload Failing**
790
+
791
+ Verify:
792
+ - Strapi Upload plugin is enabled
793
+ - File size within limits (default 10MB)
794
+ - File type is allowed
795
+ - User has upload permissions
796
+
797
+ **3. Collaboration Not Working**
798
+
799
+ Debug checklist:
800
+ - WebSocket connection established (check Network tab)
801
+ - Session token valid (check `/realtime/session-token` response)
802
+ - User has collaboration permissions
803
+ - Firewall/proxy allows WebSocket connections
804
+
805
+ **4. Link Previews Not Showing**
806
+
807
+ Ensure:
808
+ - CSP allows `img-src: '*'` in middlewares config
809
+ - Target site returns OpenGraph metadata
810
+ - Link preview timeout not too short (default: 10s)
811
+
812
+ ### Enable Debug Logging
813
+
814
+ Add to `config/plugins.ts`:
815
+
816
+ ```typescript
817
+ {
818
+ 'magic-editor-x': {
819
+ config: {
820
+ debug: true // Enable verbose logging
821
+ }
822
+ }
823
+ }
824
+ ```
825
+
826
+ ---
827
+
828
+ ## Roadmap
829
+
830
+ - **Version History** - Track all content changes with restore capability
831
+ - **Custom Blocks API** - Simplified API for creating custom tools
832
+ - **Advanced AI** - Content suggestions, auto-completion, tone analysis
833
+ - **Comments & Annotations** - Inline comments for editorial workflow
834
+ - **Offline Mode** - Full offline editing with sync on reconnect
835
+ - **Import/Export** - Markdown, HTML, DOCX conversion
836
+ - **Templates** - Pre-built content templates
837
+
838
+ ---
839
+
840
+ ## Resources
841
+
842
+ - **Documentation:** https://docs.magicdx.dev/
843
+ - **Store:** https://store.magicdx.dev/
844
+ - **GitHub:** https://github.com/Schero94/magic-editor-x
845
+ - **Strapi Custom Fields:** https://docs.strapi.io/cms/features/custom-fields
846
+ - **Editor.js:** https://editorjs.io/
847
+ - **Y.js:** https://docs.yjs.dev/
848
+
849
+ ---
850
+
851
+ ## Contributing
852
+
853
+ Contributions are welcome! Please:
854
+
855
+ 1. Fork the repository
856
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
857
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
858
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
859
+ 5. Open a Pull Request
860
+
861
+ **Development Setup:**
862
+
863
+ ```bash
864
+ git clone https://github.com/Schero94/magic-editor-x.git
865
+ cd magic-editor-x
866
+ npm install
867
+ npm run watch:link
868
+ ```
869
+
870
+ ---
871
+
872
+ ## License
873
+
874
+ MIT License - See [LICENSE](LICENSE) for details
875
+
876
+ Copyright (c) 2024 Schero D.
877
+
878
+ ---
879
+
880
+ ## Support
881
+
882
+ - **Email:** support@magicdx.dev
883
+ - **Issues:** https://github.com/Schero94/magic-editor-x/issues
884
+ - **Discord:** https://discord.gg/magicdx
885
+
886
+ ---
887
+
888
+ **Built with dedication by [Schero D.](https://github.com/Schero94)**
889
+
890
+ Part of the MagicDX Plugin Suite for Strapi