@emabuild/email-renderer 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,5 @@
1
- function wrapInDocumentShell(bodyHtml, cssBlock, bodyValues) {
2
- const bgColor = bodyValues.backgroundColor || "#e7e7e7";
3
- const contentWidth = bodyValues.contentWidth || "600px";
4
- const fontFamily = bodyValues.fontFamily?.value || "arial,helvetica,sans-serif";
5
- const textColor = bodyValues.textColor || "#000000";
6
- const preheaderText = bodyValues.preheaderText || "";
7
- const preheader = preheaderText ? `<div style="display:none;font-size:1px;color:${bgColor};line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">${preheaderText}${"&zwnj;&nbsp;".repeat(80)}</div>` : "";
1
+ function k(t, a, n) {
2
+ const e = n.backgroundColor || "#e7e7e7", d = n.contentWidth || "600px", i = n.fontFamily?.value || "arial,helvetica,sans-serif", s = n.textColor || "#000000", o = n.preheaderText || "", c = o ? `<div style="display:none;font-size:1px;color:${e};line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;">${o}${"&zwnj;&nbsp;".repeat(80)}</div>` : "";
8
3
  return `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
9
4
  <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
10
5
  <head>
@@ -23,12 +18,12 @@ function wrapInDocumentShell(bodyHtml, cssBlock, bodyValues) {
23
18
  </o:OfficeDocumentSettings>
24
19
  </xml></noscript>
25
20
  <style type="text/css">
26
- table, td, th { font-family: ${fontFamily} !important; }
21
+ table, td, th { font-family: ${i} !important; }
27
22
  </style>
28
23
  <![endif]-->
29
24
  <!--[if !mso]><!-->
30
25
  <style type="text/css">
31
- ${cssBlock}
26
+ ${a}
32
27
  </style>
33
28
  <!--<![endif]-->
34
29
  <style type="text/css">
@@ -40,14 +35,14 @@ function wrapInDocumentShell(bodyHtml, cssBlock, bodyValues) {
40
35
  a[x-apple-data-detectors='true'] { color: inherit !important; text-decoration: none !important; }
41
36
  </style>
42
37
  </head>
43
- <body class="clean-body u_body" style="margin:0;padding:0;-webkit-text-size-adjust:100%;background-color:${bgColor};color:${textColor};">
44
- ${preheader}
45
- <table id="u_body" style="border-collapse:collapse;table-layout:fixed;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;vertical-align:top;min-width:320px;margin:0 auto;background-color:${bgColor};width:100%;" cellpadding="0" cellspacing="0" border="0">
38
+ <body class="clean-body u_body" style="margin:0;padding:0;-webkit-text-size-adjust:100%;background-color:${e};color:${s};">
39
+ ${c}
40
+ <table id="u_body" style="border-collapse:collapse;table-layout:fixed;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;vertical-align:top;min-width:320px;margin:0 auto;background-color:${e};width:100%;" cellpadding="0" cellspacing="0" border="0">
46
41
  <tbody>
47
42
  <tr style="vertical-align:top;">
48
43
  <td style="word-break:break-word;border-collapse:collapse !important;vertical-align:top;">
49
- <!--[if (mso)|(IE)]><table width="${parseInt(contentWidth)}" align="center" cellpadding="0" cellspacing="0" border="0"><tr><td><![endif]-->
50
- ${bodyHtml}
44
+ <!--[if (mso)|(IE)]><table width="${parseInt(d)}" align="center" cellpadding="0" cellspacing="0" border="0"><tr><td><![endif]-->
45
+ ${t}
51
46
  <!--[if (mso)|(IE)]></td></tr></table><![endif]-->
52
47
  </td>
53
48
  </tr>
@@ -56,79 +51,68 @@ function wrapInDocumentShell(bodyHtml, cssBlock, bodyValues) {
56
51
  </body>
57
52
  </html>`;
58
53
  }
59
- function renderRow(row, bodyValues, toolRenderers) {
60
- const contentWidth = parseInt(bodyValues.contentWidth || "600");
61
- const bgColor = row.values.backgroundColor || "";
62
- const colsBgColor = row.values.columnsBackgroundColor || "";
63
- const padding = row.values.padding || "0px";
64
- const totalCells = row.cells.reduce((a, b) => a + b, 0);
65
- const bgStyle = bgColor ? `background-color:${bgColor};` : "";
66
- const bgImage = row.values.backgroundImage?.url ? `background-image:url('${row.values.backgroundImage.url}');background-repeat:${row.values.backgroundImage.repeat ? "repeat" : "no-repeat"};background-position:center top;background-size:${row.values.backgroundImage.cover ? "cover" : "auto"};` : "";
67
- const columnsHtml = row.columns.map((col, i) => {
68
- const colWidthPx = Math.round(row.cells[i] / totalCells * contentWidth);
69
- return renderColumn(col, colWidthPx, colsBgColor, bodyValues, toolRenderers);
70
- });
71
- const needsGhostTable = row.columns.length > 1;
72
- let innerHtml;
73
- if (needsGhostTable) {
74
- const ghostCols = row.columns.map((col, i) => {
75
- const colWidthPx = Math.round(row.cells[i] / totalCells * contentWidth);
76
- const colHtml = renderColumn(col, colWidthPx, colsBgColor, bodyValues, toolRenderers);
77
- return `<!--[if (mso)|(IE)]><td align="center" width="${colWidthPx}" style="width:${colWidthPx}px;padding:0px;border:none;" valign="top"><![endif]-->
78
- ${colHtml}
54
+ function w(t, a, n) {
55
+ const e = parseInt(a.contentWidth || "600"), d = t.values.backgroundColor || "", i = t.values.columnsBackgroundColor || "", s = t.values.padding || "0px", o = t.cells.reduce((u, h) => u + h, 0), c = d ? `background-color:${d};` : "", m = t.values.backgroundImage?.url ? `background-image:url('${t.values.backgroundImage.url}');background-repeat:${t.values.backgroundImage.repeat ? "repeat" : "no-repeat"};background-position:center top;background-size:${t.values.backgroundImage.cover ? "cover" : "auto"};` : "", r = t.columns.map((u, h) => {
56
+ const b = Math.round(t.cells[h] / o * e);
57
+ return y(u, b, i, a, n);
58
+ }), l = t.columns.length > 1;
59
+ let p;
60
+ if (l) {
61
+ const u = t.columns.map((h, b) => {
62
+ const g = Math.round(t.cells[b] / o * e), v = y(h, g, i, a, n);
63
+ return `<!--[if (mso)|(IE)]><td align="center" width="${g}" style="width:${g}px;padding:0px;border:none;" valign="top"><![endif]-->
64
+ ${v}
79
65
  <!--[if (mso)|(IE)]></td><![endif]-->`;
80
66
  });
81
- innerHtml = `<!--[if (mso)|(IE)]><table role="presentation" width="${contentWidth}" cellpadding="0" cellspacing="0" border="0"><tr>${ghostCols.join("\n")}</tr></table><![endif]-->
67
+ p = `<!--[if (mso)|(IE)]><table role="presentation" width="${e}" cellpadding="0" cellspacing="0" border="0"><tr>${u.join(`
68
+ `)}</tr></table><![endif]-->
82
69
 
83
70
  <!--[if !mso]><!-->
84
- <div style="max-width:${contentWidth}px;margin:0 auto;">
85
- ${columnsHtml.join("\n")}
71
+ <div style="max-width:${e}px;margin:0 auto;">
72
+ ${r.join(`
73
+ `)}
86
74
  </div>
87
75
  <!--<![endif]-->`;
88
- } else {
89
- innerHtml = columnsHtml.join("\n");
90
- }
91
- const hideDesktop = row.values.hideDesktop ? " u_hide_desktop" : "";
92
- const hideMobile = row.values.hideMobile ? " u_hide_mobile" : "";
93
- return `<div class="u_row${hideDesktop}${hideMobile}" style="padding:${padding};${bgStyle}${bgImage}">
94
- <div style="margin:0 auto;min-width:320px;max-width:${contentWidth}px;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;background-color:transparent;">
76
+ } else
77
+ p = r.join(`
78
+ `);
79
+ const x = t.values.hideDesktop ? " u_hide_desktop" : "", f = t.values.hideMobile ? " u_hide_mobile" : "";
80
+ return `<div class="u_row${x}${f}" style="padding:${s};${c}${m}">
81
+ <div style="margin:0 auto;min-width:320px;max-width:${e}px;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;background-color:transparent;">
95
82
  <div style="border-collapse:collapse;display:table;width:100%;height:100%;background-color:transparent;">
96
- ${innerHtml}
83
+ ${p}
97
84
  </div>
98
85
  </div>
99
86
  </div>`;
100
87
  }
101
- function renderColumn(col, widthPx, colsBgColor, bodyValues, toolRenderers) {
102
- const bgColor = col.values.backgroundColor || colsBgColor || "";
103
- const padding = col.values.padding || "0px";
104
- const borderRadius = col.values.borderRadius || "0px";
105
- const bgStyle = bgColor ? `background-color:${bgColor};` : "";
106
- const contentsHtml = col.contents.map((content) => {
107
- const renderer = toolRenderers.get(content.type);
108
- if (!renderer) return `<!-- unknown tool: ${content.type} -->`;
109
- const ctx = {
110
- columnWidth: widthPx,
88
+ function y(t, a, n, e, d) {
89
+ const i = t.values.backgroundColor || n || "", s = t.values.padding || "0px", o = t.values.borderRadius || "0px", c = i ? `background-color:${i};` : "", m = t.contents.map((r) => {
90
+ const l = d.get(r.type);
91
+ if (!l) return `<!-- unknown tool: ${r.type} -->`;
92
+ const p = {
93
+ columnWidth: a,
111
94
  displayMode: "email",
112
- contentWidth: parseInt(bodyValues.contentWidth || "600"),
113
- bodyValues
95
+ contentWidth: parseInt(e.contentWidth || "600"),
96
+ bodyValues: e
114
97
  };
115
- return renderer(content.values, ctx);
116
- }).join("\n");
117
- return `<div class="u_column" style="max-width:${widthPx}px;min-width:${Math.min(widthPx, 320)}px;display:table-cell;vertical-align:top;">
118
- <div style="height:100%;width:100% !important;border-radius:${borderRadius};-webkit-border-radius:${borderRadius};${bgStyle}">
119
- <div style="box-sizing:border-box;height:100%;padding:${padding};border:none;border-radius:${borderRadius};-webkit-border-radius:${borderRadius};">
120
- ${contentsHtml || '<!--[if (!mso)&(!IE)]><!--><div style="height:0;min-height:1px;font-size:0;">&nbsp;</div><!--<![endif]-->'}
98
+ return l(r.values, p);
99
+ }).join(`
100
+ `);
101
+ return `<div class="u_column" style="max-width:${a}px;min-width:${Math.min(a, 320)}px;display:table-cell;vertical-align:top;">
102
+ <div style="height:100%;width:100% !important;border-radius:${o};-webkit-border-radius:${o};${c}">
103
+ <div style="box-sizing:border-box;height:100%;padding:${s};border:none;border-radius:${o};-webkit-border-radius:${o};">
104
+ ${m || '<!--[if (!mso)&(!IE)]><!--><div style="height:0;min-height:1px;font-size:0;">&nbsp;</div><!--<![endif]-->'}
121
105
  </div>
122
106
  </div>
123
107
  </div>`;
124
108
  }
125
- function getResponsiveCss(contentWidth) {
109
+ function $(t) {
126
110
  return `
127
- @media only screen and (min-width: ${contentWidth + 20}px) {
111
+ @media only screen and (min-width: ${t + 20}px) {
128
112
  .u_row .u_column { display: table-cell; }
129
113
  }
130
114
 
131
- @media only screen and (max-width: ${contentWidth + 20}px) {
115
+ @media only screen and (max-width: ${t + 20}px) {
132
116
  .u_row .u_column {
133
117
  display: block !important;
134
118
  width: 100% !important;
@@ -162,48 +146,40 @@ function getResponsiveCss(contentWidth) {
162
146
  .u_hide_desktop { display: block !important; }
163
147
  .u_hide_mobile { display: block !important; }
164
148
 
165
- @media only screen and (max-width: ${contentWidth + 20}px) {
149
+ @media only screen and (max-width: ${t + 20}px) {
166
150
  .u_hide_desktop { display: block !important; }
167
151
  .u_hide_mobile { display: none !important; }
168
152
  }
169
153
 
170
- @media only screen and (min-width: ${contentWidth + 21}px) {
154
+ @media only screen and (min-width: ${t + 21}px) {
171
155
  .u_hide_desktop { display: none !important; }
172
156
  .u_hide_mobile { display: block !important; }
173
157
  }`;
174
158
  }
175
- function renderDesignToHtml(design, toolRenderers, options) {
176
- const bodyValues = design.body.values;
177
- const contentWidth = parseInt(bodyValues.contentWidth || "600");
178
- const rowsHtml = design.body.rows.map((row) => renderRow(row, bodyValues, toolRenderers)).join("\n");
179
- const cssBlock = getResponsiveCss(contentWidth);
180
- let fullHtml = wrapInDocumentShell(rowsHtml, cssBlock, bodyValues);
181
- if (options?.mergeTags) {
182
- for (const [tag, value] of Object.entries(options.mergeTags)) {
183
- fullHtml = fullHtml.replaceAll(`{{${tag}}}`, value);
184
- }
185
- }
186
- const bodyMatch = fullHtml.match(/<body[^>]*>([\s\S]*)<\/body>/i);
187
- const cssMatch = fullHtml.match(/<style[^>]*>([\s\S]*?)<\/style>/gi);
188
- const fontsUsed = [];
189
- if (bodyValues.fontFamily?.url) {
190
- fontsUsed.push(bodyValues.fontFamily.url);
191
- }
192
- return {
193
- design: structuredClone(design),
194
- html: fullHtml,
159
+ function _(t, a, n) {
160
+ const e = t.body.values, d = parseInt(e.contentWidth || "600"), i = t.body.rows.map((l) => w(l, e, a)).join(`
161
+ `), s = $(d);
162
+ let o = k(i, s, e);
163
+ if (n?.mergeTags)
164
+ for (const [l, p] of Object.entries(n.mergeTags))
165
+ o = o.replaceAll(`{{${l}}}`, p);
166
+ const c = o.match(/<body[^>]*>([\s\S]*)<\/body>/i), m = o.match(/<style[^>]*>([\s\S]*?)<\/style>/gi), r = [];
167
+ return e.fontFamily?.url && r.push(e.fontFamily.url), {
168
+ design: structuredClone(t),
169
+ html: o,
195
170
  chunks: {
196
- body: bodyMatch?.[1] ?? rowsHtml,
197
- css: cssMatch?.map((s) => s.replace(/<\/?style[^>]*>/gi, "")).join("\n") ?? cssBlock,
198
- fonts: fontsUsed,
171
+ body: c?.[1] ?? i,
172
+ css: m?.map((l) => l.replace(/<\/?style[^>]*>/gi, "")).join(`
173
+ `) ?? s,
174
+ fonts: r,
199
175
  js: ""
200
176
  }
201
177
  };
202
178
  }
203
179
  export {
204
- getResponsiveCss,
205
- renderDesignToHtml,
206
- renderRow,
207
- wrapInDocumentShell
180
+ $ as getResponsiveCss,
181
+ _ as renderDesignToHtml,
182
+ w as renderRow,
183
+ k as wrapInDocumentShell
208
184
  };
209
185
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/layout/document-shell.ts","../src/layout/fluid-hybrid.ts","../src/utils/responsive-css.ts","../src/render.ts"],"sourcesContent":["import type { BodyValues } from '@emabuild/types';\n\nexport function wrapInDocumentShell(bodyHtml: string, cssBlock: string, bodyValues: BodyValues): string {\n const bgColor = bodyValues.backgroundColor || '#e7e7e7';\n const contentWidth = bodyValues.contentWidth || '600px';\n const fontFamily = bodyValues.fontFamily?.value || 'arial,helvetica,sans-serif';\n const textColor = bodyValues.textColor || '#000000';\n const preheaderText = bodyValues.preheaderText || '';\n\n const preheader = preheaderText\n ? `<div style=\"display:none;font-size:1px;color:${bgColor};line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;\">${preheaderText}${'&zwnj;&nbsp;'.repeat(80)}</div>`\n : '';\n\n return `<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\">\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n <meta name=\"x-apple-disable-message-reformatting\">\n <meta name=\"format-detection\" content=\"telephone=no,address=no,email=no,date=no,url=no\">\n <meta name=\"color-scheme\" content=\"light dark\">\n <meta name=\"supported-color-schemes\" content=\"light dark\">\n <title></title>\n <!--[if mso]>\n <noscript><xml>\n <o:OfficeDocumentSettings>\n <o:AllowPNG/><o:PixelsPerInch>96</o:PixelsPerInch>\n </o:OfficeDocumentSettings>\n </xml></noscript>\n <style type=\"text/css\">\n table, td, th { font-family: ${fontFamily} !important; }\n </style>\n <![endif]-->\n <!--[if !mso]><!-->\n <style type=\"text/css\">\n ${cssBlock}\n </style>\n <!--<![endif]-->\n <style type=\"text/css\">\n body { margin: 0; padding: 0; }\n table, tr, td { vertical-align: top; border-collapse: collapse; }\n p { margin: 0; }\n .ie-container table, .mso-container table { table-layout: fixed; }\n * { line-height: inherit; }\n a[x-apple-data-detectors='true'] { color: inherit !important; text-decoration: none !important; }\n </style>\n</head>\n<body class=\"clean-body u_body\" style=\"margin:0;padding:0;-webkit-text-size-adjust:100%;background-color:${bgColor};color:${textColor};\">\n ${preheader}\n <table id=\"u_body\" style=\"border-collapse:collapse;table-layout:fixed;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;vertical-align:top;min-width:320px;margin:0 auto;background-color:${bgColor};width:100%;\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n <tbody>\n <tr style=\"vertical-align:top;\">\n <td style=\"word-break:break-word;border-collapse:collapse !important;vertical-align:top;\">\n <!--[if (mso)|(IE)]><table width=\"${parseInt(contentWidth)}\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr><td><![endif]-->\n ${bodyHtml}\n <!--[if (mso)|(IE)]></td></tr></table><![endif]-->\n </td>\n </tr>\n </tbody>\n </table>\n</body>\n</html>`;\n}\n","import type { DesignRow, DesignColumn, BodyValues } from '@emabuild/types';\n\ntype ContentRenderer = (values: Record<string, unknown>, ctx: any) => string;\n\nexport function renderRow(\n row: DesignRow,\n bodyValues: BodyValues,\n toolRenderers: Map<string, ContentRenderer>,\n): string {\n const contentWidth = parseInt(bodyValues.contentWidth || '600');\n const bgColor = row.values.backgroundColor || '';\n const colsBgColor = row.values.columnsBackgroundColor || '';\n const padding = row.values.padding || '0px';\n const totalCells = row.cells.reduce((a, b) => a + b, 0);\n\n const bgStyle = bgColor ? `background-color:${bgColor};` : '';\n const bgImage = row.values.backgroundImage?.url\n ? `background-image:url('${row.values.backgroundImage.url}');background-repeat:${row.values.backgroundImage.repeat ? 'repeat' : 'no-repeat'};background-position:center top;background-size:${row.values.backgroundImage.cover ? 'cover' : 'auto'};`\n : '';\n\n const columnsHtml = row.columns.map((col, i) => {\n const colWidthPx = Math.round((row.cells[i] / totalCells) * contentWidth);\n return renderColumn(col, colWidthPx, colsBgColor, bodyValues, toolRenderers);\n });\n\n // For multi-column layouts, use MSO ghost tables\n const needsGhostTable = row.columns.length > 1;\n\n let innerHtml: string;\n if (needsGhostTable) {\n const ghostCols = row.columns.map((col, i) => {\n const colWidthPx = Math.round((row.cells[i] / totalCells) * contentWidth);\n const colHtml = renderColumn(col, colWidthPx, colsBgColor, bodyValues, toolRenderers);\n return `<!--[if (mso)|(IE)]><td align=\"center\" width=\"${colWidthPx}\" style=\"width:${colWidthPx}px;padding:0px;border:none;\" valign=\"top\"><![endif]-->\n${colHtml}\n<!--[if (mso)|(IE)]></td><![endif]-->`;\n });\n\n innerHtml = `<!--[if (mso)|(IE)]><table role=\"presentation\" width=\"${contentWidth}\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr>${ghostCols.join('\\n')}</tr></table><![endif]-->\n\n<!--[if !mso]><!-->\n<div style=\"max-width:${contentWidth}px;margin:0 auto;\">\n${columnsHtml.join('\\n')}\n</div>\n<!--<![endif]-->`;\n } else {\n innerHtml = columnsHtml.join('\\n');\n }\n\n // Visibility classes\n const hideDesktop = row.values.hideDesktop ? ' u_hide_desktop' : '';\n const hideMobile = row.values.hideMobile ? ' u_hide_mobile' : '';\n\n return `<div class=\"u_row${hideDesktop}${hideMobile}\" style=\"padding:${padding};${bgStyle}${bgImage}\">\n <div style=\"margin:0 auto;min-width:320px;max-width:${contentWidth}px;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;background-color:transparent;\">\n <div style=\"border-collapse:collapse;display:table;width:100%;height:100%;background-color:transparent;\">\n ${innerHtml}\n </div>\n </div>\n</div>`;\n}\n\nfunction renderColumn(\n col: DesignColumn,\n widthPx: number,\n colsBgColor: string,\n bodyValues: BodyValues,\n toolRenderers: Map<string, ContentRenderer>,\n): string {\n const bgColor = col.values.backgroundColor || colsBgColor || '';\n const padding = col.values.padding || '0px';\n const borderRadius = col.values.borderRadius || '0px';\n const bgStyle = bgColor ? `background-color:${bgColor};` : '';\n\n const contentsHtml = col.contents\n .map((content) => {\n const renderer = toolRenderers.get(content.type);\n if (!renderer) return `<!-- unknown tool: ${content.type} -->`;\n const ctx = {\n columnWidth: widthPx,\n displayMode: 'email',\n contentWidth: parseInt(bodyValues.contentWidth || '600'),\n bodyValues,\n };\n return renderer(content.values, ctx);\n })\n .join('\\n');\n\n return `<div class=\"u_column\" style=\"max-width:${widthPx}px;min-width:${Math.min(widthPx, 320)}px;display:table-cell;vertical-align:top;\">\n <div style=\"height:100%;width:100% !important;border-radius:${borderRadius};-webkit-border-radius:${borderRadius};${bgStyle}\">\n <div style=\"box-sizing:border-box;height:100%;padding:${padding};border:none;border-radius:${borderRadius};-webkit-border-radius:${borderRadius};\">\n ${contentsHtml || '<!--[if (!mso)&(!IE)]><!--><div style=\"height:0;min-height:1px;font-size:0;\">&nbsp;</div><!--<![endif]-->'}\n </div>\n </div>\n</div>`;\n}\n","export function getResponsiveCss(contentWidth: number): string {\n return `\n@media only screen and (min-width: ${contentWidth + 20}px) {\n .u_row .u_column { display: table-cell; }\n}\n\n@media only screen and (max-width: ${contentWidth + 20}px) {\n .u_row .u_column {\n display: block !important;\n width: 100% !important;\n min-width: 320px !important;\n max-width: 100% !important;\n }\n .u_row {\n width: 100% !important;\n }\n}\n\n@media only screen and (max-width: 620px) {\n .u_row-container {\n max-width: 100% !important;\n padding-left: 0 !important;\n padding-right: 0 !important;\n }\n}\n\n@media (prefers-color-scheme: dark) {\n /* Dark mode overrides — add per-client rules as needed */\n}\n\n/* Outlook dark mode */\n[data-ogsb] body,\n[data-ogsb] table,\n[data-ogsb] td {\n /* Preserve original colors */\n}\n\n.u_hide_desktop { display: block !important; }\n.u_hide_mobile { display: block !important; }\n\n@media only screen and (max-width: ${contentWidth + 20}px) {\n .u_hide_desktop { display: block !important; }\n .u_hide_mobile { display: none !important; }\n}\n\n@media only screen and (min-width: ${contentWidth + 21}px) {\n .u_hide_desktop { display: none !important; }\n .u_hide_mobile { display: block !important; }\n}`;\n}\n","import type { EmailDesign, ExportResult, ExportOptions, BodyValues } from '@emabuild/types';\nimport { wrapInDocumentShell } from './layout/document-shell.js';\nimport { renderRow } from './layout/fluid-hybrid.js';\nimport { getResponsiveCss } from './utils/responsive-css.js';\n\ntype ContentRenderer = (values: Record<string, unknown>, ctx: any) => string;\n\nexport function renderDesignToHtml(\n design: EmailDesign,\n toolRenderers: Map<string, ContentRenderer>,\n options?: ExportOptions,\n): ExportResult {\n const bodyValues = design.body.values;\n const contentWidth = parseInt(bodyValues.contentWidth || '600');\n\n // Render all rows\n const rowsHtml = design.body.rows\n .map((row) => renderRow(row, bodyValues, toolRenderers))\n .join('\\n');\n\n // Build responsive CSS\n const cssBlock = getResponsiveCss(contentWidth);\n\n // Build full document\n let fullHtml = wrapInDocumentShell(rowsHtml, cssBlock, bodyValues);\n\n // Process merge tags if provided\n if (options?.mergeTags) {\n for (const [tag, value] of Object.entries(options.mergeTags)) {\n fullHtml = fullHtml.replaceAll(`{{${tag}}}`, value);\n }\n }\n\n // Extract chunks\n const bodyMatch = fullHtml.match(/<body[^>]*>([\\s\\S]*)<\\/body>/i);\n const cssMatch = fullHtml.match(/<style[^>]*>([\\s\\S]*?)<\\/style>/gi);\n const fontsUsed: string[] = [];\n\n // Collect Google Fonts\n if (bodyValues.fontFamily?.url) {\n fontsUsed.push(bodyValues.fontFamily.url);\n }\n\n return {\n design: structuredClone(design),\n html: fullHtml,\n chunks: {\n body: bodyMatch?.[1] ?? rowsHtml,\n css: cssMatch?.map((s) => s.replace(/<\\/?style[^>]*>/gi, '')).join('\\n') ?? cssBlock,\n fonts: fontsUsed,\n js: '',\n },\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/layout/document-shell.ts","../src/layout/fluid-hybrid.ts","../src/utils/responsive-css.ts","../src/render.ts"],"sourcesContent":["import type { BodyValues } from '@emabuild/types';\n\nexport function wrapInDocumentShell(bodyHtml: string, cssBlock: string, bodyValues: BodyValues): string {\n const bgColor = bodyValues.backgroundColor || '#e7e7e7';\n const contentWidth = bodyValues.contentWidth || '600px';\n const fontFamily = bodyValues.fontFamily?.value || 'arial,helvetica,sans-serif';\n const textColor = bodyValues.textColor || '#000000';\n const preheaderText = bodyValues.preheaderText || '';\n\n const preheader = preheaderText\n ? `<div style=\"display:none;font-size:1px;color:${bgColor};line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;\">${preheaderText}${'&zwnj;&nbsp;'.repeat(80)}</div>`\n : '';\n\n return `<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\">\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n <meta name=\"x-apple-disable-message-reformatting\">\n <meta name=\"format-detection\" content=\"telephone=no,address=no,email=no,date=no,url=no\">\n <meta name=\"color-scheme\" content=\"light dark\">\n <meta name=\"supported-color-schemes\" content=\"light dark\">\n <title></title>\n <!--[if mso]>\n <noscript><xml>\n <o:OfficeDocumentSettings>\n <o:AllowPNG/><o:PixelsPerInch>96</o:PixelsPerInch>\n </o:OfficeDocumentSettings>\n </xml></noscript>\n <style type=\"text/css\">\n table, td, th { font-family: ${fontFamily} !important; }\n </style>\n <![endif]-->\n <!--[if !mso]><!-->\n <style type=\"text/css\">\n ${cssBlock}\n </style>\n <!--<![endif]-->\n <style type=\"text/css\">\n body { margin: 0; padding: 0; }\n table, tr, td { vertical-align: top; border-collapse: collapse; }\n p { margin: 0; }\n .ie-container table, .mso-container table { table-layout: fixed; }\n * { line-height: inherit; }\n a[x-apple-data-detectors='true'] { color: inherit !important; text-decoration: none !important; }\n </style>\n</head>\n<body class=\"clean-body u_body\" style=\"margin:0;padding:0;-webkit-text-size-adjust:100%;background-color:${bgColor};color:${textColor};\">\n ${preheader}\n <table id=\"u_body\" style=\"border-collapse:collapse;table-layout:fixed;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;vertical-align:top;min-width:320px;margin:0 auto;background-color:${bgColor};width:100%;\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n <tbody>\n <tr style=\"vertical-align:top;\">\n <td style=\"word-break:break-word;border-collapse:collapse !important;vertical-align:top;\">\n <!--[if (mso)|(IE)]><table width=\"${parseInt(contentWidth)}\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr><td><![endif]-->\n ${bodyHtml}\n <!--[if (mso)|(IE)]></td></tr></table><![endif]-->\n </td>\n </tr>\n </tbody>\n </table>\n</body>\n</html>`;\n}\n","import type { DesignRow, DesignColumn, BodyValues } from '@emabuild/types';\n\ntype ContentRenderer = (values: Record<string, unknown>, ctx: any) => string;\n\nexport function renderRow(\n row: DesignRow,\n bodyValues: BodyValues,\n toolRenderers: Map<string, ContentRenderer>,\n): string {\n const contentWidth = parseInt(bodyValues.contentWidth || '600');\n const bgColor = row.values.backgroundColor || '';\n const colsBgColor = row.values.columnsBackgroundColor || '';\n const padding = row.values.padding || '0px';\n const totalCells = row.cells.reduce((a, b) => a + b, 0);\n\n const bgStyle = bgColor ? `background-color:${bgColor};` : '';\n const bgImage = row.values.backgroundImage?.url\n ? `background-image:url('${row.values.backgroundImage.url}');background-repeat:${row.values.backgroundImage.repeat ? 'repeat' : 'no-repeat'};background-position:center top;background-size:${row.values.backgroundImage.cover ? 'cover' : 'auto'};`\n : '';\n\n const columnsHtml = row.columns.map((col, i) => {\n const colWidthPx = Math.round((row.cells[i] / totalCells) * contentWidth);\n return renderColumn(col, colWidthPx, colsBgColor, bodyValues, toolRenderers);\n });\n\n // For multi-column layouts, use MSO ghost tables\n const needsGhostTable = row.columns.length > 1;\n\n let innerHtml: string;\n if (needsGhostTable) {\n const ghostCols = row.columns.map((col, i) => {\n const colWidthPx = Math.round((row.cells[i] / totalCells) * contentWidth);\n const colHtml = renderColumn(col, colWidthPx, colsBgColor, bodyValues, toolRenderers);\n return `<!--[if (mso)|(IE)]><td align=\"center\" width=\"${colWidthPx}\" style=\"width:${colWidthPx}px;padding:0px;border:none;\" valign=\"top\"><![endif]-->\n${colHtml}\n<!--[if (mso)|(IE)]></td><![endif]-->`;\n });\n\n innerHtml = `<!--[if (mso)|(IE)]><table role=\"presentation\" width=\"${contentWidth}\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr>${ghostCols.join('\\n')}</tr></table><![endif]-->\n\n<!--[if !mso]><!-->\n<div style=\"max-width:${contentWidth}px;margin:0 auto;\">\n${columnsHtml.join('\\n')}\n</div>\n<!--<![endif]-->`;\n } else {\n innerHtml = columnsHtml.join('\\n');\n }\n\n // Visibility classes\n const hideDesktop = row.values.hideDesktop ? ' u_hide_desktop' : '';\n const hideMobile = row.values.hideMobile ? ' u_hide_mobile' : '';\n\n return `<div class=\"u_row${hideDesktop}${hideMobile}\" style=\"padding:${padding};${bgStyle}${bgImage}\">\n <div style=\"margin:0 auto;min-width:320px;max-width:${contentWidth}px;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;background-color:transparent;\">\n <div style=\"border-collapse:collapse;display:table;width:100%;height:100%;background-color:transparent;\">\n ${innerHtml}\n </div>\n </div>\n</div>`;\n}\n\nfunction renderColumn(\n col: DesignColumn,\n widthPx: number,\n colsBgColor: string,\n bodyValues: BodyValues,\n toolRenderers: Map<string, ContentRenderer>,\n): string {\n const bgColor = col.values.backgroundColor || colsBgColor || '';\n const padding = col.values.padding || '0px';\n const borderRadius = col.values.borderRadius || '0px';\n const bgStyle = bgColor ? `background-color:${bgColor};` : '';\n\n const contentsHtml = col.contents\n .map((content) => {\n const renderer = toolRenderers.get(content.type);\n if (!renderer) return `<!-- unknown tool: ${content.type} -->`;\n const ctx = {\n columnWidth: widthPx,\n displayMode: 'email',\n contentWidth: parseInt(bodyValues.contentWidth || '600'),\n bodyValues,\n };\n return renderer(content.values, ctx);\n })\n .join('\\n');\n\n return `<div class=\"u_column\" style=\"max-width:${widthPx}px;min-width:${Math.min(widthPx, 320)}px;display:table-cell;vertical-align:top;\">\n <div style=\"height:100%;width:100% !important;border-radius:${borderRadius};-webkit-border-radius:${borderRadius};${bgStyle}\">\n <div style=\"box-sizing:border-box;height:100%;padding:${padding};border:none;border-radius:${borderRadius};-webkit-border-radius:${borderRadius};\">\n ${contentsHtml || '<!--[if (!mso)&(!IE)]><!--><div style=\"height:0;min-height:1px;font-size:0;\">&nbsp;</div><!--<![endif]-->'}\n </div>\n </div>\n</div>`;\n}\n","export function getResponsiveCss(contentWidth: number): string {\n return `\n@media only screen and (min-width: ${contentWidth + 20}px) {\n .u_row .u_column { display: table-cell; }\n}\n\n@media only screen and (max-width: ${contentWidth + 20}px) {\n .u_row .u_column {\n display: block !important;\n width: 100% !important;\n min-width: 320px !important;\n max-width: 100% !important;\n }\n .u_row {\n width: 100% !important;\n }\n}\n\n@media only screen and (max-width: 620px) {\n .u_row-container {\n max-width: 100% !important;\n padding-left: 0 !important;\n padding-right: 0 !important;\n }\n}\n\n@media (prefers-color-scheme: dark) {\n /* Dark mode overrides — add per-client rules as needed */\n}\n\n/* Outlook dark mode */\n[data-ogsb] body,\n[data-ogsb] table,\n[data-ogsb] td {\n /* Preserve original colors */\n}\n\n.u_hide_desktop { display: block !important; }\n.u_hide_mobile { display: block !important; }\n\n@media only screen and (max-width: ${contentWidth + 20}px) {\n .u_hide_desktop { display: block !important; }\n .u_hide_mobile { display: none !important; }\n}\n\n@media only screen and (min-width: ${contentWidth + 21}px) {\n .u_hide_desktop { display: none !important; }\n .u_hide_mobile { display: block !important; }\n}`;\n}\n","import type { EmailDesign, ExportResult, ExportOptions, BodyValues } from '@emabuild/types';\nimport { wrapInDocumentShell } from './layout/document-shell.js';\nimport { renderRow } from './layout/fluid-hybrid.js';\nimport { getResponsiveCss } from './utils/responsive-css.js';\n\ntype ContentRenderer = (values: Record<string, unknown>, ctx: any) => string;\n\nexport function renderDesignToHtml(\n design: EmailDesign,\n toolRenderers: Map<string, ContentRenderer>,\n options?: ExportOptions,\n): ExportResult {\n const bodyValues = design.body.values;\n const contentWidth = parseInt(bodyValues.contentWidth || '600');\n\n // Render all rows\n const rowsHtml = design.body.rows\n .map((row) => renderRow(row, bodyValues, toolRenderers))\n .join('\\n');\n\n // Build responsive CSS\n const cssBlock = getResponsiveCss(contentWidth);\n\n // Build full document\n let fullHtml = wrapInDocumentShell(rowsHtml, cssBlock, bodyValues);\n\n // Process merge tags if provided\n if (options?.mergeTags) {\n for (const [tag, value] of Object.entries(options.mergeTags)) {\n fullHtml = fullHtml.replaceAll(`{{${tag}}}`, value);\n }\n }\n\n // Extract chunks\n const bodyMatch = fullHtml.match(/<body[^>]*>([\\s\\S]*)<\\/body>/i);\n const cssMatch = fullHtml.match(/<style[^>]*>([\\s\\S]*?)<\\/style>/gi);\n const fontsUsed: string[] = [];\n\n // Collect Google Fonts\n if (bodyValues.fontFamily?.url) {\n fontsUsed.push(bodyValues.fontFamily.url);\n }\n\n return {\n design: structuredClone(design),\n html: fullHtml,\n chunks: {\n body: bodyMatch?.[1] ?? rowsHtml,\n css: cssMatch?.map((s) => s.replace(/<\\/?style[^>]*>/gi, '')).join('\\n') ?? cssBlock,\n fonts: fontsUsed,\n js: '',\n },\n };\n}\n"],"names":["wrapInDocumentShell","bodyHtml","cssBlock","bodyValues","bgColor","contentWidth","fontFamily","textColor","preheaderText","preheader","renderRow","row","toolRenderers","colsBgColor","padding","totalCells","a","b","bgStyle","bgImage","columnsHtml","col","i","colWidthPx","renderColumn","needsGhostTable","innerHtml","ghostCols","colHtml","hideDesktop","hideMobile","widthPx","borderRadius","contentsHtml","content","renderer","ctx","getResponsiveCss","renderDesignToHtml","design","options","rowsHtml","fullHtml","tag","value","bodyMatch","cssMatch","fontsUsed","s"],"mappings":"AAEO,SAASA,EAAoBC,GAAkBC,GAAkBC,GAAgC;AACtG,QAAMC,IAAUD,EAAW,mBAAmB,WACxCE,IAAeF,EAAW,gBAAgB,SAC1CG,IAAaH,EAAW,YAAY,SAAS,8BAC7CI,IAAYJ,EAAW,aAAa,WACpCK,IAAgBL,EAAW,iBAAiB,IAE5CM,IAAYD,IACd,gDAAgDJ,CAAO,6EAA6EI,CAAa,GAAG,eAAe,OAAO,EAAE,CAAC,WAC7K;AAEJ,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mCAkB0BF,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA,MAKvCJ,CAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2GAY6FE,CAAO,UAAUG,CAAS;AAAA,IACjIE,CAAS;AAAA,uMAC0LL,CAAO;AAAA;AAAA;AAAA;AAAA,8CAIhK,SAASC,CAAY,CAAC;AAAA,YACxDJ,CAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQpB;AC3DO,SAASS,EACdC,GACAR,GACAS,GACQ;AACR,QAAMP,IAAe,SAASF,EAAW,gBAAgB,KAAK,GACxDC,IAAUO,EAAI,OAAO,mBAAmB,IACxCE,IAAcF,EAAI,OAAO,0BAA0B,IACnDG,IAAUH,EAAI,OAAO,WAAW,OAChCI,IAAaJ,EAAI,MAAM,OAAO,CAACK,GAAGC,MAAMD,IAAIC,GAAG,CAAC,GAEhDC,IAAUd,IAAU,oBAAoBA,CAAO,MAAM,IACrDe,IAAUR,EAAI,OAAO,iBAAiB,MACxC,yBAAyBA,EAAI,OAAO,gBAAgB,GAAG,wBAAwBA,EAAI,OAAO,gBAAgB,SAAS,WAAW,WAAW,mDAAmDA,EAAI,OAAO,gBAAgB,QAAQ,UAAU,MAAM,MAC/O,IAEES,IAAcT,EAAI,QAAQ,IAAI,CAACU,GAAKC,MAAM;AAC9C,UAAMC,IAAa,KAAK,MAAOZ,EAAI,MAAMW,CAAC,IAAIP,IAAcV,CAAY;AACxE,WAAOmB,EAAaH,GAAKE,GAAYV,GAAaV,GAAYS,CAAa;AAAA,EAC7E,CAAC,GAGKa,IAAkBd,EAAI,QAAQ,SAAS;AAE7C,MAAIe;AACJ,MAAID,GAAiB;AACnB,UAAME,IAAYhB,EAAI,QAAQ,IAAI,CAACU,GAAKC,MAAM;AAC5C,YAAMC,IAAa,KAAK,MAAOZ,EAAI,MAAMW,CAAC,IAAIP,IAAcV,CAAY,GAClEuB,IAAUJ,EAAaH,GAAKE,GAAYV,GAAaV,GAAYS,CAAa;AACpF,aAAO,iDAAiDW,CAAU,kBAAkBA,CAAU;AAAA,EAClGK,CAAO;AAAA;AAAA,IAEL,CAAC;AAED,IAAAF,IAAY,yDAAyDrB,CAAY,oDAAoDsB,EAAU,KAAK;AAAA,CAAI,CAAC;AAAA;AAAA;AAAA,wBAGrItB,CAAY;AAAA,EAClCe,EAAY,KAAK;AAAA,CAAI,CAAC;AAAA;AAAA;AAAA,EAGtB;AACE,IAAAM,IAAYN,EAAY,KAAK;AAAA,CAAI;AAInC,QAAMS,IAAclB,EAAI,OAAO,cAAc,oBAAoB,IAC3DmB,IAAanB,EAAI,OAAO,aAAa,mBAAmB;AAE9D,SAAO,oBAAoBkB,CAAW,GAAGC,CAAU,oBAAoBhB,CAAO,IAAII,CAAO,GAAGC,CAAO;AAAA,wDAC7Cd,CAAY;AAAA;AAAA,QAE5DqB,CAAS;AAAA;AAAA;AAAA;AAIjB;AAEA,SAASF,EACPH,GACAU,GACAlB,GACAV,GACAS,GACQ;AACR,QAAMR,IAAUiB,EAAI,OAAO,mBAAmBR,KAAe,IACvDC,IAAUO,EAAI,OAAO,WAAW,OAChCW,IAAeX,EAAI,OAAO,gBAAgB,OAC1CH,IAAUd,IAAU,oBAAoBA,CAAO,MAAM,IAErD6B,IAAeZ,EAAI,SACtB,IAAI,CAACa,MAAY;AAChB,UAAMC,IAAWvB,EAAc,IAAIsB,EAAQ,IAAI;AAC/C,QAAI,CAACC,EAAU,QAAO,sBAAsBD,EAAQ,IAAI;AACxD,UAAME,IAAM;AAAA,MACV,aAAaL;AAAA,MACb,aAAa;AAAA,MACb,cAAc,SAAS5B,EAAW,gBAAgB,KAAK;AAAA,MACvD,YAAAA;AAAA,IAAA;AAEF,WAAOgC,EAASD,EAAQ,QAAQE,CAAG;AAAA,EACrC,CAAC,EACA,KAAK;AAAA,CAAI;AAEZ,SAAO,0CAA0CL,CAAO,gBAAgB,KAAK,IAAIA,GAAS,GAAG,CAAC;AAAA,gEAChCC,CAAY,0BAA0BA,CAAY,IAAId,CAAO;AAAA,4DACjEJ,CAAO,8BAA8BkB,CAAY,0BAA0BA,CAAY;AAAA,QAC3IC,KAAgB,2GAA2G;AAAA;AAAA;AAAA;AAInI;AC/FO,SAASI,EAAiBhC,GAA8B;AAC7D,SAAO;AAAA,qCAC4BA,IAAe,EAAE;AAAA;AAAA;AAAA;AAAA,qCAIjBA,IAAe,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qCAkCjBA,IAAe,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,qCAKjBA,IAAe,EAAE;AAAA;AAAA;AAAA;AAItD;AC1CO,SAASiC,EACdC,GACA3B,GACA4B,GACc;AACd,QAAMrC,IAAaoC,EAAO,KAAK,QACzBlC,IAAe,SAASF,EAAW,gBAAgB,KAAK,GAGxDsC,IAAWF,EAAO,KAAK,KAC1B,IAAI,CAAC5B,MAAQD,EAAUC,GAAKR,GAAYS,CAAa,CAAC,EACtD,KAAK;AAAA,CAAI,GAGNV,IAAWmC,EAAiBhC,CAAY;AAG9C,MAAIqC,IAAW1C,EAAoByC,GAAUvC,GAAUC,CAAU;AAGjE,MAAIqC,GAAS;AACX,eAAW,CAACG,GAAKC,CAAK,KAAK,OAAO,QAAQJ,EAAQ,SAAS;AACzD,MAAAE,IAAWA,EAAS,WAAW,KAAKC,CAAG,MAAMC,CAAK;AAKtD,QAAMC,IAAYH,EAAS,MAAM,+BAA+B,GAC1DI,IAAWJ,EAAS,MAAM,mCAAmC,GAC7DK,IAAsB,CAAA;AAG5B,SAAI5C,EAAW,YAAY,OACzB4C,EAAU,KAAK5C,EAAW,WAAW,GAAG,GAGnC;AAAA,IACL,QAAQ,gBAAgBoC,CAAM;AAAA,IAC9B,MAAMG;AAAA,IACN,QAAQ;AAAA,MACN,MAAMG,IAAY,CAAC,KAAKJ;AAAA,MACxB,KAAKK,GAAU,IAAI,CAACE,MAAMA,EAAE,QAAQ,qBAAqB,EAAE,CAAC,EAAE,KAAK;AAAA,CAAI,KAAK9C;AAAA,MAC5E,OAAO6C;AAAA,MACP,IAAI;AAAA,IAAA;AAAA,EACN;AAEJ;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emabuild/email-renderer",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Email HTML renderer — converts design JSON to cross-client email HTML",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,7 +18,7 @@
18
18
  "README.md"
19
19
  ],
20
20
  "dependencies": {
21
- "@emabuild/types": "0.0.4"
21
+ "@emabuild/types": "0.0.5"
22
22
  },
23
23
  "devDependencies": {
24
24
  "vite": "^6.2.0",