email-builder-utils 1.1.31 → 1.1.35
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/utils/convertJsonToHtml.d.ts.map +1 -1
- package/dist/utils/convertJsonToHtml.js +79 -77
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/jsonToHTML.d.ts.map +1 -1
- package/dist/utils/jsonToHTML.js +347 -445
- package/package.json +33 -33
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertJsonToHtml.d.ts","sourceRoot":"","sources":["../../src/utils/convertJsonToHtml.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,GAAU,UAAU,GAAG,
|
|
1
|
+
{"version":3,"file":"convertJsonToHtml.d.ts","sourceRoot":"","sources":["../../src/utils/convertJsonToHtml.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,GAAU,UAAU,GAAG,oBA8GpD,CAAC"}
|
|
@@ -12,83 +12,85 @@ const convertJsonToHtml = async (jsonData) => {
|
|
|
12
12
|
}
|
|
13
13
|
const { fontFamily, canvasColor, textColor, padding = {}, borderColor, borderRadius, borderWidth, borderStyle, } = rootData.style || {};
|
|
14
14
|
const { top = 0, right = 0, bottom = 0, left = 0 } = padding;
|
|
15
|
-
const rawHtml = `<!DOCTYPE html>
|
|
16
|
-
<html lang="en">
|
|
17
|
-
<head>
|
|
18
|
-
<meta charset="UTF-8" />
|
|
19
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
20
|
-
<meta name="x-apple-disable-message-reformatting" />
|
|
21
|
-
<style>
|
|
22
|
-
.responsive-table {
|
|
23
|
-
width: 100%;
|
|
24
|
-
max-width: 600px;
|
|
25
|
-
}
|
|
26
|
-
@media only screen and (max-width: 600px) {
|
|
27
|
-
.responsive-table {
|
|
28
|
-
width: 100% !important;
|
|
29
|
-
}
|
|
30
|
-
.stack-column,
|
|
31
|
-
.stack-column td {
|
|
32
|
-
display: block !important;
|
|
33
|
-
width: 100% !important;
|
|
34
|
-
max-width: 100% !important;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
.hide-mobile {
|
|
38
|
-
display: block !important;
|
|
39
|
-
mso-hide: all !important; /* Hide in Outlook */
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.hide-desktop {
|
|
43
|
-
display: block !important;
|
|
44
|
-
mso-hide: all !important; /* Hide in Outlook */
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
@media only screen and (max-width: 600px) {
|
|
48
|
-
.hide-mobile {
|
|
49
|
-
display: none !important;
|
|
50
|
-
max-height: 0 !important;
|
|
51
|
-
overflow: hidden !important;
|
|
52
|
-
mso-hide: all !important;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
@media only screen and (min-width: 601px) {
|
|
57
|
-
.hide-desktop {
|
|
58
|
-
display: none !important;
|
|
59
|
-
max-height: 0 !important;
|
|
60
|
-
overflow: hidden !important;
|
|
61
|
-
mso-hide: all !important;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
</style>
|
|
66
|
-
</head>
|
|
67
|
-
<body>
|
|
68
|
-
<center>
|
|
69
|
-
<table
|
|
70
|
-
class="responsive-table"
|
|
71
|
-
bgcolor="${canvasColor}"
|
|
72
|
-
style="
|
|
73
|
-
font-family: ${fontFamily};
|
|
74
|
-
margin: 0 auto;
|
|
75
|
-
table-layout:fixed;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
15
|
+
const rawHtml = `<!DOCTYPE html>
|
|
16
|
+
<html lang="en">
|
|
17
|
+
<head>
|
|
18
|
+
<meta charset="UTF-8" />
|
|
19
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
20
|
+
<meta name="x-apple-disable-message-reformatting" />
|
|
21
|
+
<style>
|
|
22
|
+
.responsive-table {
|
|
23
|
+
width: 100%;
|
|
24
|
+
max-width: 600px;
|
|
25
|
+
}
|
|
26
|
+
@media only screen and (max-width: 600px) {
|
|
27
|
+
.responsive-table {
|
|
28
|
+
width: 100% !important;
|
|
29
|
+
}
|
|
30
|
+
.stack-column,
|
|
31
|
+
.stack-column td {
|
|
32
|
+
display: block !important;
|
|
33
|
+
width: 100% !important;
|
|
34
|
+
max-width: 100% !important;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
.hide-mobile {
|
|
38
|
+
display: block !important;
|
|
39
|
+
mso-hide: all !important; /* Hide in Outlook */
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.hide-desktop {
|
|
43
|
+
display: block !important;
|
|
44
|
+
mso-hide: all !important; /* Hide in Outlook */
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@media only screen and (max-width: 600px) {
|
|
48
|
+
.hide-mobile {
|
|
49
|
+
display: none !important;
|
|
50
|
+
max-height: 0 !important;
|
|
51
|
+
overflow: hidden !important;
|
|
52
|
+
mso-hide: all !important;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@media only screen and (min-width: 601px) {
|
|
57
|
+
.hide-desktop {
|
|
58
|
+
display: none !important;
|
|
59
|
+
max-height: 0 !important;
|
|
60
|
+
overflow: hidden !important;
|
|
61
|
+
mso-hide: all !important;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
</style>
|
|
66
|
+
</head>
|
|
67
|
+
<body>
|
|
68
|
+
<center>
|
|
69
|
+
<table
|
|
70
|
+
class="responsive-table"
|
|
71
|
+
bgcolor="${canvasColor}"
|
|
72
|
+
style="
|
|
73
|
+
font-family: ${fontFamily};
|
|
74
|
+
margin: 0 auto;
|
|
75
|
+
table-layout:fixed;
|
|
76
|
+
width:600px;
|
|
77
|
+
max-width:600px;
|
|
78
|
+
background-color: ${canvasColor};
|
|
79
|
+
color: ${textColor};
|
|
80
|
+
padding: ${top}px ${right}px ${bottom}px ${left}px;
|
|
81
|
+
border: ${borderWidth}px ${borderStyle} ${borderColor};
|
|
82
|
+
border-radius: ${borderRadius}px; "
|
|
83
|
+
>
|
|
84
|
+
<tbody>
|
|
85
|
+
<tr>
|
|
86
|
+
<td style="padding: 0;">
|
|
87
|
+
${blocksHtml.join("")}
|
|
88
|
+
</td>
|
|
89
|
+
</tr>
|
|
90
|
+
</tbody>
|
|
91
|
+
</table>
|
|
92
|
+
</center>
|
|
93
|
+
</body>
|
|
92
94
|
</html>`;
|
|
93
95
|
return rawHtml;
|
|
94
96
|
};
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC"}
|
package/dist/utils/index.js
CHANGED
|
@@ -16,3 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./convertJsonToHtml"), exports);
|
|
18
18
|
__exportStar(require("./generateUniqueId"), exports);
|
|
19
|
+
__exportStar(require("./common"), exports);
|
|
20
|
+
__exportStar(require("./jsonToHTML"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsonToHTML.d.ts","sourceRoot":"","sources":["../../src/utils/jsonToHTML.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"jsonToHTML.d.ts","sourceRoot":"","sources":["../../src/utils/jsonToHTML.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE;QACJ,KAAK,EAAE,cAAc,CAAC;QACtB,KAAK,EAAE,GAAG,CAAC;QACX,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;KAC7B,CAAC;CACH;AAYD,eAAO,MAAM,gBAAgB,kDAAkD,CAAC;AAyFhF,wBAAsB,aAAa,CACjC,SAAS,EAAE,UAAU,EACrB,QAAQ,EAAE,GAAG,EACb,aAAa,EAAE,MAAM,mBAwBtB;AAmkBD,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,mBAyL5E"}
|
package/dist/utils/jsonToHTML.js
CHANGED
|
@@ -40,19 +40,53 @@ function buildStyles(style, { pxChanges, perChanges }) {
|
|
|
40
40
|
Object.entries(style).forEach(([key, value]) => {
|
|
41
41
|
if (key === "customCss")
|
|
42
42
|
return;
|
|
43
|
+
const INVALID_KEYS = [
|
|
44
|
+
"columns",
|
|
45
|
+
"cellWidths",
|
|
46
|
+
"cellWidth",
|
|
47
|
+
"childWidth",
|
|
48
|
+
"visibility",
|
|
49
|
+
"hideOnMobile",
|
|
50
|
+
"hideOnDesktop"
|
|
51
|
+
];
|
|
52
|
+
if (INVALID_KEYS.includes(key))
|
|
53
|
+
return;
|
|
54
|
+
// Prevent null/undefined/"" from leaking into CSS
|
|
43
55
|
if (value === undefined || value === null || value === "")
|
|
44
56
|
return;
|
|
57
|
+
// FIX 1 — SANITIZE padding objects
|
|
45
58
|
if ((key === "padding" || key === "buttonPadding") &&
|
|
46
59
|
typeof value === "object") {
|
|
47
|
-
const
|
|
48
|
-
|
|
60
|
+
const pad = value;
|
|
61
|
+
const safePad = {
|
|
62
|
+
top: Number.isFinite(pad.top) ? pad.top : 0,
|
|
63
|
+
right: Number.isFinite(pad.right) ? pad.right : 0,
|
|
64
|
+
bottom: Number.isFinite(pad.bottom) ? pad.bottom : 0,
|
|
65
|
+
left: Number.isFinite(pad.left) ? pad.left : 0,
|
|
66
|
+
};
|
|
67
|
+
value = `${safePad.top}px ${safePad.right}px ${safePad.bottom}px ${safePad.left}px`;
|
|
49
68
|
}
|
|
50
69
|
const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
70
|
+
// FIX 2 — Sanitize invalid px/per values
|
|
51
71
|
if (pxChanges.includes(key)) {
|
|
52
|
-
|
|
72
|
+
if (typeof value === "number") {
|
|
73
|
+
stylesObj[cssKey] = `${value}px`;
|
|
74
|
+
}
|
|
75
|
+
else if (typeof value === "string" && value.includes("null")) {
|
|
76
|
+
// Skip invalid styles
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
stylesObj[cssKey] = value;
|
|
81
|
+
}
|
|
53
82
|
}
|
|
54
83
|
else if (perChanges.includes(key)) {
|
|
55
|
-
|
|
84
|
+
if (typeof value === "number") {
|
|
85
|
+
stylesObj[cssKey] = `${value}%`;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
stylesObj[cssKey] = value;
|
|
89
|
+
}
|
|
56
90
|
}
|
|
57
91
|
else {
|
|
58
92
|
stylesObj[cssKey] = value;
|
|
@@ -93,14 +127,14 @@ function appendOutlookSupport(content, contentStyle, className) {
|
|
|
93
127
|
const visibilityClass = className || "";
|
|
94
128
|
const shouldHideInOutlook = visibilityClass.includes("hide-desktop");
|
|
95
129
|
if (shouldHideInOutlook) {
|
|
96
|
-
return `
|
|
97
|
-
<!--[if !mso]><!-->
|
|
98
|
-
<table width="100%" style="${exports.tableCommonStyle}" class="${visibilityClass}"><tr><td style="${contentStyle}">${content}</td></tr></table>
|
|
99
|
-
<!--<![endif]-->
|
|
130
|
+
return `
|
|
131
|
+
<!--[if !mso]><!-->
|
|
132
|
+
<table width="100%" style="${exports.tableCommonStyle}" class="${visibilityClass}"><tr><td style="${contentStyle}">${content}</td></tr></table>
|
|
133
|
+
<!--<![endif]-->
|
|
100
134
|
`;
|
|
101
135
|
}
|
|
102
|
-
return `
|
|
103
|
-
<table width="100%" style="${exports.tableCommonStyle}" class="${visibilityClass}"><tr><td style="${contentStyle}">${content}</td></tr></table>
|
|
136
|
+
return `
|
|
137
|
+
<table width="100%" style="${exports.tableCommonStyle}; max-width:600px;" class="${visibilityClass}"><tr><td style="${contentStyle}">${content}</td></tr></table>
|
|
104
138
|
`;
|
|
105
139
|
}
|
|
106
140
|
function convertDividerBlockToHtml(blockData) {
|
|
@@ -119,21 +153,21 @@ function convertDividerBlockToHtml(blockData) {
|
|
|
119
153
|
]
|
|
120
154
|
.filter(Boolean)
|
|
121
155
|
.join(" ");
|
|
122
|
-
const dividerContent = `
|
|
123
|
-
<table
|
|
124
|
-
width="${dividerWidth}%"
|
|
125
|
-
cellpadding="0"
|
|
126
|
-
cellspacing="0"
|
|
127
|
-
>
|
|
128
|
-
<tr>
|
|
129
|
-
<td
|
|
130
|
-
height="${thickness}"
|
|
131
|
-
style="font-size:1px; line-height:1px; background:${dividerColor}; width:${dividerWidth};"
|
|
132
|
-
>
|
|
133
|
-
|
|
134
|
-
</td>
|
|
135
|
-
</tr>
|
|
136
|
-
</table>
|
|
156
|
+
const dividerContent = `
|
|
157
|
+
<table
|
|
158
|
+
width="${dividerWidth}%"
|
|
159
|
+
cellpadding="0"
|
|
160
|
+
cellspacing="0"
|
|
161
|
+
>
|
|
162
|
+
<tr>
|
|
163
|
+
<td
|
|
164
|
+
height="${thickness}"
|
|
165
|
+
style="font-size:1px; line-height:1px; background:${dividerColor}; width:${dividerWidth};"
|
|
166
|
+
>
|
|
167
|
+
|
|
168
|
+
</td>
|
|
169
|
+
</tr>
|
|
170
|
+
</table>
|
|
137
171
|
`;
|
|
138
172
|
return appendOutlookSupport(dividerContent, convertedStyle, visibilityClass);
|
|
139
173
|
}
|
|
@@ -214,21 +248,21 @@ async function appendOutlookForImage(content, outerContainerWidth, innerContaine
|
|
|
214
248
|
const borderAttributes = borderWidth > 0
|
|
215
249
|
? `strokeweight="${borderWidth}px" strokecolor="${borderColor}"`
|
|
216
250
|
: `stroked="false"`;
|
|
217
|
-
const outlookImage = `<!--[if mso]>
|
|
218
|
-
<v:${useRoundRect ? "roundrect" : "rect"} xmlns:v="urn:schemas-microsoft-com:vml"
|
|
219
|
-
style="width:${scaledWidth}px;height:${scaledHeight}px;"
|
|
220
|
-
${borderAttributes}
|
|
221
|
-
${useRoundRect ? `arcsize="${arcsize}"` : ""}
|
|
222
|
-
fill="true" fillcolor="none">
|
|
223
|
-
<v:fill src="${imageUrl}" type="frame" />
|
|
224
|
-
<v:textbox inset="0,0,0,0"><div style="display:none;">.</div></v:textbox>
|
|
225
|
-
</v:${useRoundRect ? "roundrect" : "rect"}>
|
|
251
|
+
const outlookImage = `<!--[if mso]>
|
|
252
|
+
<v:${useRoundRect ? "roundrect" : "rect"} xmlns:v="urn:schemas-microsoft-com:vml"
|
|
253
|
+
style="width:${scaledWidth}px;height:${scaledHeight}px;"
|
|
254
|
+
${borderAttributes}
|
|
255
|
+
${useRoundRect ? `arcsize="${arcsize}"` : ""}
|
|
256
|
+
fill="true" fillcolor="none">
|
|
257
|
+
<v:fill src="${imageUrl}" type="frame" />
|
|
258
|
+
<v:textbox inset="0,0,0,0"><div style="display:none;">.</div></v:textbox>
|
|
259
|
+
</v:${useRoundRect ? "roundrect" : "rect"}>
|
|
226
260
|
<![endif]-->`;
|
|
227
|
-
return `
|
|
228
|
-
${outlookImage}
|
|
229
|
-
<!--[if !mso]><!-->
|
|
230
|
-
${content}
|
|
231
|
-
<!--<![endif]-->
|
|
261
|
+
return `
|
|
262
|
+
${outlookImage}
|
|
263
|
+
<!--[if !mso]><!-->
|
|
264
|
+
${content}
|
|
265
|
+
<!--<![endif]-->
|
|
232
266
|
`;
|
|
233
267
|
}
|
|
234
268
|
async function computeScaledDimensions(imageUrl, maxContainerWidthPx) {
|
|
@@ -291,23 +325,23 @@ function appendOutlookForButton(content, buttonStyle, navigateToUrl, text) {
|
|
|
291
325
|
const borderAttributes = borderWidth > 0
|
|
292
326
|
? `strokeweight="${borderWidth}px" strokecolor="${borderColor}"`
|
|
293
327
|
: `stroked="false"`;
|
|
294
|
-
return `
|
|
295
|
-
<!--[if mso]>
|
|
296
|
-
<v:${borderRadius ? "roundrect" : "rect"} xmlns:v="urn:schemas-microsoft-com:vml" href="${navigateToUrl}"
|
|
297
|
-
style="height:${height}px;v-text-anchor:middle;width:${width}px;"
|
|
298
|
-
arcsize="${borderRadius / height}" ${borderAttributes}
|
|
299
|
-
fillcolor="${buttonColor}">
|
|
300
|
-
<w:anchorlock/>
|
|
301
|
-
<v:textbox inset="${buttonPadding.top}px,${buttonPadding.left}px,${buttonPadding.bottom}px,${buttonPadding.right}px">
|
|
302
|
-
<center style="font-family:${fontFamily};font-size:${fontSize}px;font-weight:${fontWeight};color:${color};">
|
|
303
|
-
${text}
|
|
304
|
-
</center>
|
|
305
|
-
</v:textbox>
|
|
306
|
-
</v:${borderRadius ? "roundrect" : "rect"}>
|
|
307
|
-
<![endif]-->
|
|
308
|
-
<!--[if !mso]><!-->
|
|
309
|
-
${content}
|
|
310
|
-
<!--<![endif]-->
|
|
328
|
+
return `
|
|
329
|
+
<!--[if mso]>
|
|
330
|
+
<v:${borderRadius ? "roundrect" : "rect"} xmlns:v="urn:schemas-microsoft-com:vml" href="${navigateToUrl}"
|
|
331
|
+
style="height:${height}px;v-text-anchor:middle;width:${width}px;"
|
|
332
|
+
arcsize="${borderRadius / height}" ${borderAttributes}
|
|
333
|
+
fillcolor="${buttonColor}">
|
|
334
|
+
<w:anchorlock/>
|
|
335
|
+
<v:textbox inset="${buttonPadding.top}px,${buttonPadding.left}px,${buttonPadding.bottom}px,${buttonPadding.right}px">
|
|
336
|
+
<center style="font-family:${fontFamily};font-size:${fontSize}px;font-weight:${fontWeight};color:${color};">
|
|
337
|
+
${text}
|
|
338
|
+
</center>
|
|
339
|
+
</v:textbox>
|
|
340
|
+
</v:${borderRadius ? "roundrect" : "rect"}>
|
|
341
|
+
<![endif]-->
|
|
342
|
+
<!--[if !mso]><!-->
|
|
343
|
+
${content}
|
|
344
|
+
<!--<![endif]-->
|
|
311
345
|
`;
|
|
312
346
|
}
|
|
313
347
|
function convertButtonBlock(blockData) {
|
|
@@ -346,90 +380,106 @@ async function convertGridBlock(blockData, rootData, cellWidthInPx) {
|
|
|
346
380
|
const { columns = 1, cellWidths = [], responsive = true } = props;
|
|
347
381
|
const { columnGap = 0, ...restStyle } = style;
|
|
348
382
|
const gridVisibilityClass = (0, common_1.getVisibilityClass)(props);
|
|
383
|
+
// FIX: avoid table-layout:fixed – causes shrink in many clients
|
|
349
384
|
const tableStyles = buildStyles(restStyle, {
|
|
350
385
|
perChanges: [],
|
|
351
386
|
pxChanges: allPxAttributes,
|
|
352
387
|
});
|
|
353
388
|
const total = childrenIds.length;
|
|
354
389
|
const visualRows = Math.ceil(total / columns);
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
<![endif]-->
|
|
361
|
-
<table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%"
|
|
362
|
-
|
|
390
|
+
let html = `
|
|
391
|
+
<!--[if mso]>
|
|
392
|
+
<table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%"
|
|
393
|
+
style="border-collapse:separate;border-spacing:${columnGap}px;"
|
|
394
|
+
class="${gridVisibilityClass}">
|
|
395
|
+
<![endif]-->
|
|
396
|
+
<table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%"
|
|
397
|
+
role="presentation"
|
|
398
|
+
style="border-collapse:separate;border-spacing:${columnGap}px; ${tableStyles}; max-width:600px;"
|
|
399
|
+
class="${gridVisibilityClass}">
|
|
363
400
|
`;
|
|
364
401
|
for (let r = 0; r < visualRows; r++) {
|
|
365
402
|
html += "<tr>";
|
|
366
|
-
|
|
367
|
-
|
|
403
|
+
// COUNT visible cells only
|
|
404
|
+
let visibleCells = 0;
|
|
405
|
+
const rowIds = [];
|
|
368
406
|
for (let c = 0; c < columns; c++) {
|
|
369
407
|
const idx = r * columns + c;
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
const
|
|
374
|
-
const
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
visibleCellsInRow++;
|
|
378
|
-
}
|
|
379
|
-
else {
|
|
380
|
-
rowCellVisibility.push(false);
|
|
408
|
+
const id = childrenIds[idx] ?? null;
|
|
409
|
+
rowIds.push(id);
|
|
410
|
+
if (id) {
|
|
411
|
+
const child = rootData[id];
|
|
412
|
+
const isHidden = child?.data?.props?.hideOnDesktop;
|
|
413
|
+
if (!isHidden)
|
|
414
|
+
visibleCells++;
|
|
381
415
|
}
|
|
382
416
|
}
|
|
383
|
-
|
|
417
|
+
// FIX: fallback safe-width
|
|
418
|
+
const safeWidth = visibleCells > 0 ? Math.min(100 / visibleCells, 50) : Math.min(100 / columns, 50);
|
|
384
419
|
for (let c = 0; c < columns; c++) {
|
|
385
420
|
const idx = r * columns + c;
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
421
|
+
const id = rowIds[c];
|
|
422
|
+
let widthPercent = cellWidths[c] ?? safeWidth;
|
|
423
|
+
// FIX: never exceed reasonable width
|
|
424
|
+
if (widthPercent <= 0 || widthPercent > 100) {
|
|
425
|
+
widthPercent = safeWidth;
|
|
426
|
+
}
|
|
427
|
+
// FIX: Cap width percent to prevent overflow in Outlook
|
|
428
|
+
widthPercent = Math.min(widthPercent, 50);
|
|
429
|
+
if (id) {
|
|
430
|
+
const child = rootData[id];
|
|
431
|
+
const { style: cellStyle = {}, props: childProps = {} } = child.data;
|
|
391
432
|
const verticalAlign = cellStyle.verticalAlign || "top";
|
|
392
|
-
const
|
|
393
|
-
const
|
|
394
|
-
if
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
433
|
+
const childVisible = !childProps.hideOnDesktop;
|
|
434
|
+
const visibilityClass = (0, common_1.getVisibilityClass)(childProps);
|
|
435
|
+
// Only render if visible
|
|
436
|
+
if (childVisible) {
|
|
437
|
+
const { html: childHtml, styles } = await convertGridCellBlock(child, rootData, widthPercent, cellWidthInPx);
|
|
438
|
+
html += `
|
|
439
|
+
<td
|
|
440
|
+
width="${Math.round(widthPercent)}%"
|
|
441
|
+
class="${[
|
|
442
|
+
responsive ? "stack-column" : "",
|
|
443
|
+
visibilityClass,
|
|
444
|
+
].filter(Boolean).join(" ")}"
|
|
445
|
+
style="vertical-align:${verticalAlign};word-break:break-word;${styles}"
|
|
446
|
+
>
|
|
447
|
+
${childHtml}
|
|
448
|
+
</td>`;
|
|
405
449
|
}
|
|
406
450
|
}
|
|
407
451
|
else {
|
|
408
|
-
|
|
452
|
+
// SAFE empty cell (keeps layout stable)
|
|
453
|
+
html += `
|
|
454
|
+
<td width="${Math.round(widthPercent)}%"
|
|
455
|
+
${responsive ? 'class="stack-column"' : ""}
|
|
456
|
+
style="vertical-align:top;">
|
|
457
|
+
</td>`;
|
|
409
458
|
}
|
|
410
459
|
}
|
|
411
460
|
html += "</tr>";
|
|
412
461
|
}
|
|
413
|
-
html +=
|
|
462
|
+
html += "</table><!--[if mso]></table><![endif]-->";
|
|
414
463
|
return html;
|
|
415
464
|
}
|
|
416
465
|
async function convertGridCellBlock(blockData, rootData, cellWidthPercent, parentCellWidthPx) {
|
|
417
466
|
const { style = {}, childrenIds = [], props = {} } = blockData.data;
|
|
467
|
+
const visibilityClass = (0, common_1.getVisibilityClass)(props);
|
|
418
468
|
const styles = buildStyles(style, {
|
|
419
469
|
perChanges: [],
|
|
420
470
|
pxChanges: allPxAttributes,
|
|
421
471
|
});
|
|
422
|
-
const
|
|
472
|
+
const parts = [];
|
|
473
|
+
// FIX: do NOT re-calc px based on parent → causes shrinking
|
|
474
|
+
const safeCellWidthPx = Math.max(parentCellWidthPx, 20);
|
|
423
475
|
for (const childId of childrenIds) {
|
|
424
476
|
const child = rootData[childId];
|
|
425
477
|
if (child) {
|
|
426
|
-
|
|
427
|
-
innerHtmlParts.push(await convertToHtml(child, rootData, cellWidthPx));
|
|
478
|
+
parts.push(await convertToHtml(child, rootData, safeCellWidthPx));
|
|
428
479
|
}
|
|
429
480
|
}
|
|
430
|
-
const cellContent = innerHtmlParts.join("");
|
|
431
481
|
return {
|
|
432
|
-
html:
|
|
482
|
+
html: parts.join(""),
|
|
433
483
|
styles,
|
|
434
484
|
};
|
|
435
485
|
}
|
|
@@ -494,116 +544,116 @@ async function convertVideoBlock(blockData, cellWidthInPx) {
|
|
|
494
544
|
const vmlTop = calculatedHeight / 2 - playIconHeight / 2;
|
|
495
545
|
const shouldHideInOutlook = hideOnDesktop;
|
|
496
546
|
const outlookVideoContent = shouldHideInOutlook
|
|
497
|
-
? `<!--[if !mso]><!-->
|
|
498
|
-
<v:group xmlns:v="urn:schemas-microsoft-com:vml"
|
|
499
|
-
coordsize="${innerContainerWidth},${calculatedHeight}"
|
|
500
|
-
href="${videoLink}"
|
|
501
|
-
style="width:${innerContainerWidth}px;height:${calculatedHeight}px;">
|
|
502
|
-
<v:rect fill="t" style="position:absolute;width:${innerContainerWidth}px;height:${calculatedHeight}px; stroked="t"
|
|
503
|
-
strokeweight="${borderWidth}px"
|
|
504
|
-
strokecolor="${borderColor}"
|
|
505
|
-
${borderRadius > 0 ? `arcsize="${Math.min(borderRadius / calculatedHeight, 1).toFixed(2)}"` : ""}
|
|
506
|
-
>
|
|
507
|
-
<v:fill src="${resolvedThumbnail}" type="frame" color="${style?.backgroundColor || "#FFFFFF"}"/>
|
|
508
|
-
</v:rect>
|
|
509
|
-
<v:shape type="#_x0000_t75"
|
|
510
|
-
style="position:absolute;
|
|
511
|
-
left:${vmlLeft.toFixed(1)}px;
|
|
512
|
-
top:${vmlTop.toFixed(1)}px;
|
|
513
|
-
width:${playIconWidth}px;
|
|
514
|
-
height:${playIconHeight}px;"
|
|
515
|
-
alt="Play" href="${videoLink}" title="${altText || "Video"}"
|
|
516
|
-
stroked="f" filled="t">
|
|
517
|
-
<v:imagedata src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png" />
|
|
518
|
-
</v:shape>
|
|
519
|
-
</v:group>
|
|
547
|
+
? `<!--[if !mso]><!-->
|
|
548
|
+
<v:group xmlns:v="urn:schemas-microsoft-com:vml"
|
|
549
|
+
coordsize="${innerContainerWidth},${calculatedHeight}"
|
|
550
|
+
href="${videoLink}"
|
|
551
|
+
style="width:${innerContainerWidth}px;height:${calculatedHeight}px;">
|
|
552
|
+
<v:rect fill="t" style="position:absolute;width:${innerContainerWidth}px;height:${calculatedHeight}px;" stroked="t"
|
|
553
|
+
strokeweight="${borderWidth}px"
|
|
554
|
+
strokecolor="${borderColor}"
|
|
555
|
+
${borderRadius > 0 ? `arcsize="${Math.min(borderRadius / calculatedHeight, 1).toFixed(2)}"` : ""}
|
|
556
|
+
>
|
|
557
|
+
<v:fill src="${resolvedThumbnail}" type="frame" color="${style?.backgroundColor || "#FFFFFF"}"/>
|
|
558
|
+
</v:rect>
|
|
559
|
+
<v:shape type="#_x0000_t75"
|
|
560
|
+
style="position:absolute;
|
|
561
|
+
left:${vmlLeft.toFixed(1)}px;
|
|
562
|
+
top:${vmlTop.toFixed(1)}px;
|
|
563
|
+
width:${playIconWidth}px;
|
|
564
|
+
height:${playIconHeight}px;"
|
|
565
|
+
alt="Play" href="${videoLink}" title="${altText || "Video"}"
|
|
566
|
+
stroked="f" filled="t">
|
|
567
|
+
<v:imagedata src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png" />
|
|
568
|
+
</v:shape>
|
|
569
|
+
</v:group>
|
|
520
570
|
<!--<![endif]-->`
|
|
521
|
-
: `<!--[if mso]>
|
|
522
|
-
<v:group xmlns:v="urn:schemas-microsoft-com:vml"
|
|
523
|
-
coordsize="${innerContainerWidth},${calculatedHeight}"
|
|
524
|
-
href="${videoLink}"
|
|
525
|
-
style="width:${innerContainerWidth}px;height:${calculatedHeight}px;">
|
|
526
|
-
<v:rect fill="t" style="position:absolute;width:${innerContainerWidth}px;height:${calculatedHeight}px; stroked="t"
|
|
527
|
-
strokeweight="${borderWidth}px"
|
|
528
|
-
strokecolor="${borderColor}"
|
|
529
|
-
${borderRadius > 0 ? `arcsize="${Math.min(borderRadius / calculatedHeight, 1).toFixed(2)}"` : ""}
|
|
530
|
-
>
|
|
531
|
-
<v:fill src="${resolvedThumbnail}" type="frame" color="${style?.backgroundColor || "#FFFFFF"}"/>
|
|
532
|
-
</v:rect>
|
|
533
|
-
<v:shape type="#_x0000_t75"
|
|
534
|
-
style="position:absolute;
|
|
535
|
-
left:${vmlLeft.toFixed(1)}px;
|
|
536
|
-
top:${vmlTop.toFixed(1)}px;
|
|
537
|
-
width:${playIconWidth}px;
|
|
538
|
-
height:${playIconHeight}px;"
|
|
539
|
-
alt="Play" href="${videoLink}" title="${altText || "Video"}"
|
|
540
|
-
stroked="f" filled="t">
|
|
541
|
-
<v:imagedata src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png" />
|
|
542
|
-
</v:shape>
|
|
543
|
-
</v:group>
|
|
571
|
+
: `<!--[if mso]>
|
|
572
|
+
<v:group xmlns:v="urn:schemas-microsoft-com:vml"
|
|
573
|
+
coordsize="${innerContainerWidth},${calculatedHeight}"
|
|
574
|
+
href="${videoLink}"
|
|
575
|
+
style="width:${innerContainerWidth}px;height:${calculatedHeight}px;">
|
|
576
|
+
<v:rect fill="t" style="position:absolute;width:${innerContainerWidth}px;height:${calculatedHeight}px; stroked="t"
|
|
577
|
+
strokeweight="${borderWidth}px"
|
|
578
|
+
strokecolor="${borderColor}"
|
|
579
|
+
${borderRadius > 0 ? `arcsize="${Math.min(borderRadius / calculatedHeight, 1).toFixed(2)}"` : ""}
|
|
580
|
+
>
|
|
581
|
+
<v:fill src="${resolvedThumbnail}" type="frame" color="${style?.backgroundColor || "#FFFFFF"}"/>
|
|
582
|
+
</v:rect>
|
|
583
|
+
<v:shape type="#_x0000_t75"
|
|
584
|
+
style="position:absolute;
|
|
585
|
+
left:${vmlLeft.toFixed(1)}px;
|
|
586
|
+
top:${vmlTop.toFixed(1)}px;
|
|
587
|
+
width:${playIconWidth}px;
|
|
588
|
+
height:${playIconHeight}px;"
|
|
589
|
+
alt="Play" href="${videoLink}" title="${altText || "Video"}"
|
|
590
|
+
stroked="f" filled="t">
|
|
591
|
+
<v:imagedata src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png" />
|
|
592
|
+
</v:shape>
|
|
593
|
+
</v:group>
|
|
544
594
|
<![endif]-->`;
|
|
545
|
-
const nonOutlookVideoContent = `<!--[if !mso]><!-->
|
|
546
|
-
<table
|
|
547
|
-
width="${innerContainerWidth}"
|
|
548
|
-
cellpadding="0"
|
|
549
|
-
cellspacing="0"
|
|
550
|
-
border="0"
|
|
551
|
-
role="presentation"
|
|
552
|
-
align="${style?.textAlign || "left"}"
|
|
553
|
-
style="
|
|
554
|
-
max-width: ${innerContainerWidth}px;
|
|
555
|
-
width: 100%;
|
|
556
|
-
height: ${calculatedHeight}px;
|
|
557
|
-
background-color: ${style?.backgroundColor || "#FFFFFF"};
|
|
558
|
-
background-image: url('${resolvedThumbnail}');
|
|
559
|
-
background-size:
|
|
560
|
-
background-position: center;
|
|
561
|
-
background-repeat: no-repeat;
|
|
562
|
-
box-sizing: border-box;
|
|
563
|
-
border: ${borderWidth}px ${style?.borderStyle || "solid"} ${borderColor};
|
|
564
|
-
border-radius: ${borderRadius}px;
|
|
565
|
-
"
|
|
566
|
-
>
|
|
567
|
-
<tr>
|
|
568
|
-
<td style="padding: 0; height: ${calculatedHeight}px; text-align: center; vertical-align: middle;" valign="middle">
|
|
569
|
-
<a href="${videoLink}" target="_blank" style="display:inline-block; border: 0; outline: none; text-decoration: none;">
|
|
570
|
-
<img
|
|
571
|
-
src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png"
|
|
572
|
-
width="${playIconWidth}"
|
|
573
|
-
alt="Play"
|
|
574
|
-
style="display: block;
|
|
575
|
-
border: 0;
|
|
576
|
-
outline: none;
|
|
577
|
-
text-decoration: none;
|
|
578
|
-
height: auto;"
|
|
579
|
-
/>
|
|
580
|
-
</a>
|
|
581
|
-
</td>
|
|
582
|
-
</tr>
|
|
583
|
-
</table>
|
|
595
|
+
const nonOutlookVideoContent = `<!--[if !mso]><!-->
|
|
596
|
+
<table
|
|
597
|
+
width="${innerContainerWidth}"
|
|
598
|
+
cellpadding="0"
|
|
599
|
+
cellspacing="0"
|
|
600
|
+
border="0"
|
|
601
|
+
role="presentation"
|
|
602
|
+
align="${style?.textAlign || "left"}"
|
|
603
|
+
style="
|
|
604
|
+
max-width: ${innerContainerWidth}px;
|
|
605
|
+
width: 100%;
|
|
606
|
+
height: ${calculatedHeight}px;
|
|
607
|
+
background-color: ${style?.backgroundColor || "#FFFFFF"};
|
|
608
|
+
background-image: url('${resolvedThumbnail}');
|
|
609
|
+
background-size: contain;
|
|
610
|
+
background-position: center;
|
|
611
|
+
background-repeat: no-repeat;
|
|
612
|
+
box-sizing: border-box;
|
|
613
|
+
border: ${borderWidth}px ${style?.borderStyle || "solid"} ${borderColor};
|
|
614
|
+
border-radius: ${borderRadius}px;
|
|
615
|
+
"
|
|
616
|
+
>
|
|
617
|
+
<tr>
|
|
618
|
+
<td style="padding: 0; height: ${calculatedHeight}px; text-align: center; vertical-align: middle;" valign="middle">
|
|
619
|
+
<a href="${videoLink}" target="_blank" style="display:inline-block; border: 0; outline: none; text-decoration: none;">
|
|
620
|
+
<img
|
|
621
|
+
src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png"
|
|
622
|
+
width="${playIconWidth}"
|
|
623
|
+
alt="Play"
|
|
624
|
+
style="display: block;
|
|
625
|
+
border: 0;
|
|
626
|
+
outline: none;
|
|
627
|
+
text-decoration: none;
|
|
628
|
+
height: auto;"
|
|
629
|
+
/>
|
|
630
|
+
</a>
|
|
631
|
+
</td>
|
|
632
|
+
</tr>
|
|
633
|
+
</table>
|
|
584
634
|
<!--<![endif]-->`;
|
|
585
635
|
const videoContent = `${outlookVideoContent}${nonOutlookVideoContent}`;
|
|
586
|
-
const wrapperHtml = `
|
|
587
|
-
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="margin:0; padding:0; border-collapse: collapse;" class="${visibilityClass}">
|
|
588
|
-
<tr>
|
|
589
|
-
<td align="${style?.textAlign || "left"}" style="padding:0; ${outerContainerStyles}">
|
|
590
|
-
<table border="0" cellpadding="0" cellspacing="0" role="presentation"
|
|
591
|
-
align="${style?.textAlign || "left"}"
|
|
592
|
-
style="
|
|
593
|
-
margin:0;
|
|
594
|
-
max-width:${cellWidthInPx}px;
|
|
595
|
-
width:${percentWidth};
|
|
596
|
-
border-collapse:collapse;
|
|
597
|
-
">
|
|
598
|
-
<tr>
|
|
599
|
-
<td align="${style?.textAlign || "left"}" style="text-align:${style?.textAlign || "left"}; padding:0;">
|
|
600
|
-
${videoContent}
|
|
601
|
-
</td>
|
|
602
|
-
</tr>
|
|
603
|
-
</table>
|
|
604
|
-
</td>
|
|
605
|
-
</tr>
|
|
606
|
-
</table>
|
|
636
|
+
const wrapperHtml = `
|
|
637
|
+
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="margin:0; padding:0; border-collapse: collapse; max-width:600px;" class="${visibilityClass}">
|
|
638
|
+
<tr>
|
|
639
|
+
<td align="${style?.textAlign || "left"}" style="padding:0; ${outerContainerStyles}">
|
|
640
|
+
<table border="0" cellpadding="0" cellspacing="0" role="presentation"
|
|
641
|
+
align="${style?.textAlign || "left"}"
|
|
642
|
+
style="
|
|
643
|
+
margin:0;
|
|
644
|
+
max-width:${cellWidthInPx}px;
|
|
645
|
+
width:${percentWidth};
|
|
646
|
+
border-collapse:collapse;
|
|
647
|
+
">
|
|
648
|
+
<tr>
|
|
649
|
+
<td align="${style?.textAlign || "left"}" style="text-align:${style?.textAlign || "left"}; padding:0;">
|
|
650
|
+
${videoContent}
|
|
651
|
+
</td>
|
|
652
|
+
</tr>
|
|
653
|
+
</table>
|
|
654
|
+
</td>
|
|
655
|
+
</tr>
|
|
656
|
+
</table>
|
|
607
657
|
`;
|
|
608
658
|
return wrapperHtml;
|
|
609
659
|
}
|
|
@@ -623,154 +673,6 @@ function computeArcSize(borderRadius, widthPx) {
|
|
|
623
673
|
const px = parseFloat(s.replace("px", "")) || 0;
|
|
624
674
|
return Math.min(px / widthPx, 1).toFixed(2);
|
|
625
675
|
}
|
|
626
|
-
// ---------- Updated convertShapeBlock function ----------
|
|
627
|
-
// async function convertShapeBlock(blockData: IBlockData) {
|
|
628
|
-
// const { style, props } = blockData.data;
|
|
629
|
-
// const { shape, text, imageUrl } = props as any;
|
|
630
|
-
// const {
|
|
631
|
-
// width = "100",
|
|
632
|
-
// height = "150",
|
|
633
|
-
// padding = {},
|
|
634
|
-
// backgroundColor = "#2F80ED",
|
|
635
|
-
// borderRadius,
|
|
636
|
-
// borderWidth = 0,
|
|
637
|
-
// borderStyle = "solid",
|
|
638
|
-
// borderColor = "transparent",
|
|
639
|
-
// customCss,
|
|
640
|
-
// shapeColor,
|
|
641
|
-
// alignment = "left",
|
|
642
|
-
// msoBakeImageWithText,
|
|
643
|
-
// color = "#000000",
|
|
644
|
-
// fontSize = 14,
|
|
645
|
-
// verticalAlign = "center",
|
|
646
|
-
// } = style || {};
|
|
647
|
-
// const borderRadiusMap: Record<string, string> = {
|
|
648
|
-
// rectangle: "0",
|
|
649
|
-
// rounded: "10px",
|
|
650
|
-
// circle: "50%",
|
|
651
|
-
// oval: "50%",
|
|
652
|
-
// };
|
|
653
|
-
// let resolvedBorderRadius = borderRadius || borderRadiusMap[shape] || "0";
|
|
654
|
-
// let resolvedWidthPx =
|
|
655
|
-
// typeof width === "number"
|
|
656
|
-
// ? width
|
|
657
|
-
// : parseInt(width.toString().replace("px", ""), 10) || 100;
|
|
658
|
-
// let resolvedHeightPx =
|
|
659
|
-
// typeof height === "number"
|
|
660
|
-
// ? height
|
|
661
|
-
// : parseInt(height.toString().replace("px", ""), 10) || 150;
|
|
662
|
-
// // --- Shape specific constraints ---
|
|
663
|
-
// if (shape === "circle") {
|
|
664
|
-
// const side = Math.min(resolvedWidthPx, resolvedHeightPx);
|
|
665
|
-
// resolvedWidthPx = side;
|
|
666
|
-
// resolvedHeightPx = side;
|
|
667
|
-
// resolvedBorderRadius = "50%";
|
|
668
|
-
// } else if (shape === "oval") {
|
|
669
|
-
// resolvedBorderRadius = "50% / 50%";
|
|
670
|
-
// }
|
|
671
|
-
// const finalBackgroundColor = shapeColor || backgroundColor;
|
|
672
|
-
// const alignmentStyles = {
|
|
673
|
-
// left: "margin-right:auto;margin-left:0;",
|
|
674
|
-
// center: "margin-left:auto;margin-right:auto;",
|
|
675
|
-
// right: "margin-left:auto;margin-right:0;",
|
|
676
|
-
// };
|
|
677
|
-
// const alignmentStyle =
|
|
678
|
-
// alignmentStyles[alignment as keyof typeof alignmentStyles] || "";
|
|
679
|
-
// const verticalAlignStyles = {
|
|
680
|
-
// top: "align-items:flex-start;padding-top:8px;",
|
|
681
|
-
// center: "align-items:center;",
|
|
682
|
-
// bottom: "align-items:flex-end;padding-bottom:8px;",
|
|
683
|
-
// };
|
|
684
|
-
// const verticalAlignStyle =
|
|
685
|
-
// verticalAlignStyles[verticalAlign as keyof typeof verticalAlignStyles] ||
|
|
686
|
-
// verticalAlignStyles.center;
|
|
687
|
-
// // Text styling (safe across clients)
|
|
688
|
-
// const textSizeStyle = `font-size:${fontSize}px;line-height:1.3;word-break:break-word;overflow-wrap:break-word;text-align:center;color:${color};`;
|
|
689
|
-
// // ============================
|
|
690
|
-
// // Modern HTML (non-MSO)
|
|
691
|
-
// // ============================
|
|
692
|
-
// let nonMsoContent = "";
|
|
693
|
-
// if (imageUrl && text) {
|
|
694
|
-
// nonMsoContent = `
|
|
695
|
-
// <div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
696
|
-
// border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
697
|
-
// border-radius:${resolvedBorderRadius};
|
|
698
|
-
// background:${finalBackgroundColor} url('${imageUrl}') center/cover no-repeat;
|
|
699
|
-
// overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
700
|
-
// <div style="width:100%;height:100%;display:flex;${verticalAlignStyle}justify-content:center;overflow:hidden;">
|
|
701
|
-
// <div style="${textSizeStyle}padding:6px;max-width:90%;-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;">
|
|
702
|
-
// ${text}
|
|
703
|
-
// </div>
|
|
704
|
-
// </div>
|
|
705
|
-
// </div>`;
|
|
706
|
-
// } else if (imageUrl) {
|
|
707
|
-
// nonMsoContent = `
|
|
708
|
-
// <div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
709
|
-
// border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
710
|
-
// border-radius:${resolvedBorderRadius};
|
|
711
|
-
// overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
712
|
-
// <img src="${imageUrl}" alt="${text || "shape image"}"
|
|
713
|
-
// width="${resolvedWidthPx}" height="${resolvedHeightPx}"
|
|
714
|
-
// style="width:100%;height:100%;object-fit:cover;border-radius:${resolvedBorderRadius};display:block;" />
|
|
715
|
-
// </div>`;
|
|
716
|
-
// } else {
|
|
717
|
-
// const circlePadding =
|
|
718
|
-
// shape === "circle" ? Math.round(resolvedHeightPx * 0.15) : 8;
|
|
719
|
-
// nonMsoContent = `
|
|
720
|
-
// <div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
721
|
-
// background:${finalBackgroundColor};
|
|
722
|
-
// border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
723
|
-
// border-radius:${resolvedBorderRadius};
|
|
724
|
-
// overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
725
|
-
// <div style="width:100%;height:100%;display:flex;${verticalAlignStyle}justify-content:center;padding:${circlePadding}px;box-sizing:border-box;">
|
|
726
|
-
// <div style="${textSizeStyle}max-width:90%;overflow:hidden;">
|
|
727
|
-
// ${text || ""}
|
|
728
|
-
// </div>
|
|
729
|
-
// </div>
|
|
730
|
-
// </div>`;
|
|
731
|
-
// }
|
|
732
|
-
// // ============================
|
|
733
|
-
// // Outlook (VML) version
|
|
734
|
-
// // ============================
|
|
735
|
-
// const outlookContent = await appendOutlookForShape(
|
|
736
|
-
// nonMsoContent,
|
|
737
|
-
// resolvedWidthPx,
|
|
738
|
-
// resolvedWidthPx,
|
|
739
|
-
// {
|
|
740
|
-
// shape,
|
|
741
|
-
// imageUrl,
|
|
742
|
-
// backgroundColor,
|
|
743
|
-
// shapeColor,
|
|
744
|
-
// borderWidth,
|
|
745
|
-
// borderColor,
|
|
746
|
-
// borderRadius: resolvedBorderRadius,
|
|
747
|
-
// heightPx: resolvedHeightPx,
|
|
748
|
-
// text,
|
|
749
|
-
// textColor: color,
|
|
750
|
-
// textSize: fontSize,
|
|
751
|
-
// verticalAlign,
|
|
752
|
-
// alignment,
|
|
753
|
-
// padding,
|
|
754
|
-
// msoBakeImageWithText,
|
|
755
|
-
// }
|
|
756
|
-
// );
|
|
757
|
-
// // ============================
|
|
758
|
-
// // Final combined block
|
|
759
|
-
// // ============================
|
|
760
|
-
// return `
|
|
761
|
-
// <table width="100%" style="border-collapse:collapse;table-layout:fixed;">
|
|
762
|
-
// <tr>
|
|
763
|
-
// <td style="padding:${padding.top || 0}px ${padding.right || 0}px ${
|
|
764
|
-
// padding.bottom || 0
|
|
765
|
-
// }px ${padding.left || 0}px;text-align:${alignment};">
|
|
766
|
-
// ${outlookContent}
|
|
767
|
-
// <!--[if !mso]><!-->
|
|
768
|
-
// ${nonMsoContent}
|
|
769
|
-
// <!--<![endif]-->
|
|
770
|
-
// </td>
|
|
771
|
-
// </tr>
|
|
772
|
-
// </table>`;
|
|
773
|
-
// }
|
|
774
676
|
async function convertShapeBlock(blockData) {
|
|
775
677
|
const { style, props } = blockData.data;
|
|
776
678
|
const { shape, text, imageUrl } = props;
|
|
@@ -833,44 +735,44 @@ async function convertShapeBlock(blockData) {
|
|
|
833
735
|
let nonMsoContent = "";
|
|
834
736
|
// --- Case 1: Image + Text ---
|
|
835
737
|
if (imageUrl && text) {
|
|
836
|
-
nonMsoContent = `
|
|
837
|
-
<div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
838
|
-
border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
839
|
-
border-radius:${resolvedBorderRadius};
|
|
840
|
-
background:${finalBackgroundColor} url('${imageUrl}') center/cover no-repeat;
|
|
841
|
-
overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
842
|
-
<div style="width:100%;height:100%;display:flex;justify-content:${flexJustify};align-items:${flexAlign};overflow:hidden;padding:6px;box-sizing:border-box;">
|
|
843
|
-
<div style="${textSizeStyle}text-align:${textAlignStyle};max-width:90%;overflow:hidden;">
|
|
844
|
-
${text}
|
|
845
|
-
</div>
|
|
846
|
-
</div>
|
|
738
|
+
nonMsoContent = `
|
|
739
|
+
<div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
740
|
+
border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
741
|
+
border-radius:${resolvedBorderRadius};
|
|
742
|
+
background:${finalBackgroundColor} url('${imageUrl}') center/cover no-repeat;
|
|
743
|
+
overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
744
|
+
<div style="width:100%;height:100%;display:flex;justify-content:${flexJustify};align-items:${flexAlign};overflow:hidden;padding:6px;box-sizing:border-box;">
|
|
745
|
+
<div style="${textSizeStyle}text-align:${textAlignStyle};max-width:90%;overflow:hidden;">
|
|
746
|
+
${text}
|
|
747
|
+
</div>
|
|
748
|
+
</div>
|
|
847
749
|
</div>`;
|
|
848
750
|
}
|
|
849
751
|
// --- Case 2: Image only ---
|
|
850
752
|
else if (imageUrl) {
|
|
851
|
-
nonMsoContent = `
|
|
852
|
-
<div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
853
|
-
border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
854
|
-
border-radius:${resolvedBorderRadius};
|
|
855
|
-
overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
856
|
-
<img src="${imageUrl}" alt="${text || "shape image"}"
|
|
857
|
-
width="${resolvedWidthPx}" height="${resolvedHeightPx}"
|
|
858
|
-
style="width:100%;height:100%;object-fit:cover;border-radius:${resolvedBorderRadius};display:block;" />
|
|
753
|
+
nonMsoContent = `
|
|
754
|
+
<div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
755
|
+
border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
756
|
+
border-radius:${resolvedBorderRadius};
|
|
757
|
+
overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
758
|
+
<img src="${imageUrl}" alt="${text || "shape image"}"
|
|
759
|
+
width="${resolvedWidthPx}" height="${resolvedHeightPx}"
|
|
760
|
+
style="width:100%;height:100%;object-fit:cover;border-radius:${resolvedBorderRadius};display:block;" />
|
|
859
761
|
</div>`;
|
|
860
762
|
}
|
|
861
763
|
// --- Case 3: Text only ---
|
|
862
764
|
else {
|
|
863
|
-
nonMsoContent = `
|
|
864
|
-
<div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
865
|
-
background:${finalBackgroundColor};
|
|
866
|
-
border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
867
|
-
border-radius:${resolvedBorderRadius};
|
|
868
|
-
overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
869
|
-
<div style="width:100%;height:100%;display:flex;justify-content:${flexJustify};align-items:${flexAlign};padding:8px;box-sizing:border-box;">
|
|
870
|
-
<div style="${textSizeStyle}text-align:${textAlignStyle};max-width:90%;overflow:hidden;">
|
|
871
|
-
${text || ""}
|
|
872
|
-
</div>
|
|
873
|
-
</div>
|
|
765
|
+
nonMsoContent = `
|
|
766
|
+
<div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
767
|
+
background:${finalBackgroundColor};
|
|
768
|
+
border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
769
|
+
border-radius:${resolvedBorderRadius};
|
|
770
|
+
overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
771
|
+
<div style="width:100%;height:100%;display:flex;justify-content:${flexJustify};align-items:${flexAlign};padding:8px;box-sizing:border-box;">
|
|
772
|
+
<div style="${textSizeStyle}text-align:${textAlignStyle};max-width:90%;overflow:hidden;">
|
|
773
|
+
${text || ""}
|
|
774
|
+
</div>
|
|
775
|
+
</div>
|
|
874
776
|
</div>`;
|
|
875
777
|
}
|
|
876
778
|
// Outlook (VML) fallback
|
|
@@ -893,16 +795,16 @@ async function convertShapeBlock(blockData) {
|
|
|
893
795
|
msoBakeImageWithText,
|
|
894
796
|
}, visibilityClass);
|
|
895
797
|
// Combine into table wrapper
|
|
896
|
-
return `
|
|
897
|
-
<table width="100%" style="border-collapse:collapse;table-layout:fixed;" class="${visibilityClass}">
|
|
898
|
-
<tr>
|
|
899
|
-
<td style="padding:${padding.top || 0}px ${padding.right || 0}px ${padding.bottom || 0}px ${padding.left || 0}px;text-align:${alignment};">
|
|
900
|
-
${outlookContent}
|
|
901
|
-
<!--[if !mso]><!-->
|
|
902
|
-
${nonMsoContent}
|
|
903
|
-
<!--<![endif]-->
|
|
904
|
-
</td>
|
|
905
|
-
</tr>
|
|
798
|
+
return `
|
|
799
|
+
<table width="100%" style="border-collapse:collapse;table-layout:fixed;max-width:600px;" class="${visibilityClass}">
|
|
800
|
+
<tr>
|
|
801
|
+
<td style="padding:${padding.top || 0}px ${padding.right || 0}px ${padding.bottom || 0}px ${padding.left || 0}px;text-align:${alignment};">
|
|
802
|
+
${outlookContent}
|
|
803
|
+
<!--[if !mso]><!-->
|
|
804
|
+
${nonMsoContent}
|
|
805
|
+
<!--<![endif]-->
|
|
806
|
+
</td>
|
|
807
|
+
</tr>
|
|
906
808
|
</table>`;
|
|
907
809
|
}
|
|
908
810
|
// ---------- Updated VML builder ----------
|
|
@@ -935,24 +837,24 @@ function buildVMLShape({ shape, widthPx, heightPx, imageUrl, backgroundColor, bo
|
|
|
935
837
|
const safeFontSize = Math.max(Math.round(textSize), 10);
|
|
936
838
|
// Build the textbox with table/cell for reliable vertical centering in Outlook
|
|
937
839
|
const textboxMarkup = text && !msoHasBakedText
|
|
938
|
-
? `<v:textbox inset="6pt,6pt,6pt,6pt" style="mso-fit-shape-to-text:false;">
|
|
939
|
-
<div style="display:table;width:100%;height:100%;">
|
|
940
|
-
<div style="display:table-cell;vertical-align:${vAlign};text-align:${hAlign};padding:0 6px;">
|
|
941
|
-
<div style="color:${textColor};font-family:Arial, sans-serif;font-size:${safeFontSize}px;line-height:1.3;word-wrap:break-word;">
|
|
942
|
-
${text}
|
|
943
|
-
</div>
|
|
944
|
-
</div>
|
|
945
|
-
</div>
|
|
840
|
+
? `<v:textbox inset="6pt,6pt,6pt,6pt" style="mso-fit-shape-to-text:false;">
|
|
841
|
+
<div style="display:table;width:100%;height:100%;">
|
|
842
|
+
<div style="display:table-cell;vertical-align:${vAlign};text-align:${hAlign};padding:0 6px;">
|
|
843
|
+
<div style="color:${textColor};font-family:Arial, sans-serif;font-size:${safeFontSize}px;line-height:1.3;word-wrap:break-word;">
|
|
844
|
+
${text}
|
|
845
|
+
</div>
|
|
846
|
+
</div>
|
|
847
|
+
</div>
|
|
946
848
|
</v:textbox>`
|
|
947
849
|
: `<v:textbox inset="0,0,0,0"><div style="display:none;">.</div></v:textbox>`;
|
|
948
850
|
// Return VML shape
|
|
949
|
-
return `
|
|
950
|
-
<v:${tag} xmlns:v="urn:schemas-microsoft-com:vml"
|
|
951
|
-
style="width:${widthPx}px;height:${heightPx}px;display:inline-block;"
|
|
952
|
-
${borderAttrs}
|
|
953
|
-
fill="true" fillcolor="${fillColor}"${extraAttr}>
|
|
954
|
-
${fillMarkup}
|
|
955
|
-
${textboxMarkup}
|
|
851
|
+
return `
|
|
852
|
+
<v:${tag} xmlns:v="urn:schemas-microsoft-com:vml"
|
|
853
|
+
style="width:${widthPx}px;height:${heightPx}px;display:inline-block;"
|
|
854
|
+
${borderAttrs}
|
|
855
|
+
fill="true" fillcolor="${fillColor}"${extraAttr}>
|
|
856
|
+
${fillMarkup}
|
|
857
|
+
${textboxMarkup}
|
|
956
858
|
</v:${tag}>`;
|
|
957
859
|
}
|
|
958
860
|
function appendOutlookForShape(content, outerContainerWidth, innerContainerWidth, opts, visibilityClass) {
|
|
@@ -980,28 +882,28 @@ function appendOutlookForShape(content, outerContainerWidth, innerContainerWidth
|
|
|
980
882
|
const shouldHideInOutlook = visibilityClass.includes("hide-desktop");
|
|
981
883
|
// Fix: Properly handle Outlook visibility with conditional comments
|
|
982
884
|
if (shouldHideInOutlook) {
|
|
983
|
-
return `<!--[if !mso]><!-->
|
|
984
|
-
<table align="${align}" border="0" cellpadding="0" cellspacing="0"
|
|
985
|
-
style="width:${widthPx}px;height:${heightPx}px;border-collapse:collapse;" class="${visibilityClass}">
|
|
986
|
-
<tr>
|
|
987
|
-
<td valign="${valign}"
|
|
988
|
-
style="padding:${pad.top || 0}px ${pad.right || 0}px ${pad.bottom || 0}px ${pad.left || 0}px;">
|
|
989
|
-
${vml}
|
|
990
|
-
</td>
|
|
991
|
-
</tr>
|
|
992
|
-
</table>
|
|
885
|
+
return `<!--[if !mso]><!-->
|
|
886
|
+
<table align="${align}" border="0" cellpadding="0" cellspacing="0"
|
|
887
|
+
style="width:${widthPx}px;height:${heightPx}px;border-collapse:collapse;" class="${visibilityClass}">
|
|
888
|
+
<tr>
|
|
889
|
+
<td valign="${valign}"
|
|
890
|
+
style="padding:${pad.top || 0}px ${pad.right || 0}px ${pad.bottom || 0}px ${pad.left || 0}px;">
|
|
891
|
+
${vml}
|
|
892
|
+
</td>
|
|
893
|
+
</tr>
|
|
894
|
+
</table>
|
|
993
895
|
<!--<![endif]-->`;
|
|
994
896
|
}
|
|
995
|
-
return `<!--[if mso]>
|
|
996
|
-
<table align="${align}" border="0" cellpadding="0" cellspacing="0"
|
|
997
|
-
style="width:${widthPx}px;height:${heightPx}px;border-collapse:collapse;" class="${visibilityClass}">
|
|
998
|
-
<tr>
|
|
999
|
-
<td valign="${valign}"
|
|
1000
|
-
style="padding:${pad.top || 0}px ${pad.right || 0}px ${pad.bottom || 0}px ${pad.left || 0}px;">
|
|
1001
|
-
${vml}
|
|
1002
|
-
</td>
|
|
1003
|
-
</tr>
|
|
1004
|
-
</table>
|
|
897
|
+
return `<!--[if mso]>
|
|
898
|
+
<table align="${align}" border="0" cellpadding="0" cellspacing="0"
|
|
899
|
+
style="width:${widthPx}px;height:${heightPx}px;border-collapse:collapse;" class="${visibilityClass}">
|
|
900
|
+
<tr>
|
|
901
|
+
<td valign="${valign}"
|
|
902
|
+
style="padding:${pad.top || 0}px ${pad.right || 0}px ${pad.bottom || 0}px ${pad.left || 0}px;">
|
|
903
|
+
${vml}
|
|
904
|
+
</td>
|
|
905
|
+
</tr>
|
|
906
|
+
</table>
|
|
1005
907
|
<![endif]-->`;
|
|
1006
908
|
}
|
|
1007
909
|
function convertVerticalDividerBlockToHtml(blockData) {
|
|
@@ -1014,19 +916,19 @@ function convertVerticalDividerBlockToHtml(blockData) {
|
|
|
1014
916
|
pxChanges: allPxAttributes,
|
|
1015
917
|
});
|
|
1016
918
|
// Outlook-safe vertical divider
|
|
1017
|
-
const dividerContent = `
|
|
1018
|
-
<table cellpadding="0" cellspacing="0" border="0" align="center" style="width:auto; ${convertedStyle}">
|
|
1019
|
-
<tr>
|
|
1020
|
-
<td style="vertical-align: middle; text-align: center;">
|
|
1021
|
-
<!--[if mso | IE]>
|
|
1022
|
-
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fillcolor="${dividerColor}" style="width:${width}px;height:${height}px;" stroke="f"></v:rect>
|
|
1023
|
-
<![endif]-->
|
|
1024
|
-
<!--[if !mso]><!-- -->
|
|
1025
|
-
<div style="display:inline-block;width:${width}px;height:${height}px;background:${dividerColor};line-height:0;font-size:0;"> </div>
|
|
1026
|
-
<!--<![endif]-->
|
|
1027
|
-
</td>
|
|
1028
|
-
</tr>
|
|
1029
|
-
</table>
|
|
919
|
+
const dividerContent = `
|
|
920
|
+
<table cellpadding="0" cellspacing="0" border="0" align="center" style="width:auto; ${convertedStyle}">
|
|
921
|
+
<tr>
|
|
922
|
+
<td style="vertical-align: middle; text-align: center;">
|
|
923
|
+
<!--[if mso | IE]>
|
|
924
|
+
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fillcolor="${dividerColor}" style="width:${width}px;height:${height}px;" stroke="f"></v:rect>
|
|
925
|
+
<![endif]-->
|
|
926
|
+
<!--[if !mso]><!-- -->
|
|
927
|
+
<div style="display:inline-block;width:${width}px;height:${height}px;background:${dividerColor};line-height:0;font-size:0;"> </div>
|
|
928
|
+
<!--<![endif]-->
|
|
929
|
+
</td>
|
|
930
|
+
</tr>
|
|
931
|
+
</table>
|
|
1030
932
|
`;
|
|
1031
933
|
return appendOutlookSupport(dividerContent, convertedStyle, visibilityClass);
|
|
1032
934
|
}
|
package/package.json
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "email-builder-utils",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"main": "dist/index.js",
|
|
5
|
-
"types": "dist/index.d.ts",
|
|
6
|
-
"files": [
|
|
7
|
-
"dist"
|
|
8
|
-
],
|
|
9
|
-
"scripts": {
|
|
10
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
-
"build": "tsc",
|
|
12
|
-
"start": "npm run build && node dist/index.js"
|
|
13
|
-
},
|
|
14
|
-
"repository": {
|
|
15
|
-
"type": "git",
|
|
16
|
-
"url": "git+https://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@github.com/Biztecno-Infra/email-builder-utils.git"
|
|
17
|
-
},
|
|
18
|
-
"author": "",
|
|
19
|
-
"license": "ISC",
|
|
20
|
-
"bugs": {
|
|
21
|
-
"url": "https://github.com/Biztecno-Infra/email-builder-utils/issues"
|
|
22
|
-
},
|
|
23
|
-
"homepage": "https://github.com/Biztecno-Infra/email-builder-utils#readme",
|
|
24
|
-
"description": "",
|
|
25
|
-
"devDependencies": {
|
|
26
|
-
"@types/node": "^22.13.10",
|
|
27
|
-
"@types/pngjs": "^6.0.5",
|
|
28
|
-
"typescript": "^5.8.2"
|
|
29
|
-
},
|
|
30
|
-
"dependencies": {
|
|
31
|
-
"jimp": "^1.6.0"
|
|
32
|
-
}
|
|
33
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "email-builder-utils",
|
|
3
|
+
"version": "1.1.35",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "npm run build && node dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://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@github.com/Biztecno-Infra/email-builder-utils.git"
|
|
17
|
+
},
|
|
18
|
+
"author": "",
|
|
19
|
+
"license": "ISC",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/Biztecno-Infra/email-builder-utils/issues"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/Biztecno-Infra/email-builder-utils#readme",
|
|
24
|
+
"description": "",
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "^22.13.10",
|
|
27
|
+
"@types/pngjs": "^6.0.5",
|
|
28
|
+
"typescript": "^5.8.2"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"jimp": "^1.6.0"
|
|
32
|
+
}
|
|
33
|
+
}
|