@lit-pigeon/parser-mjml 0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lit Pigeon Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const C=require("htmlparser2"),g=require("@lit-pigeon/core");function I(t,n){const e={};for(const r of t)switch(r.tag){case"mj-preview":e.previewText=r.text;break;case"mj-attributes":for(const a of r.children)a.tag==="mj-all"&&a.attrs["font-family"]&&(e.fontFamily=a.attrs["font-family"]);break}return e}function u(t,n=0){if(!t)return{top:n,right:n,bottom:n,left:n};const e=t.trim().split(/\s+/).map(S);switch(e.length){case 1:return{top:e[0],right:e[0],bottom:e[0],left:e[0]};case 2:return{top:e[0],right:e[1],bottom:e[0],left:e[1]};case 3:return{top:e[0],right:e[1],bottom:e[2],left:e[1]};case 4:return{top:e[0],right:e[1],bottom:e[2],left:e[3]};default:return{top:n,right:n,bottom:n,left:n}}}function S(t){const n=parseFloat(t);return isNaN(n)?0:n}function o(t,n,e=""){return t[n]??e}function p(t,n,e=0){const r=t[n];if(r===void 0||r==="")return e;const a=parseFloat(r);return isNaN(a)?e:a}function A(t,n){return{id:g.generateId(),type:"text",values:{content:n,padding:u(o(t,"padding"),10),lineHeight:o(t,"line-height","1.5"),textAlign:o(t,"align","left")}}}function T(t){const n=o(t,"width"),e=n&&parseInt(n,10)||"auto";return{id:g.generateId(),type:"image",values:{src:o(t,"src"),alt:o(t,"alt"),width:e,href:o(t,"href")||void 0,padding:u(o(t,"padding"),10),alignment:o(t,"align","center"),borderRadius:p(t,"border-radius",0)}}}function B(t,n){const e=n.trim(),r=/^<p[\s>]/i.test(e)?e:`<p>${e}</p>`;return{id:g.generateId(),type:"button",values:{content:r,href:o(t,"href","#"),backgroundColor:o(t,"background-color","#3b82f6"),textColor:o(t,"color","#ffffff"),borderRadius:p(t,"border-radius",4),padding:u(o(t,"padding"),10),innerPadding:u(o(t,"inner-padding"),12),fontSize:p(t,"font-size",16),fontWeight:o(t,"font-weight","600"),alignment:o(t,"align","center"),fullWidth:o(t,"width")==="100%"}}}function N(t){return{id:g.generateId(),type:"divider",values:{borderColor:o(t,"border-color","#e2e8f0"),borderWidth:p(t,"border-width",1),borderStyle:o(t,"border-style","solid"),padding:u(o(t,"padding"),10),width:o(t,"width","100%")}}}function D(t){return{id:g.generateId(),type:"spacer",values:{height:p(t,"height",20)}}}const W=["facebook","twitter","instagram","linkedin","youtube","tiktok"];function $(t){const n=t.toLowerCase();for(const e of W)if(n.includes(e))return e;return"custom"}function F(t,n){const e=n.map(r=>{const c={type:$(o(r.attrs,"name","custom")),href:o(r.attrs,"href","#"),label:r.innerText.trim()||void 0},s=o(r.attrs,"src");return s&&(c.iconUrl=s),c});return{id:g.generateId(),type:"social",values:{icons:e,iconSize:p(t,"icon-size",32),spacing:p(t,"icon-padding",8),alignment:o(t,"align","center"),padding:u(o(t,"padding"),10)}}}function P(t){const n=t.match(/^<div\s+style="padding:\s*([^"]*)">([\s\S]*)<\/div>$/);return n?{id:g.generateId(),type:"html",values:{content:n[2],padding:u(n[1],0)}}:{id:g.generateId(),type:"html",values:{content:t,padding:u(void 0,0)}}}function z(t,n){const e=n.map(r=>{const a={href:o(r.attrs,"href","#"),text:r.innerText.trim()||"Link"},c=o(r.attrs,"color");c&&(a.color=c);const s=o(r.attrs,"font-weight");s&&(a.fontWeight=s);const i=o(r.attrs,"text-decoration");i&&(a.textDecoration=i);const d=o(r.attrs,"padding");return d&&(a.padding=d),a});return{id:g.generateId(),type:"navbar",values:{links:e,hamburger:o(t,"hamburger","hamburger"),alignment:o(t,"align","center"),padding:u(o(t,"padding"),10),linkColor:o(t,"ico-color","#000000"),linkFontSize:p(t,"font-size",14),linkPadding:o(t,"link-padding","10px 15px")}}}function w(t,n){const e=t.attrs,r=[];for(const a of t.children){const c=H(a,n);c&&r.push(c)}return{id:g.generateId(),type:"column",attributes:{backgroundColor:o(e,"background-color")||void 0,padding:u(o(e,"padding"),0),borderRadius:p(e,"border-radius",0)||void 0,verticalAlign:o(e,"vertical-align","top")},blocks:r}}function H(t,n){switch(t.tag){case"mj-text":return A(t.attrs,t.text);case"mj-image":return T(t.attrs);case"mj-button":return B(t.attrs,t.text);case"mj-divider":return N(t.attrs);case"mj-spacer":return D(t.attrs);case"mj-social":{const e=t.children.filter(r=>r.tag==="mj-social-element").map(r=>({attrs:r.attrs,innerText:r.text}));return F(t.attrs,e)}case"mj-raw":return P(t.text);case"mj-navbar":{const e=t.children.filter(r=>r.tag==="mj-navbar-link").map(r=>({attrs:r.attrs,innerText:r.text}));return z(t.attrs,e)}default:return n.push({message:`Unknown block element: ${t.tag}`,tag:t.tag}),null}}function v(t,n){const e=t.attrs,r=[];for(const i of t.children)if(i.tag==="mj-column")r.push(w(i,n));else if(i.tag==="mj-group")for(const d of i.children)d.tag==="mj-column"&&r.push(w(d,n));else n.push({message:`Unexpected section child: ${i.tag}`,tag:i.tag});r.length===0&&r.push({id:g.generateId(),type:"column",attributes:{padding:u(void 0,0),verticalAlign:"top"},blocks:[]});const a=R(r),s=o(e,"full-width")==="full-width";return{id:g.generateId(),type:"row",attributes:{backgroundColor:o(e,"background-color")||void 0,backgroundImage:o(e,"background-url")||void 0,padding:u(o(e,"padding"),0),fullWidth:s},columns:r,columnRatios:a,locked:!1}}function R(t,n){const e=t.length,r=Math.floor(12/e);return t.map(()=>r)}function O(t,n){return{id:g.generateId(),type:"hero",values:{backgroundUrl:o(t,"background-url"),backgroundPosition:o(t,"background-position","center center"),mode:o(t,"mode","fluid-height"),width:p(t,"width",600),height:p(t,"height",400),verticalAlign:o(t,"vertical-align","middle"),padding:u(o(t,"padding"),0),innerPadding:u(void 0,20),backgroundColor:o(t,"background-color","#ffffff"),content:n}}}function U(t,n){const e=p(t.attrs,"width",600),r=o(t.attrs,"background-color","#f4f4f5"),a=[];let c;const s=i=>(c&&(i.attributes.condition=c,c=void 0),i);for(const i of t.children)switch(i.tag){case"mj-raw":{const d=/\{\{#if\s+([^}]+?)\s*\}\}/.exec(i.text??"");d&&(c=d[1].trim());break}case"mj-section":a.push(s(v(i,n)));break;case"mj-hero":{const d=_(i),l=O(i.attrs,d),m={id:g.generateId(),type:"column",attributes:{padding:u(void 0,0),verticalAlign:"top"},blocks:[l]},f={id:g.generateId(),type:"row",attributes:{padding:u(void 0,0),fullWidth:!1},columns:[m],columnRatios:[12],locked:!1};a.push(s(f));break}case"mj-wrapper":for(const d of i.children)d.tag==="mj-section"&&a.push(s(v(d,n)));break;default:n.push({message:`Unknown body child element: ${i.tag}`,tag:i.tag});break}return{width:e,backgroundColor:r,rows:a}}function _(t){const n=[];for(const e of t.children)(e.tag==="mj-text"||e.tag==="mj-button")&&n.push(e.text);return n.join("")||"<p>Hero Content</p>"}function M(t){const n={tag:"root",attrs:{},children:[],text:""},e=[n],r=new Set(["mj-text","mj-button","mj-raw","mj-preview","mj-social-element","mj-navbar-link"]),a=new Set(["mj-image","mj-divider","mj-spacer","mj-all","mj-class","mj-font","mj-breakpoint"]);let c=null,s="",i=0;const d=new C.Parser({onopentag(l,m){if(c){const k=Object.entries(m).map(([x,y])=>`${x}="${y}"`).join(" ");s+=k?`<${l} ${k}>`:`<${l}>`,i++;return}const f={tag:l,attrs:m,children:[],text:""};e[e.length-1].children.push(f),!a.has(l)&&(e.push(f),r.has(l)&&(c={node:f,depth:0},s="",i=0))},ontext(l){if(c){s+=l;return}const m=e[e.length-1];m.text+=l},onclosetag(l){if(c){if(i>0){s+=`</${l}>`,i--;return}c.node.text=s,c=null,s="",i=0,e.length>1&&e[e.length-1].tag===l&&e.pop();return}a.has(l)||e.length>1&&e[e.length-1].tag===l&&e.pop()}},{recognizeSelfClosing:!0,lowerCaseTags:!0,lowerCaseAttributeNames:!0});return d.write(t),d.end(),n}function b(t,n){if(t.tag===n)return t;for(const e of t.children){const r=b(e,n);if(r)return r}}function E(t,n){const e=[],r=M(t),a=b(r,"mjml");if(!a)return e.push({message:"No <mjml> root element found"}),{document:j(),warnings:e};const c=b(a,"mj-head"),s=b(a,"mj-body");let i={};if(c&&(i=I(c.children.map(f=>({tag:f.tag,attrs:f.attrs,children:f.children.map(h=>({tag:h.tag,attrs:h.attrs,children:[],text:h.text})),text:f.text})))),!s)return e.push({message:"No <mj-body> element found"}),{document:j(),warnings:e};const d=U(s,e),l=new Date().toISOString();return{document:{version:"1.0",metadata:{name:"Imported Template",previewText:i.previewText,createdAt:l,updatedAt:l},body:{attributes:{width:d.width,backgroundColor:d.backgroundColor,fontFamily:i.fontFamily??"Arial, Helvetica, sans-serif",contentAlignment:"center"},rows:d.rows}},warnings:e}}function j(){const t=new Date().toISOString();return{version:"1.0",metadata:{name:"Imported Template",createdAt:t,updatedAt:t},body:{attributes:{width:600,backgroundColor:"#f4f4f5",fontFamily:"Arial, Helvetica, sans-serif",contentAlignment:"center"},rows:[]}}}exports.mjmlToDocument=E;
@@ -0,0 +1,28 @@
1
+ import { PigeonDocument } from '@lit-pigeon/core';
2
+
3
+ /**
4
+ * Converts an MJML string into a PigeonDocument.
5
+ *
6
+ * @param mjml - The MJML markup string to parse
7
+ * @param options - Optional parsing configuration
8
+ * @returns ParseResult containing the document and any warnings
9
+ */
10
+ export declare function mjmlToDocument(mjml: string, _options?: ParseOptions): ParseResult;
11
+
12
+ export declare interface ParseOptions {
13
+ /** If true, lenient parsing will skip unknown elements instead of warning. */
14
+ lenient?: boolean;
15
+ }
16
+
17
+ export declare interface ParseResult {
18
+ document: PigeonDocument;
19
+ warnings: ParseWarning[];
20
+ }
21
+
22
+ export declare interface ParseWarning {
23
+ message: string;
24
+ tag?: string;
25
+ line?: number;
26
+ }
27
+
28
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,482 @@
1
+ import { Parser as C } from "htmlparser2";
2
+ import { generateId as p } from "@lit-pigeon/core";
3
+ function S(t, n) {
4
+ const e = {};
5
+ for (const o of t)
6
+ switch (o.tag) {
7
+ case "mj-preview":
8
+ e.previewText = o.text;
9
+ break;
10
+ case "mj-attributes":
11
+ for (const a of o.children)
12
+ a.tag === "mj-all" && a.attrs["font-family"] && (e.fontFamily = a.attrs["font-family"]);
13
+ break;
14
+ }
15
+ return e;
16
+ }
17
+ function u(t, n = 0) {
18
+ if (!t)
19
+ return { top: n, right: n, bottom: n, left: n };
20
+ const e = t.trim().split(/\s+/).map(A);
21
+ switch (e.length) {
22
+ case 1:
23
+ return { top: e[0], right: e[0], bottom: e[0], left: e[0] };
24
+ case 2:
25
+ return { top: e[0], right: e[1], bottom: e[0], left: e[1] };
26
+ case 3:
27
+ return { top: e[0], right: e[1], bottom: e[2], left: e[1] };
28
+ case 4:
29
+ return { top: e[0], right: e[1], bottom: e[2], left: e[3] };
30
+ default:
31
+ return { top: n, right: n, bottom: n, left: n };
32
+ }
33
+ }
34
+ function A(t) {
35
+ const n = parseFloat(t);
36
+ return isNaN(n) ? 0 : n;
37
+ }
38
+ function r(t, n, e = "") {
39
+ return t[n] ?? e;
40
+ }
41
+ function f(t, n, e = 0) {
42
+ const o = t[n];
43
+ if (o === void 0 || o === "") return e;
44
+ const a = parseFloat(o);
45
+ return isNaN(a) ? e : a;
46
+ }
47
+ function T(t, n) {
48
+ return {
49
+ id: p(),
50
+ type: "text",
51
+ values: {
52
+ content: n,
53
+ padding: u(r(t, "padding"), 10),
54
+ lineHeight: r(t, "line-height", "1.5"),
55
+ textAlign: r(t, "align", "left")
56
+ }
57
+ };
58
+ }
59
+ function B(t) {
60
+ const n = r(t, "width"), e = n && parseInt(n, 10) || "auto";
61
+ return {
62
+ id: p(),
63
+ type: "image",
64
+ values: {
65
+ src: r(t, "src"),
66
+ alt: r(t, "alt"),
67
+ width: e,
68
+ href: r(t, "href") || void 0,
69
+ padding: u(r(t, "padding"), 10),
70
+ alignment: r(t, "align", "center"),
71
+ borderRadius: f(t, "border-radius", 0)
72
+ }
73
+ };
74
+ }
75
+ function N(t, n) {
76
+ const e = n.trim(), o = /^<p[\s>]/i.test(e) ? e : `<p>${e}</p>`;
77
+ return {
78
+ id: p(),
79
+ type: "button",
80
+ values: {
81
+ content: o,
82
+ href: r(t, "href", "#"),
83
+ backgroundColor: r(t, "background-color", "#3b82f6"),
84
+ textColor: r(t, "color", "#ffffff"),
85
+ borderRadius: f(t, "border-radius", 4),
86
+ padding: u(r(t, "padding"), 10),
87
+ innerPadding: u(r(t, "inner-padding"), 12),
88
+ fontSize: f(t, "font-size", 16),
89
+ fontWeight: r(t, "font-weight", "600"),
90
+ alignment: r(t, "align", "center"),
91
+ fullWidth: r(t, "width") === "100%"
92
+ }
93
+ };
94
+ }
95
+ function W(t) {
96
+ return {
97
+ id: p(),
98
+ type: "divider",
99
+ values: {
100
+ borderColor: r(t, "border-color", "#e2e8f0"),
101
+ borderWidth: f(t, "border-width", 1),
102
+ borderStyle: r(t, "border-style", "solid"),
103
+ padding: u(r(t, "padding"), 10),
104
+ width: r(t, "width", "100%")
105
+ }
106
+ };
107
+ }
108
+ function $(t) {
109
+ return {
110
+ id: p(),
111
+ type: "spacer",
112
+ values: {
113
+ height: f(t, "height", 20)
114
+ }
115
+ };
116
+ }
117
+ const D = ["facebook", "twitter", "instagram", "linkedin", "youtube", "tiktok"];
118
+ function F(t) {
119
+ const n = t.toLowerCase();
120
+ for (const e of D)
121
+ if (n.includes(e)) return e;
122
+ return "custom";
123
+ }
124
+ function I(t, n) {
125
+ const e = n.map((o) => {
126
+ const c = {
127
+ type: F(r(o.attrs, "name", "custom")),
128
+ href: r(o.attrs, "href", "#"),
129
+ label: o.innerText.trim() || void 0
130
+ }, s = r(o.attrs, "src");
131
+ return s && (c.iconUrl = s), c;
132
+ });
133
+ return {
134
+ id: p(),
135
+ type: "social",
136
+ values: {
137
+ icons: e,
138
+ iconSize: f(t, "icon-size", 32),
139
+ spacing: f(t, "icon-padding", 8),
140
+ alignment: r(t, "align", "center"),
141
+ padding: u(r(t, "padding"), 10)
142
+ }
143
+ };
144
+ }
145
+ function P(t) {
146
+ const n = t.match(/^<div\s+style="padding:\s*([^"]*)">([\s\S]*)<\/div>$/);
147
+ return n ? {
148
+ id: p(),
149
+ type: "html",
150
+ values: {
151
+ content: n[2],
152
+ padding: u(n[1], 0)
153
+ }
154
+ } : {
155
+ id: p(),
156
+ type: "html",
157
+ values: {
158
+ content: t,
159
+ padding: u(void 0, 0)
160
+ }
161
+ };
162
+ }
163
+ function z(t, n) {
164
+ const e = n.map((o) => {
165
+ const a = {
166
+ href: r(o.attrs, "href", "#"),
167
+ text: o.innerText.trim() || "Link"
168
+ }, c = r(o.attrs, "color");
169
+ c && (a.color = c);
170
+ const s = r(o.attrs, "font-weight");
171
+ s && (a.fontWeight = s);
172
+ const i = r(o.attrs, "text-decoration");
173
+ i && (a.textDecoration = i);
174
+ const d = r(o.attrs, "padding");
175
+ return d && (a.padding = d), a;
176
+ });
177
+ return {
178
+ id: p(),
179
+ type: "navbar",
180
+ values: {
181
+ links: e,
182
+ hamburger: r(t, "hamburger", "hamburger"),
183
+ alignment: r(t, "align", "center"),
184
+ padding: u(r(t, "padding"), 10),
185
+ linkColor: r(t, "ico-color", "#000000"),
186
+ linkFontSize: f(t, "font-size", 14),
187
+ linkPadding: r(t, "link-padding", "10px 15px")
188
+ }
189
+ };
190
+ }
191
+ function w(t, n) {
192
+ const e = t.attrs, o = [];
193
+ for (const a of t.children) {
194
+ const c = H(a, n);
195
+ c && o.push(c);
196
+ }
197
+ return {
198
+ id: p(),
199
+ type: "column",
200
+ attributes: {
201
+ backgroundColor: r(e, "background-color") || void 0,
202
+ padding: u(r(e, "padding"), 0),
203
+ borderRadius: f(e, "border-radius", 0) || void 0,
204
+ verticalAlign: r(e, "vertical-align", "top")
205
+ },
206
+ blocks: o
207
+ };
208
+ }
209
+ function H(t, n) {
210
+ switch (t.tag) {
211
+ case "mj-text":
212
+ return T(t.attrs, t.text);
213
+ case "mj-image":
214
+ return B(t.attrs);
215
+ case "mj-button":
216
+ return N(t.attrs, t.text);
217
+ case "mj-divider":
218
+ return W(t.attrs);
219
+ case "mj-spacer":
220
+ return $(t.attrs);
221
+ case "mj-social": {
222
+ const e = t.children.filter((o) => o.tag === "mj-social-element").map((o) => ({ attrs: o.attrs, innerText: o.text }));
223
+ return I(t.attrs, e);
224
+ }
225
+ case "mj-raw":
226
+ return P(t.text);
227
+ case "mj-navbar": {
228
+ const e = t.children.filter((o) => o.tag === "mj-navbar-link").map((o) => ({ attrs: o.attrs, innerText: o.text }));
229
+ return z(t.attrs, e);
230
+ }
231
+ default:
232
+ return n.push({
233
+ message: `Unknown block element: ${t.tag}`,
234
+ tag: t.tag
235
+ }), null;
236
+ }
237
+ }
238
+ function v(t, n) {
239
+ const e = t.attrs, o = [];
240
+ for (const i of t.children)
241
+ if (i.tag === "mj-column")
242
+ o.push(w(i, n));
243
+ else if (i.tag === "mj-group")
244
+ for (const d of i.children)
245
+ d.tag === "mj-column" && o.push(w(d, n));
246
+ else
247
+ n.push({
248
+ message: `Unexpected section child: ${i.tag}`,
249
+ tag: i.tag
250
+ });
251
+ o.length === 0 && o.push({
252
+ id: p(),
253
+ type: "column",
254
+ attributes: {
255
+ padding: u(void 0, 0),
256
+ verticalAlign: "top"
257
+ },
258
+ blocks: []
259
+ });
260
+ const a = R(o), s = r(e, "full-width") === "full-width";
261
+ return {
262
+ id: p(),
263
+ type: "row",
264
+ attributes: {
265
+ backgroundColor: r(e, "background-color") || void 0,
266
+ backgroundImage: r(e, "background-url") || void 0,
267
+ padding: u(r(e, "padding"), 0),
268
+ fullWidth: s
269
+ },
270
+ columns: o,
271
+ columnRatios: a,
272
+ locked: !1
273
+ };
274
+ }
275
+ function R(t, n) {
276
+ const e = t.length, o = Math.floor(12 / e);
277
+ return t.map(() => o);
278
+ }
279
+ function O(t, n) {
280
+ return {
281
+ id: p(),
282
+ type: "hero",
283
+ values: {
284
+ backgroundUrl: r(t, "background-url"),
285
+ backgroundPosition: r(t, "background-position", "center center"),
286
+ mode: r(t, "mode", "fluid-height"),
287
+ width: f(t, "width", 600),
288
+ height: f(t, "height", 400),
289
+ verticalAlign: r(t, "vertical-align", "middle"),
290
+ padding: u(r(t, "padding"), 0),
291
+ innerPadding: u(void 0, 20),
292
+ backgroundColor: r(t, "background-color", "#ffffff"),
293
+ content: n
294
+ }
295
+ };
296
+ }
297
+ function U(t, n) {
298
+ const e = f(t.attrs, "width", 600), o = r(t.attrs, "background-color", "#f4f4f5"), a = [];
299
+ let c;
300
+ const s = (i) => (c && (i.attributes.condition = c, c = void 0), i);
301
+ for (const i of t.children)
302
+ switch (i.tag) {
303
+ case "mj-raw": {
304
+ const d = /\{\{#if\s+([^}]+?)\s*\}\}/.exec(i.text ?? "");
305
+ d && (c = d[1].trim());
306
+ break;
307
+ }
308
+ case "mj-section":
309
+ a.push(s(v(i, n)));
310
+ break;
311
+ case "mj-hero": {
312
+ const d = _(i), l = O(i.attrs, d), m = {
313
+ id: p(),
314
+ type: "column",
315
+ attributes: {
316
+ padding: u(void 0, 0),
317
+ verticalAlign: "top"
318
+ },
319
+ blocks: [l]
320
+ }, g = {
321
+ id: p(),
322
+ type: "row",
323
+ attributes: {
324
+ padding: u(void 0, 0),
325
+ fullWidth: !1
326
+ },
327
+ columns: [m],
328
+ columnRatios: [12],
329
+ locked: !1
330
+ };
331
+ a.push(s(g));
332
+ break;
333
+ }
334
+ case "mj-wrapper":
335
+ for (const d of i.children)
336
+ d.tag === "mj-section" && a.push(s(v(d, n)));
337
+ break;
338
+ default:
339
+ n.push({
340
+ message: `Unknown body child element: ${i.tag}`,
341
+ tag: i.tag
342
+ });
343
+ break;
344
+ }
345
+ return { width: e, backgroundColor: o, rows: a };
346
+ }
347
+ function _(t) {
348
+ const n = [];
349
+ for (const e of t.children)
350
+ (e.tag === "mj-text" || e.tag === "mj-button") && n.push(e.text);
351
+ return n.join("") || "<p>Hero Content</p>";
352
+ }
353
+ function E(t) {
354
+ const n = { tag: "root", attrs: {}, children: [], text: "" }, e = [n], o = /* @__PURE__ */ new Set([
355
+ "mj-text",
356
+ "mj-button",
357
+ "mj-raw",
358
+ "mj-preview",
359
+ "mj-social-element",
360
+ "mj-navbar-link"
361
+ ]), a = /* @__PURE__ */ new Set([
362
+ "mj-image",
363
+ "mj-divider",
364
+ "mj-spacer",
365
+ "mj-all",
366
+ "mj-class",
367
+ "mj-font",
368
+ "mj-breakpoint"
369
+ ]);
370
+ let c = null, s = "", i = 0;
371
+ const d = new C({
372
+ onopentag(l, m) {
373
+ if (c) {
374
+ const k = Object.entries(m).map(([x, y]) => `${x}="${y}"`).join(" ");
375
+ s += k ? `<${l} ${k}>` : `<${l}>`, i++;
376
+ return;
377
+ }
378
+ const g = { tag: l, attrs: m, children: [], text: "" };
379
+ e[e.length - 1].children.push(g), !a.has(l) && (e.push(g), o.has(l) && (c = { node: g, depth: 0 }, s = "", i = 0));
380
+ },
381
+ ontext(l) {
382
+ if (c) {
383
+ s += l;
384
+ return;
385
+ }
386
+ const m = e[e.length - 1];
387
+ m.text += l;
388
+ },
389
+ onclosetag(l) {
390
+ if (c) {
391
+ if (i > 0) {
392
+ s += `</${l}>`, i--;
393
+ return;
394
+ }
395
+ c.node.text = s, c = null, s = "", i = 0, e.length > 1 && e[e.length - 1].tag === l && e.pop();
396
+ return;
397
+ }
398
+ a.has(l) || e.length > 1 && e[e.length - 1].tag === l && e.pop();
399
+ }
400
+ }, {
401
+ recognizeSelfClosing: !0,
402
+ lowerCaseTags: !0,
403
+ lowerCaseAttributeNames: !0
404
+ });
405
+ return d.write(t), d.end(), n;
406
+ }
407
+ function b(t, n) {
408
+ if (t.tag === n) return t;
409
+ for (const e of t.children) {
410
+ const o = b(e, n);
411
+ if (o) return o;
412
+ }
413
+ }
414
+ function K(t, n) {
415
+ const e = [], o = E(t), a = b(o, "mjml");
416
+ if (!a)
417
+ return e.push({ message: "No <mjml> root element found" }), {
418
+ document: j(),
419
+ warnings: e
420
+ };
421
+ const c = b(a, "mj-head"), s = b(a, "mj-body");
422
+ let i = {};
423
+ if (c && (i = S(
424
+ c.children.map((g) => ({
425
+ tag: g.tag,
426
+ attrs: g.attrs,
427
+ children: g.children.map((h) => ({
428
+ tag: h.tag,
429
+ attrs: h.attrs,
430
+ children: [],
431
+ text: h.text
432
+ })),
433
+ text: g.text
434
+ }))
435
+ )), !s)
436
+ return e.push({ message: "No <mj-body> element found" }), {
437
+ document: j(),
438
+ warnings: e
439
+ };
440
+ const d = U(s, e), l = (/* @__PURE__ */ new Date()).toISOString();
441
+ return { document: {
442
+ version: "1.0",
443
+ metadata: {
444
+ name: "Imported Template",
445
+ previewText: i.previewText,
446
+ createdAt: l,
447
+ updatedAt: l
448
+ },
449
+ body: {
450
+ attributes: {
451
+ width: d.width,
452
+ backgroundColor: d.backgroundColor,
453
+ fontFamily: i.fontFamily ?? "Arial, Helvetica, sans-serif",
454
+ contentAlignment: "center"
455
+ },
456
+ rows: d.rows
457
+ }
458
+ }, warnings: e };
459
+ }
460
+ function j() {
461
+ const t = (/* @__PURE__ */ new Date()).toISOString();
462
+ return {
463
+ version: "1.0",
464
+ metadata: {
465
+ name: "Imported Template",
466
+ createdAt: t,
467
+ updatedAt: t
468
+ },
469
+ body: {
470
+ attributes: {
471
+ width: 600,
472
+ backgroundColor: "#f4f4f5",
473
+ fontFamily: "Arial, Helvetica, sans-serif",
474
+ contentAlignment: "center"
475
+ },
476
+ rows: []
477
+ }
478
+ };
479
+ }
480
+ export {
481
+ K as mjmlToDocument
482
+ };
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@lit-pigeon/parser-mjml",
3
+ "version": "0.1.1",
4
+ "description": "MJML-to-PigeonDocument parser for Pigeon email editor",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "dependencies": {
20
+ "htmlparser2": "^9.1.0",
21
+ "@lit-pigeon/core": "^0.1.1"
22
+ },
23
+ "devDependencies": {
24
+ "typescript": "^5.5.0",
25
+ "vite": "^5.4.0",
26
+ "vite-plugin-dts": "^4.0.0",
27
+ "vitest": "^2.0.0"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/snxstudio/lit-pigeon.git",
35
+ "directory": "packages/parser-mjml"
36
+ },
37
+ "license": "MIT",
38
+ "scripts": {
39
+ "build": "vite build",
40
+ "dev": "vite build --watch",
41
+ "test": "vitest run",
42
+ "test:watch": "vitest",
43
+ "clean": "rm -rf dist"
44
+ }
45
+ }