magic-editor-x 1.0.0 → 1.1.1
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 +81 -1
- package/dist/server/index.js +66 -2
- package/dist/server/index.mjs +66 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ Magic Editor X is a production-ready Strapi v5 Custom Field that brings the powe
|
|
|
15
15
|
|
|
16
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
17
|
|
|
18
|
-
### Why Magic Editor X?
|
|
18
|
+
### Why Magic Editor X? :)
|
|
19
19
|
|
|
20
20
|
**For Developers:**
|
|
21
21
|
- Clean JSON output instead of unstructured HTML
|
|
@@ -387,6 +387,11 @@ export default () => ({
|
|
|
387
387
|
allowedAdminRoles: ['strapi-super-admin'],
|
|
388
388
|
allowedAdminUserIds: [],
|
|
389
389
|
},
|
|
390
|
+
|
|
391
|
+
// API Response Settings
|
|
392
|
+
api: {
|
|
393
|
+
autoParseJSON: true, // Auto-parse JSON strings to objects in API responses
|
|
394
|
+
},
|
|
390
395
|
},
|
|
391
396
|
},
|
|
392
397
|
});
|
|
@@ -478,6 +483,11 @@ interface MagicEditorXConfig {
|
|
|
478
483
|
// Link Preview Settings
|
|
479
484
|
linkPreviewTimeout?: number; // Milliseconds, default: 10000
|
|
480
485
|
|
|
486
|
+
// API Response Settings
|
|
487
|
+
api?: {
|
|
488
|
+
autoParseJSON: boolean; // Auto-parse JSON strings to objects, default: true
|
|
489
|
+
};
|
|
490
|
+
|
|
481
491
|
// Collaboration Settings
|
|
482
492
|
collaboration?: {
|
|
483
493
|
enabled: boolean; // Default: true
|
|
@@ -507,6 +517,76 @@ When adding the field in Content-Type Builder:
|
|
|
507
517
|
|
|
508
518
|
---
|
|
509
519
|
|
|
520
|
+
## API Response Format
|
|
521
|
+
|
|
522
|
+
### Automatic JSON Parsing
|
|
523
|
+
|
|
524
|
+
Magic Editor X automatically transforms JSON string fields into structured objects in API responses for better developer experience.
|
|
525
|
+
|
|
526
|
+
**Without auto-parsing (raw Strapi response):**
|
|
527
|
+
```json
|
|
528
|
+
{
|
|
529
|
+
"data": {
|
|
530
|
+
"id": 1,
|
|
531
|
+
"documentId": "abc123",
|
|
532
|
+
"editorX": "{\"time\":1699999999999,\"blocks\":[{\"id\":\"xyz\",\"type\":\"paragraph\",\"data\":{\"text\":\"Hello\"}}],\"version\":\"2.31.0\"}"
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
**With auto-parsing (Magic Editor X middleware active):**
|
|
538
|
+
```json
|
|
539
|
+
{
|
|
540
|
+
"data": {
|
|
541
|
+
"id": 1,
|
|
542
|
+
"documentId": "abc123",
|
|
543
|
+
"editorX": {
|
|
544
|
+
"time": 1699999999999,
|
|
545
|
+
"blocks": [
|
|
546
|
+
{
|
|
547
|
+
"id": "xyz",
|
|
548
|
+
"type": "paragraph",
|
|
549
|
+
"data": {
|
|
550
|
+
"text": "Hello"
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
],
|
|
554
|
+
"version": "2.31.0"
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
**Configuration:**
|
|
561
|
+
|
|
562
|
+
Auto-parsing is enabled by default. To disable it, add to `config/plugins.ts`:
|
|
563
|
+
|
|
564
|
+
```typescript
|
|
565
|
+
{
|
|
566
|
+
'magic-editor-x': {
|
|
567
|
+
config: {
|
|
568
|
+
api: {
|
|
569
|
+
autoParseJSON: false // Disable automatic JSON parsing
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
**Manual Parsing (if auto-parse is disabled):**
|
|
577
|
+
|
|
578
|
+
```javascript
|
|
579
|
+
// Client-side parsing
|
|
580
|
+
const response = await fetch('/api/articles/1');
|
|
581
|
+
const data = await response.json();
|
|
582
|
+
|
|
583
|
+
// Parse Editor.js field manually
|
|
584
|
+
const editorContent = JSON.parse(data.data.editorX);
|
|
585
|
+
console.log(editorContent.blocks); // Array of blocks
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
---
|
|
589
|
+
|
|
510
590
|
## API Reference
|
|
511
591
|
|
|
512
592
|
### Public API Endpoints
|
package/dist/server/index.js
CHANGED
|
@@ -77,6 +77,15 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
|
|
|
77
77
|
}
|
|
78
78
|
await strapi2.plugin("magic-editor-x").service("realtimeService").initSocketServer();
|
|
79
79
|
strapi2.log.info("[Magic Editor X] [SUCCESS] Realtime server started");
|
|
80
|
+
const pluginConfig = strapi2.config.get("plugin::magic-editor-x") || {};
|
|
81
|
+
const autoParseJSON = pluginConfig.api?.autoParseJSON !== false;
|
|
82
|
+
if (autoParseJSON) {
|
|
83
|
+
const parseMiddleware = strapi2.plugin("magic-editor-x").middleware("parse-editor-fields");
|
|
84
|
+
strapi2.server.use(parseMiddleware({}, { strapi: strapi2 }));
|
|
85
|
+
strapi2.log.info("[Magic Editor X] [SUCCESS] Auto-parse middleware registered (api.autoParseJSON: true)");
|
|
86
|
+
} else {
|
|
87
|
+
strapi2.log.info("[Magic Editor X] [INFO] Auto-parse middleware disabled (api.autoParseJSON: false)");
|
|
88
|
+
}
|
|
80
89
|
} catch (error) {
|
|
81
90
|
strapi2.log.error("[Magic Editor X] [ERROR] Bootstrap failed:", error);
|
|
82
91
|
}
|
|
@@ -143,6 +152,11 @@ var config$1 = {
|
|
|
143
152
|
allowedOrigins: [],
|
|
144
153
|
allowedAdminRoles: ["strapi-super-admin"],
|
|
145
154
|
allowedAdminUserIds: []
|
|
155
|
+
},
|
|
156
|
+
// API Response Settings
|
|
157
|
+
api: {
|
|
158
|
+
autoParseJSON: true
|
|
159
|
+
// Automatically parse Editor.js JSON strings to objects in API responses
|
|
146
160
|
}
|
|
147
161
|
},
|
|
148
162
|
validator: (config2) => {
|
|
@@ -923,7 +937,57 @@ var controllers$1 = {
|
|
|
923
937
|
collaboration,
|
|
924
938
|
license: license$1
|
|
925
939
|
};
|
|
926
|
-
var
|
|
940
|
+
var parseEditorFields$1 = (config2, { strapi: strapi2 }) => {
|
|
941
|
+
return async (ctx, next) => {
|
|
942
|
+
await next();
|
|
943
|
+
if (ctx.method !== "GET" || ctx.status !== 200) {
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
if (!ctx.body || typeof ctx.body !== "object") {
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
try {
|
|
950
|
+
const parseEditorFields2 = (data) => {
|
|
951
|
+
if (!data || typeof data !== "object") {
|
|
952
|
+
return data;
|
|
953
|
+
}
|
|
954
|
+
if (Array.isArray(data)) {
|
|
955
|
+
return data.map(parseEditorFields2);
|
|
956
|
+
}
|
|
957
|
+
const parsed = {};
|
|
958
|
+
for (const [key, value] of Object.entries(data)) {
|
|
959
|
+
if (typeof value === "string" && value.startsWith("{") && value.includes('"blocks"')) {
|
|
960
|
+
try {
|
|
961
|
+
const parsedValue = JSON.parse(value);
|
|
962
|
+
if (parsedValue.blocks && Array.isArray(parsedValue.blocks)) {
|
|
963
|
+
parsed[key] = parsedValue;
|
|
964
|
+
continue;
|
|
965
|
+
}
|
|
966
|
+
} catch (e) {
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
if (value !== null && typeof value === "object") {
|
|
970
|
+
parsed[key] = parseEditorFields2(value);
|
|
971
|
+
} else {
|
|
972
|
+
parsed[key] = value;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
return parsed;
|
|
976
|
+
};
|
|
977
|
+
if (ctx.body.data) {
|
|
978
|
+
ctx.body.data = parseEditorFields2(ctx.body.data);
|
|
979
|
+
} else {
|
|
980
|
+
ctx.body = parseEditorFields2(ctx.body);
|
|
981
|
+
}
|
|
982
|
+
} catch (error) {
|
|
983
|
+
strapi2.log.debug("[Magic Editor X] Failed to parse editor fields:", error.message);
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
};
|
|
987
|
+
const parseEditorFields = parseEditorFields$1;
|
|
988
|
+
var middlewares$1 = {
|
|
989
|
+
"parse-editor-fields": parseEditorFields
|
|
990
|
+
};
|
|
927
991
|
var policies$1 = {};
|
|
928
992
|
var admin$1 = {
|
|
929
993
|
type: "admin",
|
|
@@ -1931,7 +1995,7 @@ var snapshotService$1 = ({ strapi: strapi2 }) => ({
|
|
|
1931
1995
|
}
|
|
1932
1996
|
});
|
|
1933
1997
|
const name = "magic-editor-x";
|
|
1934
|
-
const version = "1.0
|
|
1998
|
+
const version = "1.1.0";
|
|
1935
1999
|
const description = "Advanced block-based editor for Strapi v5 with Editor.js, Media Library integration, and real-time collaboration support";
|
|
1936
2000
|
const keywords = [
|
|
1937
2001
|
"strapi",
|
package/dist/server/index.mjs
CHANGED
|
@@ -65,6 +65,15 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
|
|
|
65
65
|
}
|
|
66
66
|
await strapi2.plugin("magic-editor-x").service("realtimeService").initSocketServer();
|
|
67
67
|
strapi2.log.info("[Magic Editor X] [SUCCESS] Realtime server started");
|
|
68
|
+
const pluginConfig = strapi2.config.get("plugin::magic-editor-x") || {};
|
|
69
|
+
const autoParseJSON = pluginConfig.api?.autoParseJSON !== false;
|
|
70
|
+
if (autoParseJSON) {
|
|
71
|
+
const parseMiddleware = strapi2.plugin("magic-editor-x").middleware("parse-editor-fields");
|
|
72
|
+
strapi2.server.use(parseMiddleware({}, { strapi: strapi2 }));
|
|
73
|
+
strapi2.log.info("[Magic Editor X] [SUCCESS] Auto-parse middleware registered (api.autoParseJSON: true)");
|
|
74
|
+
} else {
|
|
75
|
+
strapi2.log.info("[Magic Editor X] [INFO] Auto-parse middleware disabled (api.autoParseJSON: false)");
|
|
76
|
+
}
|
|
68
77
|
} catch (error) {
|
|
69
78
|
strapi2.log.error("[Magic Editor X] [ERROR] Bootstrap failed:", error);
|
|
70
79
|
}
|
|
@@ -131,6 +140,11 @@ var config$1 = {
|
|
|
131
140
|
allowedOrigins: [],
|
|
132
141
|
allowedAdminRoles: ["strapi-super-admin"],
|
|
133
142
|
allowedAdminUserIds: []
|
|
143
|
+
},
|
|
144
|
+
// API Response Settings
|
|
145
|
+
api: {
|
|
146
|
+
autoParseJSON: true
|
|
147
|
+
// Automatically parse Editor.js JSON strings to objects in API responses
|
|
134
148
|
}
|
|
135
149
|
},
|
|
136
150
|
validator: (config2) => {
|
|
@@ -911,7 +925,57 @@ var controllers$1 = {
|
|
|
911
925
|
collaboration,
|
|
912
926
|
license: license$1
|
|
913
927
|
};
|
|
914
|
-
var
|
|
928
|
+
var parseEditorFields$1 = (config2, { strapi: strapi2 }) => {
|
|
929
|
+
return async (ctx, next) => {
|
|
930
|
+
await next();
|
|
931
|
+
if (ctx.method !== "GET" || ctx.status !== 200) {
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
if (!ctx.body || typeof ctx.body !== "object") {
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
try {
|
|
938
|
+
const parseEditorFields2 = (data) => {
|
|
939
|
+
if (!data || typeof data !== "object") {
|
|
940
|
+
return data;
|
|
941
|
+
}
|
|
942
|
+
if (Array.isArray(data)) {
|
|
943
|
+
return data.map(parseEditorFields2);
|
|
944
|
+
}
|
|
945
|
+
const parsed = {};
|
|
946
|
+
for (const [key, value] of Object.entries(data)) {
|
|
947
|
+
if (typeof value === "string" && value.startsWith("{") && value.includes('"blocks"')) {
|
|
948
|
+
try {
|
|
949
|
+
const parsedValue = JSON.parse(value);
|
|
950
|
+
if (parsedValue.blocks && Array.isArray(parsedValue.blocks)) {
|
|
951
|
+
parsed[key] = parsedValue;
|
|
952
|
+
continue;
|
|
953
|
+
}
|
|
954
|
+
} catch (e) {
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
if (value !== null && typeof value === "object") {
|
|
958
|
+
parsed[key] = parseEditorFields2(value);
|
|
959
|
+
} else {
|
|
960
|
+
parsed[key] = value;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
return parsed;
|
|
964
|
+
};
|
|
965
|
+
if (ctx.body.data) {
|
|
966
|
+
ctx.body.data = parseEditorFields2(ctx.body.data);
|
|
967
|
+
} else {
|
|
968
|
+
ctx.body = parseEditorFields2(ctx.body);
|
|
969
|
+
}
|
|
970
|
+
} catch (error) {
|
|
971
|
+
strapi2.log.debug("[Magic Editor X] Failed to parse editor fields:", error.message);
|
|
972
|
+
}
|
|
973
|
+
};
|
|
974
|
+
};
|
|
975
|
+
const parseEditorFields = parseEditorFields$1;
|
|
976
|
+
var middlewares$1 = {
|
|
977
|
+
"parse-editor-fields": parseEditorFields
|
|
978
|
+
};
|
|
915
979
|
var policies$1 = {};
|
|
916
980
|
var admin$1 = {
|
|
917
981
|
type: "admin",
|
|
@@ -1919,7 +1983,7 @@ var snapshotService$1 = ({ strapi: strapi2 }) => ({
|
|
|
1919
1983
|
}
|
|
1920
1984
|
});
|
|
1921
1985
|
const name = "magic-editor-x";
|
|
1922
|
-
const version = "1.0
|
|
1986
|
+
const version = "1.1.0";
|
|
1923
1987
|
const description = "Advanced block-based editor for Strapi v5 with Editor.js, Media Library integration, and real-time collaboration support";
|
|
1924
1988
|
const keywords = [
|
|
1925
1989
|
"strapi",
|
package/package.json
CHANGED