@savvycal/mjml-editor 0.7.0 → 0.9.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.
- package/dist/components/editor/InteractivePreview.d.ts.map +1 -1
- package/dist/components/editor/InteractivePreview.js +40 -38
- package/dist/components/editor/MjmlEditor.d.ts +13 -1
- package/dist/components/editor/MjmlEditor.d.ts.map +1 -1
- package/dist/components/editor/MjmlEditor.js +76 -72
- package/dist/components/editor/SourcePreview.d.ts.map +1 -1
- package/dist/components/editor/SourcePreview.js +23 -22
- package/dist/context/NonceContext.d.ts +9 -0
- package/dist/context/NonceContext.d.ts.map +1 -0
- package/dist/context/NonceContext.js +13 -0
- package/dist/context/RenderEndpointContext.d.ts +9 -0
- package/dist/context/RenderEndpointContext.d.ts.map +1 -0
- package/dist/context/RenderEndpointContext.js +21 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -4
- package/dist/lib/mjml/renderer.d.ts +8 -8
- package/dist/lib/mjml/renderer.d.ts.map +1 -1
- package/dist/lib/mjml/renderer.js +44 -51
- package/package.json +1 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InteractivePreview.d.ts","sourceRoot":"","sources":["../../../src/components/editor/InteractivePreview.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"InteractivePreview.d.ts","sourceRoot":"","sources":["../../../src/components/editor/InteractivePreview.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,UAAU,uBAAuB;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAID,wBAAgB,kBAAkB,CAAC,EACjC,UAAiB,EACjB,WAAuB,GACxB,EAAE,uBAAuB,2CAwLzB"}
|
|
@@ -1,37 +1,39 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { useRef as
|
|
3
|
-
import { useEditor as
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { jsxs as r, jsx as l } from "react/jsx-runtime";
|
|
2
|
+
import { useRef as y, useState as g, useEffect as a, useCallback as C } from "react";
|
|
3
|
+
import { useEditor as I } from "../../context/EditorContext.js";
|
|
4
|
+
import { useNonce as N } from "../../context/NonceContext.js";
|
|
5
|
+
import { useRenderEndpoint as L } from "../../context/RenderEndpointContext.js";
|
|
6
|
+
import { renderMjmlInteractive as D } from "../../lib/mjml/renderer.js";
|
|
7
|
+
const B = 375;
|
|
8
|
+
function W({
|
|
9
|
+
showHeader: x = !0,
|
|
10
|
+
previewMode: k = "desktop"
|
|
9
11
|
}) {
|
|
10
|
-
const { state:
|
|
12
|
+
const { state: n, selectBlock: m } = I(), i = N(), u = L(), o = y(null), [f, v] = g(n.document), [E, w] = g({
|
|
11
13
|
html: "",
|
|
12
14
|
errors: []
|
|
13
15
|
});
|
|
14
16
|
a(() => {
|
|
15
17
|
const e = setTimeout(() => {
|
|
16
|
-
|
|
18
|
+
v(n.document);
|
|
17
19
|
}, 300);
|
|
18
20
|
return () => clearTimeout(e);
|
|
19
|
-
}, [
|
|
21
|
+
}, [n.document]), a(() => {
|
|
20
22
|
let e = !1;
|
|
21
|
-
return
|
|
22
|
-
e ||
|
|
23
|
+
return D(f, u).then((t) => {
|
|
24
|
+
e || w(t);
|
|
23
25
|
}), () => {
|
|
24
26
|
e = !0;
|
|
25
27
|
};
|
|
26
|
-
}, [
|
|
27
|
-
const { html:
|
|
28
|
+
}, [f, u]);
|
|
29
|
+
const { html: b, errors: s } = E, d = C(
|
|
28
30
|
(e) => {
|
|
29
|
-
e.data?.type === "BLOCK_SELECTED" &&
|
|
31
|
+
e.data?.type === "BLOCK_SELECTED" && m(e.data.blockId);
|
|
30
32
|
},
|
|
31
|
-
[
|
|
33
|
+
[m]
|
|
32
34
|
);
|
|
33
|
-
a(() => (window.addEventListener("message",
|
|
34
|
-
const c =
|
|
35
|
+
a(() => (window.addEventListener("message", d), () => window.removeEventListener("message", d)), [d]);
|
|
36
|
+
const c = n.selectedBlockId ? `.block-${n.selectedBlockId} { outline: 2px solid #6366f1 !important; outline-offset: -2px; position: relative; }` : "", p = `
|
|
35
37
|
(function() {
|
|
36
38
|
document.addEventListener('click', function(e) {
|
|
37
39
|
e.preventDefault();
|
|
@@ -64,11 +66,11 @@ function S({
|
|
|
64
66
|
if (o.current) {
|
|
65
67
|
const e = o.current.contentDocument;
|
|
66
68
|
if (e) {
|
|
67
|
-
e.open(), e.write(
|
|
69
|
+
e.open(), e.write(b), e.close();
|
|
68
70
|
const t = e.createElement("script");
|
|
69
|
-
t.textContent =
|
|
70
|
-
const
|
|
71
|
-
|
|
71
|
+
i && (t.nonce = i), t.textContent = p, e.body.appendChild(t);
|
|
72
|
+
const h = e.createElement("style");
|
|
73
|
+
h.textContent = `
|
|
72
74
|
[class*="block-"] {
|
|
73
75
|
cursor: pointer;
|
|
74
76
|
transition: outline 0.15s ease;
|
|
@@ -78,10 +80,10 @@ function S({
|
|
|
78
80
|
outline-offset: -1px;
|
|
79
81
|
}
|
|
80
82
|
${c}
|
|
81
|
-
`, e.head.appendChild(
|
|
83
|
+
`, e.head.appendChild(h);
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
|
-
}, [
|
|
86
|
+
}, [b, c, p, i]), a(() => {
|
|
85
87
|
if (o.current) {
|
|
86
88
|
const e = o.current.contentDocument;
|
|
87
89
|
if (e) {
|
|
@@ -89,36 +91,36 @@ function S({
|
|
|
89
91
|
t || (t = e.createElement("style"), t.id = "selection-highlight", e.head.appendChild(t)), t.textContent = c;
|
|
90
92
|
}
|
|
91
93
|
}
|
|
92
|
-
}, [
|
|
93
|
-
|
|
94
|
-
/* @__PURE__ */
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
}, [n.selectedBlockId, c]), /* @__PURE__ */ r("div", { className: "flex flex-col h-full", children: [
|
|
95
|
+
x && /* @__PURE__ */ r("div", { className: "h-11 px-4 flex items-center justify-between border-b border-border bg-background", children: [
|
|
96
|
+
/* @__PURE__ */ l("span", { className: "text-sm font-semibold text-foreground", children: "Preview" }),
|
|
97
|
+
s.length > 0 && /* @__PURE__ */ r("span", { className: "text-xs font-medium text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/30 px-2 py-0.5 rounded-md", children: [
|
|
98
|
+
s.length,
|
|
97
99
|
" warning",
|
|
98
|
-
|
|
100
|
+
s.length !== 1 ? "s" : ""
|
|
99
101
|
] })
|
|
100
102
|
] }),
|
|
101
|
-
/* @__PURE__ */
|
|
103
|
+
/* @__PURE__ */ l("div", { className: "flex-1 overflow-auto bg-muted flex justify-center", children: /* @__PURE__ */ l(
|
|
102
104
|
"iframe",
|
|
103
105
|
{
|
|
104
106
|
ref: o,
|
|
105
107
|
title: "Email Preview",
|
|
106
108
|
className: "h-full border-0 bg-white transition-all duration-200",
|
|
107
109
|
style: {
|
|
108
|
-
width:
|
|
110
|
+
width: k === "mobile" ? B : "100%",
|
|
109
111
|
maxWidth: "100%"
|
|
110
112
|
},
|
|
111
113
|
sandbox: "allow-same-origin allow-scripts"
|
|
112
114
|
}
|
|
113
115
|
) }),
|
|
114
|
-
|
|
115
|
-
/* @__PURE__ */
|
|
116
|
-
/* @__PURE__ */
|
|
116
|
+
s.length > 0 && /* @__PURE__ */ r("div", { className: "max-h-28 overflow-auto border-t border-border bg-amber-50/50 dark:bg-amber-900/20 p-3", children: [
|
|
117
|
+
/* @__PURE__ */ l("div", { className: "text-xs font-semibold text-amber-700 dark:text-amber-300 mb-2", children: "Warnings" }),
|
|
118
|
+
/* @__PURE__ */ l("div", { className: "space-y-1", children: s.map((e, t) => /* @__PURE__ */ r(
|
|
117
119
|
"div",
|
|
118
120
|
{
|
|
119
121
|
className: "text-xs text-amber-600 dark:text-amber-400",
|
|
120
122
|
children: [
|
|
121
|
-
/* @__PURE__ */
|
|
123
|
+
/* @__PURE__ */ r("span", { className: "font-mono", children: [
|
|
122
124
|
"Line ",
|
|
123
125
|
e.line,
|
|
124
126
|
":"
|
|
@@ -133,5 +135,5 @@ function S({
|
|
|
133
135
|
] });
|
|
134
136
|
}
|
|
135
137
|
export {
|
|
136
|
-
|
|
138
|
+
W as InteractivePreview
|
|
137
139
|
};
|
|
@@ -3,6 +3,12 @@ import { LiquidSchema } from '../../types/liquid';
|
|
|
3
3
|
interface MjmlEditorProps {
|
|
4
4
|
value: string;
|
|
5
5
|
onChange: (mjml: string) => void;
|
|
6
|
+
/**
|
|
7
|
+
* URL to POST raw MJML content to for server-side rendering.
|
|
8
|
+
* The endpoint should accept a POST with `Content-Type: text/plain` body
|
|
9
|
+
* and return JSON: `{ html: string, errors: Array<{ line: number, message: string, tagName: string }> }`
|
|
10
|
+
*/
|
|
11
|
+
renderEndpoint: string;
|
|
6
12
|
className?: string;
|
|
7
13
|
defaultTheme?: 'light' | 'dark' | 'system';
|
|
8
14
|
liquidSchema?: LiquidSchema;
|
|
@@ -48,7 +54,13 @@ interface MjmlEditorProps {
|
|
|
48
54
|
* @default false
|
|
49
55
|
*/
|
|
50
56
|
defaultRightPanelOpen?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* CSP nonce to apply to dynamically injected script tags.
|
|
59
|
+
* Required when the host application uses a Content Security Policy
|
|
60
|
+
* with `script-src 'nonce-...'`.
|
|
61
|
+
*/
|
|
62
|
+
nonce?: string;
|
|
51
63
|
}
|
|
52
|
-
export declare function MjmlEditor({ value, onChange, className, defaultTheme, liquidSchema, extensions, applyThemeToDocument, showThemeToggle, defaultLeftPanelOpen, defaultRightPanelOpen, }: MjmlEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
64
|
+
export declare function MjmlEditor({ value, onChange, renderEndpoint, className, defaultTheme, liquidSchema, extensions, applyThemeToDocument, showThemeToggle, defaultLeftPanelOpen, defaultRightPanelOpen, nonce, }: MjmlEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
53
65
|
export {};
|
|
54
66
|
//# sourceMappingURL=MjmlEditor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MjmlEditor.d.ts","sourceRoot":"","sources":["../../../src/components/editor/MjmlEditor.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MjmlEditor.d.ts","sourceRoot":"","sources":["../../../src/components/editor/MjmlEditor.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAY,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAcnD,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC3C,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;;;;;;;OASG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAoKD,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,cAAc,EACd,SAAS,EACT,YAAuB,EACvB,YAAY,EACZ,UAAU,EACV,oBAA2B,EAC3B,eAAsB,EACtB,oBAA2B,EAC3B,qBAA6B,EAC7B,KAAK,GACN,EAAE,eAAe,2CAkDjB"}
|
|
@@ -1,97 +1,99 @@
|
|
|
1
1
|
import { jsx as e, jsxs as w, Fragment as L } from "react/jsx-runtime";
|
|
2
|
-
import { useState as a, useEffect as
|
|
2
|
+
import { useState as a, useEffect as s, useCallback as D, useRef as M } from "react";
|
|
3
3
|
import { EditorProvider as O, useEditor as j } from "../../context/EditorContext.js";
|
|
4
4
|
import { ThemeProvider as x, useTheme as C } from "../../context/ThemeContext.js";
|
|
5
|
-
import { LiquidSchemaProvider as
|
|
6
|
-
import { ExtensionsProvider as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
5
|
+
import { LiquidSchemaProvider as R } from "../../context/LiquidSchemaContext.js";
|
|
6
|
+
import { ExtensionsProvider as S } from "../../context/ExtensionsContext.js";
|
|
7
|
+
import { NonceProvider as K } from "../../context/NonceContext.js";
|
|
8
|
+
import { RenderEndpointProvider as N } from "../../context/RenderEndpointContext.js";
|
|
9
|
+
import { OutlineTree as A, GLOBAL_STYLES_ID as B } from "./OutlineTree.js";
|
|
10
|
+
import { EditorCanvas as F } from "./EditorCanvas.js";
|
|
11
|
+
import { BlockInspector as $ } from "./BlockInspector.js";
|
|
12
|
+
import { GlobalStylesPanel as z } from "./GlobalStylesPanel.js";
|
|
11
13
|
import { FloatingPanel as I } from "../ui/floating-panel.js";
|
|
12
|
-
import { createEmptyDocument as
|
|
13
|
-
function
|
|
14
|
+
import { createEmptyDocument as b, parseMjml as G, serializeMjml as H } from "../../lib/mjml/parser.js";
|
|
15
|
+
function _(n) {
|
|
14
16
|
if (!n || n.trim() === "")
|
|
15
|
-
return
|
|
17
|
+
return b();
|
|
16
18
|
try {
|
|
17
|
-
return
|
|
19
|
+
return G(n);
|
|
18
20
|
} catch (o) {
|
|
19
|
-
return console.error("Failed to parse MJML:", o),
|
|
21
|
+
return console.error("Failed to parse MJML:", o), b();
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
|
-
function
|
|
24
|
+
function q({
|
|
23
25
|
className: n,
|
|
24
26
|
children: o
|
|
25
27
|
}) {
|
|
26
|
-
const { resolvedTheme:
|
|
28
|
+
const { resolvedTheme: i } = C();
|
|
27
29
|
return /* @__PURE__ */ e(
|
|
28
30
|
"div",
|
|
29
31
|
{
|
|
30
|
-
className: `mjml-editor ${
|
|
32
|
+
className: `mjml-editor ${i} relative h-full w-full overflow-hidden bg-background text-foreground antialiased ${n || ""}`,
|
|
31
33
|
children: o
|
|
32
34
|
}
|
|
33
35
|
);
|
|
34
36
|
}
|
|
35
|
-
function
|
|
37
|
+
function J({
|
|
36
38
|
onChange: n,
|
|
37
39
|
showThemeToggle: o = !0,
|
|
38
|
-
defaultLeftPanelOpen:
|
|
39
|
-
defaultRightPanelOpen:
|
|
40
|
+
defaultLeftPanelOpen: i = !0,
|
|
41
|
+
defaultRightPanelOpen: m = !1
|
|
40
42
|
}) {
|
|
41
|
-
const { state: r, undo:
|
|
42
|
-
return
|
|
43
|
-
|
|
44
|
-
}, [n]),
|
|
45
|
-
r.selectedBlockId &&
|
|
46
|
-
}, [r.selectedBlockId]),
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
}, [r.document]),
|
|
50
|
-
const
|
|
43
|
+
const { state: r, undo: f, redo: u, canUndo: p, canRedo: h, deleteBlock: g, selectBlock: v } = j(), [d, k] = a(i), [c, l] = a(m), [T, y] = a("edit"), P = M(n);
|
|
44
|
+
return s(() => {
|
|
45
|
+
P.current = n;
|
|
46
|
+
}, [n]), s(() => {
|
|
47
|
+
r.selectedBlockId && l(!0);
|
|
48
|
+
}, [r.selectedBlockId]), s(() => {
|
|
49
|
+
const E = H(r.document);
|
|
50
|
+
P.current(E);
|
|
51
|
+
}, [r.document]), s(() => {
|
|
52
|
+
const E = (t) => {
|
|
51
53
|
if (!(t.target instanceof HTMLInputElement || t.target instanceof HTMLTextAreaElement || t.target?.isContentEditable)) {
|
|
52
54
|
if ((t.metaKey || t.ctrlKey) && t.key === "z") {
|
|
53
|
-
t.preventDefault(), t.shiftKey ?
|
|
55
|
+
t.preventDefault(), t.shiftKey ? h && u() : p && f();
|
|
54
56
|
return;
|
|
55
57
|
}
|
|
56
58
|
if ((t.key === "Delete" || t.key === "Backspace") && r.selectedBlockId && r.selectedBlockId !== B) {
|
|
57
|
-
t.preventDefault(),
|
|
59
|
+
t.preventDefault(), g(r.selectedBlockId);
|
|
58
60
|
return;
|
|
59
61
|
}
|
|
60
62
|
if (t.key === "Escape" && r.selectedBlockId) {
|
|
61
|
-
t.preventDefault(),
|
|
63
|
+
t.preventDefault(), v(null);
|
|
62
64
|
return;
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
67
|
};
|
|
66
|
-
return window.addEventListener("keydown",
|
|
68
|
+
return window.addEventListener("keydown", E), () => window.removeEventListener("keydown", E);
|
|
67
69
|
}, [
|
|
68
|
-
u,
|
|
69
70
|
f,
|
|
70
|
-
|
|
71
|
+
u,
|
|
71
72
|
p,
|
|
72
73
|
h,
|
|
73
74
|
g,
|
|
75
|
+
v,
|
|
74
76
|
r.selectedBlockId
|
|
75
77
|
]), /* @__PURE__ */ w("div", { className: "relative h-full overflow-hidden", children: [
|
|
76
78
|
/* @__PURE__ */ e("div", { className: "absolute inset-0 bg-canvas", children: /* @__PURE__ */ e(
|
|
77
|
-
|
|
79
|
+
F,
|
|
78
80
|
{
|
|
79
|
-
activeTab:
|
|
80
|
-
onTabChange:
|
|
81
|
-
leftPanelOpen:
|
|
81
|
+
activeTab: T,
|
|
82
|
+
onTabChange: y,
|
|
83
|
+
leftPanelOpen: d,
|
|
82
84
|
rightPanelOpen: c,
|
|
83
85
|
showThemeToggle: o
|
|
84
86
|
}
|
|
85
87
|
) }),
|
|
86
|
-
|
|
88
|
+
T === "edit" && /* @__PURE__ */ w(L, { children: [
|
|
87
89
|
/* @__PURE__ */ e(
|
|
88
90
|
I,
|
|
89
91
|
{
|
|
90
92
|
side: "left",
|
|
91
|
-
isOpen:
|
|
92
|
-
onToggle: () => k(!
|
|
93
|
+
isOpen: d,
|
|
94
|
+
onToggle: () => k(!d),
|
|
93
95
|
width: 256,
|
|
94
|
-
children: /* @__PURE__ */ e(
|
|
96
|
+
children: /* @__PURE__ */ e(A, { onTogglePanel: () => k(!1) })
|
|
95
97
|
}
|
|
96
98
|
),
|
|
97
99
|
/* @__PURE__ */ e(
|
|
@@ -99,58 +101,60 @@ function _({
|
|
|
99
101
|
{
|
|
100
102
|
side: "right",
|
|
101
103
|
isOpen: c,
|
|
102
|
-
onToggle: () =>
|
|
104
|
+
onToggle: () => l(!c),
|
|
103
105
|
width: 300,
|
|
104
106
|
children: r.selectedBlockId === B ? /* @__PURE__ */ e(
|
|
105
|
-
|
|
107
|
+
z,
|
|
106
108
|
{
|
|
107
|
-
onTogglePanel: () =>
|
|
109
|
+
onTogglePanel: () => l(!1)
|
|
108
110
|
}
|
|
109
|
-
) : /* @__PURE__ */ e(
|
|
111
|
+
) : /* @__PURE__ */ e($, { onTogglePanel: () => l(!1) })
|
|
110
112
|
}
|
|
111
113
|
)
|
|
112
114
|
] })
|
|
113
115
|
] });
|
|
114
116
|
}
|
|
115
|
-
function
|
|
117
|
+
function de({
|
|
116
118
|
value: n,
|
|
117
119
|
onChange: o,
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
renderEndpoint: i,
|
|
121
|
+
className: m,
|
|
122
|
+
defaultTheme: r = "system",
|
|
123
|
+
liquidSchema: f,
|
|
121
124
|
extensions: u,
|
|
122
|
-
applyThemeToDocument:
|
|
123
|
-
showThemeToggle:
|
|
124
|
-
defaultLeftPanelOpen:
|
|
125
|
-
defaultRightPanelOpen:
|
|
125
|
+
applyThemeToDocument: p = !0,
|
|
126
|
+
showThemeToggle: h = !0,
|
|
127
|
+
defaultLeftPanelOpen: g = !0,
|
|
128
|
+
defaultRightPanelOpen: v = !1,
|
|
129
|
+
nonce: d
|
|
126
130
|
}) {
|
|
127
|
-
const [
|
|
128
|
-
|
|
129
|
-
|
|
131
|
+
const [k, c] = a(!1);
|
|
132
|
+
s(() => {
|
|
133
|
+
c(!0);
|
|
130
134
|
}, []);
|
|
131
|
-
const [
|
|
132
|
-
(
|
|
133
|
-
o(
|
|
135
|
+
const [l] = a(() => _(n)), T = D(
|
|
136
|
+
(y) => {
|
|
137
|
+
o(y);
|
|
134
138
|
},
|
|
135
139
|
[o]
|
|
136
140
|
);
|
|
137
|
-
return
|
|
141
|
+
return k ? /* @__PURE__ */ e(
|
|
138
142
|
x,
|
|
139
143
|
{
|
|
140
|
-
defaultTheme:
|
|
141
|
-
applyToDocument:
|
|
142
|
-
children: /* @__PURE__ */ e(K, { extensions: u, children: /* @__PURE__ */ e(
|
|
143
|
-
|
|
144
|
+
defaultTheme: r,
|
|
145
|
+
applyToDocument: p,
|
|
146
|
+
children: /* @__PURE__ */ e(N, { renderEndpoint: i, children: /* @__PURE__ */ e(K, { nonce: d, children: /* @__PURE__ */ e(S, { extensions: u, children: /* @__PURE__ */ e(R, { schema: f, children: /* @__PURE__ */ e(q, { className: m, children: /* @__PURE__ */ e(O, { initialDocument: l, children: /* @__PURE__ */ e(
|
|
147
|
+
J,
|
|
144
148
|
{
|
|
145
|
-
onChange:
|
|
146
|
-
showThemeToggle:
|
|
147
|
-
defaultLeftPanelOpen:
|
|
148
|
-
defaultRightPanelOpen:
|
|
149
|
+
onChange: T,
|
|
150
|
+
showThemeToggle: h,
|
|
151
|
+
defaultLeftPanelOpen: g,
|
|
152
|
+
defaultRightPanelOpen: v
|
|
149
153
|
}
|
|
150
|
-
) }) }) }) })
|
|
154
|
+
) }) }) }) }) }) })
|
|
151
155
|
}
|
|
152
|
-
) : /* @__PURE__ */ e("div", { className: `h-full w-full bg-background ${
|
|
156
|
+
) : /* @__PURE__ */ e("div", { className: `h-full w-full bg-background ${m || ""}` });
|
|
153
157
|
}
|
|
154
158
|
export {
|
|
155
|
-
|
|
159
|
+
de as MjmlEditor
|
|
156
160
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SourcePreview.d.ts","sourceRoot":"","sources":["../../../src/components/editor/SourcePreview.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SourcePreview.d.ts","sourceRoot":"","sources":["../../../src/components/editor/SourcePreview.tsx"],"names":[],"mappings":"AAIA,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,aAAa,CAAC,EAC5B,UAAU,EACV,UAAgB,GACjB,EAAE,kBAAkB,2CAsFpB"}
|
|
@@ -1,38 +1,39 @@
|
|
|
1
1
|
import { jsxs as r, jsx as n } from "react/jsx-runtime";
|
|
2
|
-
import { useRef as
|
|
3
|
-
import { renderMjmlString as
|
|
4
|
-
|
|
2
|
+
import { useRef as h, useState as f, useEffect as i } from "react";
|
|
3
|
+
import { renderMjmlString as g } from "../../lib/mjml/renderer.js";
|
|
4
|
+
import { useRenderEndpoint as p } from "../../context/RenderEndpointContext.js";
|
|
5
|
+
function R({
|
|
5
6
|
mjmlSource: s,
|
|
6
|
-
debounceMs:
|
|
7
|
+
debounceMs: d = 300
|
|
7
8
|
}) {
|
|
8
|
-
const
|
|
9
|
+
const m = p(), o = h(null), [a, u] = f(s), [x, c] = f({
|
|
9
10
|
html: "",
|
|
10
11
|
errors: []
|
|
11
12
|
});
|
|
12
13
|
i(() => {
|
|
13
14
|
const e = setTimeout(() => {
|
|
14
|
-
|
|
15
|
-
},
|
|
15
|
+
u(s);
|
|
16
|
+
}, d);
|
|
16
17
|
return () => clearTimeout(e);
|
|
17
|
-
}, [s,
|
|
18
|
-
if (!
|
|
19
|
-
|
|
18
|
+
}, [s, d]), i(() => {
|
|
19
|
+
if (!a.trim()) {
|
|
20
|
+
c({ html: "", errors: [] });
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
22
23
|
let e = !1;
|
|
23
|
-
return
|
|
24
|
-
e ||
|
|
24
|
+
return g(a, m).then((l) => {
|
|
25
|
+
e || c(l);
|
|
25
26
|
}), () => {
|
|
26
27
|
e = !0;
|
|
27
28
|
};
|
|
28
|
-
}, [
|
|
29
|
-
const { html:
|
|
29
|
+
}, [a, m]);
|
|
30
|
+
const { html: b, errors: t } = x;
|
|
30
31
|
return i(() => {
|
|
31
|
-
if (
|
|
32
|
-
const e =
|
|
33
|
-
e && (e.open(), e.write(
|
|
32
|
+
if (o.current) {
|
|
33
|
+
const e = o.current.contentDocument;
|
|
34
|
+
e && (e.open(), e.write(b), e.close());
|
|
34
35
|
}
|
|
35
|
-
}, [
|
|
36
|
+
}, [b]), /* @__PURE__ */ r("div", { className: "flex flex-col h-full", children: [
|
|
36
37
|
/* @__PURE__ */ r("div", { className: "h-11 px-4 flex items-center justify-between border-b border-border bg-background", children: [
|
|
37
38
|
/* @__PURE__ */ n("span", { className: "text-sm font-semibold text-foreground", children: "Preview" }),
|
|
38
39
|
t.length > 0 && /* @__PURE__ */ r("span", { className: "text-xs font-medium text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/30 px-2 py-0.5 rounded-md", children: [
|
|
@@ -44,7 +45,7 @@ function w({
|
|
|
44
45
|
/* @__PURE__ */ n("div", { className: "flex-1 overflow-auto bg-muted", children: /* @__PURE__ */ n(
|
|
45
46
|
"iframe",
|
|
46
47
|
{
|
|
47
|
-
ref:
|
|
48
|
+
ref: o,
|
|
48
49
|
title: "Source Preview",
|
|
49
50
|
className: "w-full h-full border-0 bg-white",
|
|
50
51
|
sandbox: "allow-same-origin"
|
|
@@ -52,7 +53,7 @@ function w({
|
|
|
52
53
|
) }),
|
|
53
54
|
t.length > 0 && /* @__PURE__ */ r("div", { className: "max-h-28 overflow-auto border-t border-border bg-amber-50/50 dark:bg-amber-900/20 p-3", children: [
|
|
54
55
|
/* @__PURE__ */ n("div", { className: "text-xs font-semibold text-amber-700 dark:text-amber-300 mb-2", children: "Warnings" }),
|
|
55
|
-
/* @__PURE__ */ n("div", { className: "space-y-1", children: t.map((e,
|
|
56
|
+
/* @__PURE__ */ n("div", { className: "space-y-1", children: t.map((e, l) => /* @__PURE__ */ r(
|
|
56
57
|
"div",
|
|
57
58
|
{
|
|
58
59
|
className: "text-xs text-amber-600 dark:text-amber-400",
|
|
@@ -66,11 +67,11 @@ function w({
|
|
|
66
67
|
e.message
|
|
67
68
|
]
|
|
68
69
|
},
|
|
69
|
-
|
|
70
|
+
l
|
|
70
71
|
)) })
|
|
71
72
|
] })
|
|
72
73
|
] });
|
|
73
74
|
}
|
|
74
75
|
export {
|
|
75
|
-
|
|
76
|
+
R as SourcePreview
|
|
76
77
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
interface NonceProviderProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
nonce?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function NonceProvider({ children, nonce }: NonceProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare function useNonce(): string | undefined;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=NonceContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NonceContext.d.ts","sourceRoot":"","sources":["../../src/context/NonceContext.tsx"],"names":[],"mappings":"AACA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIlE,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,kBAAkB,2CAIpE;AAED,wBAAgB,QAAQ,uBAEvB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { useContext as n, createContext as c } from "react";
|
|
3
|
+
const o = c(void 0);
|
|
4
|
+
function x({ children: e, nonce: t }) {
|
|
5
|
+
return /* @__PURE__ */ r(o.Provider, { value: t, children: e });
|
|
6
|
+
}
|
|
7
|
+
function f() {
|
|
8
|
+
return n(o);
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
x as NonceProvider,
|
|
12
|
+
f as useNonce
|
|
13
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
interface RenderEndpointProviderProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
renderEndpoint: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function RenderEndpointProvider({ children, renderEndpoint, }: RenderEndpointProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare function useRenderEndpoint(): string;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=RenderEndpointContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RenderEndpointContext.d.ts","sourceRoot":"","sources":["../../src/context/RenderEndpointContext.tsx"],"names":[],"mappings":"AACA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIlE,UAAU,2BAA2B;IACnC,QAAQ,EAAE,SAAS,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,cAAc,GACf,EAAE,2BAA2B,2CAM7B;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAQ1C"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { useContext as t, createContext as d } from "react";
|
|
3
|
+
const e = d(void 0);
|
|
4
|
+
function u({
|
|
5
|
+
children: n,
|
|
6
|
+
renderEndpoint: o
|
|
7
|
+
}) {
|
|
8
|
+
return /* @__PURE__ */ r(e.Provider, { value: o, children: n });
|
|
9
|
+
}
|
|
10
|
+
function s() {
|
|
11
|
+
const n = t(e);
|
|
12
|
+
if (!n)
|
|
13
|
+
throw new Error(
|
|
14
|
+
"useRenderEndpoint must be used within MjmlEditor (no renderEndpoint provided)"
|
|
15
|
+
);
|
|
16
|
+
return n;
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
u as RenderEndpointProvider,
|
|
20
|
+
s as useRenderEndpoint
|
|
21
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { MjmlEditor } from './components/editor/MjmlEditor';
|
|
2
2
|
export { ThemeProvider, useTheme } from './context/ThemeContext';
|
|
3
3
|
export { ThemeToggle } from './components/ui/theme-toggle';
|
|
4
|
+
export { useNonce } from './context/NonceContext';
|
|
5
|
+
export { useRenderEndpoint } from './context/RenderEndpointContext';
|
|
4
6
|
export type { MjmlNode, MjmlTagName, ContentBlockType, EditorState, EditorAction, EditorExtensions, } from './types/mjml';
|
|
5
7
|
export type { LiquidSchema, LiquidSchemaItem } from './types/liquid';
|
|
6
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAG3D,YAAY,EACV,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAG3D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGlD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAGpE,YAAY,EACV,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { MjmlEditor as r } from "./components/editor/MjmlEditor.js";
|
|
2
|
-
import { ThemeProvider as t, useTheme as
|
|
3
|
-
import { ThemeToggle as
|
|
2
|
+
import { ThemeProvider as t, useTheme as p } from "./context/ThemeContext.js";
|
|
3
|
+
import { ThemeToggle as x } from "./components/ui/theme-toggle.js";
|
|
4
|
+
import { useNonce as n } from "./context/NonceContext.js";
|
|
5
|
+
import { useRenderEndpoint as h } from "./context/RenderEndpointContext.js";
|
|
4
6
|
export {
|
|
5
7
|
r as MjmlEditor,
|
|
6
8
|
t as ThemeProvider,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
x as ThemeToggle,
|
|
10
|
+
n as useNonce,
|
|
11
|
+
h as useRenderEndpoint,
|
|
12
|
+
p as useTheme
|
|
9
13
|
};
|
|
@@ -8,19 +8,19 @@ export interface RenderResult {
|
|
|
8
8
|
}[];
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
* Render MJML JSON to HTML.
|
|
12
|
-
* Custom attributes (like sc-if) are stripped to prevent
|
|
11
|
+
* Render MJML JSON to HTML via the render endpoint.
|
|
12
|
+
* Custom attributes (like sc-if) are stripped to prevent warnings.
|
|
13
13
|
*/
|
|
14
|
-
export declare function renderMjml(document: MjmlNode): Promise<RenderResult>;
|
|
14
|
+
export declare function renderMjml(document: MjmlNode, renderEndpoint: string): Promise<RenderResult>;
|
|
15
15
|
/**
|
|
16
|
-
* Render MJML string to HTML.
|
|
17
|
-
* Custom attributes (like sc-if) are stripped to prevent
|
|
16
|
+
* Render MJML string to HTML via the render endpoint.
|
|
17
|
+
* Custom attributes (like sc-if) are stripped to prevent warnings.
|
|
18
18
|
*/
|
|
19
|
-
export declare function renderMjmlString(mjmlString: string): Promise<RenderResult>;
|
|
19
|
+
export declare function renderMjmlString(mjmlString: string, renderEndpoint: string): Promise<RenderResult>;
|
|
20
20
|
/**
|
|
21
21
|
* Render MJML JSON to HTML with block IDs preserved as CSS classes.
|
|
22
22
|
* This allows clicking elements in the preview to identify the source block.
|
|
23
|
-
* Custom attributes (like sc-if) are stripped to prevent
|
|
23
|
+
* Custom attributes (like sc-if) are stripped to prevent warnings.
|
|
24
24
|
*/
|
|
25
|
-
export declare function renderMjmlInteractive(document: MjmlNode): Promise<RenderResult>;
|
|
25
|
+
export declare function renderMjmlInteractive(document: MjmlNode, renderEndpoint: string): Promise<RenderResult>;
|
|
26
26
|
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/lib/mjml/renderer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9D;
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/lib/mjml/renderer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9D;AAuHD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,YAAY,CAAC,CAYvB;AAkBD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,YAAY,CAAC,CAWvB;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,YAAY,CAAC,CAavB"}
|
|
@@ -1,73 +1,71 @@
|
|
|
1
1
|
import "uuid";
|
|
2
|
-
const
|
|
3
|
-
function
|
|
4
|
-
const
|
|
2
|
+
const p = ["sc-if"];
|
|
3
|
+
function u(t) {
|
|
4
|
+
const e = Object.fromEntries(
|
|
5
5
|
Object.entries(t.attributes || {}).filter(
|
|
6
|
-
([
|
|
6
|
+
([r]) => !p.includes(r)
|
|
7
7
|
)
|
|
8
8
|
);
|
|
9
9
|
return {
|
|
10
10
|
...t,
|
|
11
|
-
attributes:
|
|
12
|
-
children: t.children?.map(
|
|
11
|
+
attributes: e,
|
|
12
|
+
children: t.children?.map(u)
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
async function m(t, e) {
|
|
16
|
+
const r = await fetch(t, {
|
|
17
|
+
method: "POST",
|
|
18
|
+
headers: { "Content-Type": "text/plain" },
|
|
19
|
+
body: e
|
|
20
|
+
});
|
|
21
|
+
if (!r.ok)
|
|
22
|
+
throw new Error(`Render endpoint returned ${r.status}`);
|
|
23
|
+
return r.json();
|
|
18
24
|
}
|
|
19
|
-
function
|
|
25
|
+
function l(t) {
|
|
20
26
|
if (!t._id || !t.tagName.startsWith("mj-"))
|
|
21
27
|
return {
|
|
22
28
|
...t,
|
|
23
|
-
children: t.children?.map(
|
|
29
|
+
children: t.children?.map(l)
|
|
24
30
|
};
|
|
25
|
-
const
|
|
31
|
+
const e = t.attributes["mj-class"] || "", r = `block-${t._id}`, n = e ? `${e} ${r}` : r;
|
|
26
32
|
return {
|
|
27
33
|
...t,
|
|
28
|
-
attributes: { ...t.attributes, "mj-class":
|
|
29
|
-
children: t.children?.map(
|
|
34
|
+
attributes: { ...t.attributes, "mj-class": n },
|
|
35
|
+
children: t.children?.map(l)
|
|
30
36
|
};
|
|
31
37
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const e = " ".repeat(r), s = t.tagName, l = Object.entries(t.attributes || {}).filter(
|
|
37
|
-
([c, i]) => c !== "_id" && i !== "" && i !== void 0
|
|
38
|
-
).map(([c, i]) => `${c}="${f(i)}"`).join(" "), n = l ? `<${s} ${l}>` : `<${s}>`, a = `</${s}>`;
|
|
38
|
+
function g(t, e = 0) {
|
|
39
|
+
const r = " ".repeat(e), n = t.tagName, i = Object.entries(t.attributes || {}).filter(
|
|
40
|
+
([c, s]) => c !== "_id" && s !== "" && s !== void 0
|
|
41
|
+
).map(([c, s]) => `${c}="${d(s)}"`).join(" "), a = i ? `<${n} ${i}>` : `<${n}>`, o = `</${n}>`;
|
|
39
42
|
if (t.content !== void 0)
|
|
40
|
-
return `${
|
|
43
|
+
return `${r}${a}${t.content}${o}`;
|
|
41
44
|
if (t.children && t.children.length > 0) {
|
|
42
|
-
const c = t.children.map((
|
|
45
|
+
const c = t.children.map((s) => g(s, e + 1)).join(`
|
|
43
46
|
`);
|
|
44
|
-
return `${
|
|
47
|
+
return `${r}${a}
|
|
45
48
|
${c}
|
|
46
|
-
${
|
|
49
|
+
${r}${o}`;
|
|
47
50
|
}
|
|
48
|
-
return `${
|
|
51
|
+
return `${r}${a}${o}`;
|
|
49
52
|
}
|
|
50
|
-
function
|
|
53
|
+
function d(t) {
|
|
51
54
|
return t.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
52
55
|
}
|
|
53
|
-
function
|
|
54
|
-
for (const
|
|
55
|
-
const
|
|
56
|
-
t = t.replace(
|
|
57
|
-
const
|
|
58
|
-
t = t.replace(
|
|
56
|
+
function h(t) {
|
|
57
|
+
for (const e of p) {
|
|
58
|
+
const r = new RegExp(`\\s+${e}="[^"]*"`, "g");
|
|
59
|
+
t = t.replace(r, "");
|
|
60
|
+
const n = new RegExp(`\\s+${e}='[^']*'`, "g");
|
|
61
|
+
t = t.replace(n, "");
|
|
59
62
|
}
|
|
60
63
|
return t;
|
|
61
64
|
}
|
|
62
|
-
async function
|
|
65
|
+
async function f(t, e) {
|
|
63
66
|
try {
|
|
64
|
-
const r =
|
|
65
|
-
|
|
66
|
-
});
|
|
67
|
-
return {
|
|
68
|
-
html: s.html,
|
|
69
|
-
errors: s.errors || []
|
|
70
|
-
};
|
|
67
|
+
const r = h(t);
|
|
68
|
+
return await m(e, r);
|
|
71
69
|
} catch (r) {
|
|
72
70
|
return console.error("MJML render error:", r), {
|
|
73
71
|
html: '<p style="color: #dc2626; padding: 20px; background: white; margin: 0;">Error rendering email preview</p>',
|
|
@@ -75,15 +73,10 @@ async function b(t) {
|
|
|
75
73
|
};
|
|
76
74
|
}
|
|
77
75
|
}
|
|
78
|
-
async function
|
|
76
|
+
async function b(t, e) {
|
|
79
77
|
try {
|
|
80
|
-
const r =
|
|
81
|
-
|
|
82
|
-
});
|
|
83
|
-
return {
|
|
84
|
-
html: n.html,
|
|
85
|
-
errors: n.errors || []
|
|
86
|
-
};
|
|
78
|
+
const r = u(t), n = l(r), i = g(n);
|
|
79
|
+
return await m(e, i);
|
|
87
80
|
} catch (r) {
|
|
88
81
|
return console.error("MJML render error:", r), {
|
|
89
82
|
html: '<p style="color: #dc2626; padding: 20px; background: white; margin: 0;">Error rendering email preview</p>',
|
|
@@ -92,6 +85,6 @@ async function M(t) {
|
|
|
92
85
|
}
|
|
93
86
|
}
|
|
94
87
|
export {
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
b as renderMjmlInteractive,
|
|
89
|
+
f as renderMjmlString
|
|
97
90
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savvycal/mjml-editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -62,7 +62,6 @@
|
|
|
62
62
|
"class-variance-authority": "^0.7.1",
|
|
63
63
|
"clsx": "^2.1.1",
|
|
64
64
|
"lucide-react": "^0.562.0",
|
|
65
|
-
"mjml-browser": "^4.18.0",
|
|
66
65
|
"react-arborist": "^3.4.3",
|
|
67
66
|
"tailwind-merge": "^3.4.0",
|
|
68
67
|
"uuid": "^13.0.0"
|