email-builder-utils 1.1.42 → 1.1.45
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 +90 -83
- package/dist/utils/jsonToHTML.d.ts +1 -1
- package/dist/utils/jsonToHTML.d.ts.map +1 -1
- package/dist/utils/jsonToHTML.js +701 -500
- package/dist/utils/outlookSupport.d.ts +210 -0
- package/dist/utils/outlookSupport.d.ts.map +1 -0
- package/dist/utils/outlookSupport.js +479 -0
- package/package.json +34 -33
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.tableCommonStyle = void 0;
|
|
18
|
+
exports.computeArcSize = computeArcSize;
|
|
19
|
+
exports.shouldHideInOutlook = shouldHideInOutlook;
|
|
20
|
+
exports.buildOutlookGridTable = buildOutlookGridTable;
|
|
21
|
+
exports.buildOutlookGridCell = buildOutlookGridCell;
|
|
22
|
+
exports.buildOutlookEmptyCell = buildOutlookEmptyCell;
|
|
23
|
+
exports.buildOutlookVMLImage = buildOutlookVMLImage;
|
|
24
|
+
exports.buildOutlookVMLButton = buildOutlookVMLButton;
|
|
25
|
+
exports.buildVMLShape = buildVMLShape;
|
|
26
|
+
exports.buildOutlookShapeWrapper = buildOutlookShapeWrapper;
|
|
27
|
+
exports.buildOutlookVMLVideo = buildOutlookVMLVideo;
|
|
28
|
+
exports.buildOutlookVMLVDivider = buildOutlookVMLVDivider;
|
|
29
|
+
exports.wrapNonOutlookContent = wrapNonOutlookContent;
|
|
30
|
+
exports.buildOutlookWrapperTable = buildOutlookWrapperTable;
|
|
31
|
+
exports.buildOutlookImageWrapper = buildOutlookImageWrapper;
|
|
32
|
+
exports.buildOutlookButtonWrapper = buildOutlookButtonWrapper;
|
|
33
|
+
exports.buildOutlookVideoWrapper = buildOutlookVideoWrapper;
|
|
34
|
+
exports.buildOutlookVDividerWrapper = buildOutlookVDividerWrapper;
|
|
35
|
+
exports.buildOutlookShapeWrapperTable = buildOutlookShapeWrapperTable;
|
|
36
|
+
exports.buildOutlookGridWrapper = buildOutlookGridWrapper;
|
|
37
|
+
exports.buildOutlookGridRow = buildOutlookGridRow;
|
|
38
|
+
exports.buildOutlookGridCellWrapper = buildOutlookGridCellWrapper;
|
|
39
|
+
exports.buildOutlookEmptyCellWrapper = buildOutlookEmptyCellWrapper;
|
|
40
|
+
const jimp_1 = require("jimp");
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// OUTLOOK SUPPORT UTILITIES
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// These functions handle Microsoft Outlook-specific VML rendering and
|
|
45
|
+
// conditional comments for email HTML compatibility.
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// ---------- Helper: Compute arc size for rounded shapes ----------
|
|
48
|
+
function computeArcSize(borderRadius, widthPx) {
|
|
49
|
+
if (!borderRadius)
|
|
50
|
+
return "0";
|
|
51
|
+
if (typeof borderRadius === "number")
|
|
52
|
+
return Math.min(borderRadius / widthPx, 1).toFixed(2);
|
|
53
|
+
const s = borderRadius.toString().trim();
|
|
54
|
+
if (s.endsWith("%")) {
|
|
55
|
+
const pct = parseFloat(s.replace("%", "")) || 0;
|
|
56
|
+
return Math.min(pct / 100, 1).toFixed(2);
|
|
57
|
+
}
|
|
58
|
+
const px = parseFloat(s.replace("px", "")) || 0;
|
|
59
|
+
return Math.min(px / widthPx, 1).toFixed(2);
|
|
60
|
+
}
|
|
61
|
+
// ---------- Helper: Check if should hide in Outlook ----------
|
|
62
|
+
function shouldHideInOutlook(visibilityClass) {
|
|
63
|
+
return visibilityClass.includes("hide-desktop");
|
|
64
|
+
}
|
|
65
|
+
function buildOutlookGridTable(options) {
|
|
66
|
+
const { columnGap, gridVisibilityClass, tableStyles, content } = options;
|
|
67
|
+
// Outlook needs explicit table layout and width attributes
|
|
68
|
+
// For MSO, we use a fixed width table to prevent overflow issues
|
|
69
|
+
// For non-MSO, we use 100% with max-width for responsiveness
|
|
70
|
+
return `<!--[if mso]>
|
|
71
|
+
<table border="0" cellpadding="0" cellspacing="${columnGap}" width="600"
|
|
72
|
+
style="border-collapse:separate;border-spacing:${columnGap}px;${tableStyles};mso-table-lspace:0;mso-table-rspace:0;"
|
|
73
|
+
class="${gridVisibilityClass}">
|
|
74
|
+
<![endif]-->
|
|
75
|
+
<!--[if !mso]><!-->
|
|
76
|
+
<table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%"
|
|
77
|
+
role="presentation"
|
|
78
|
+
style="border-collapse:separate;border-spacing:${columnGap}px; ${tableStyles}; max-width:600px;overflow:hidden;"
|
|
79
|
+
class="${gridVisibilityClass}">
|
|
80
|
+
<!--<![endif]-->
|
|
81
|
+
${content}
|
|
82
|
+
</table>`;
|
|
83
|
+
}
|
|
84
|
+
function buildOutlookGridCell(options) {
|
|
85
|
+
const { widthPercent, widthPx, verticalAlign, visibilityClass, responsive, styles, content, } = options;
|
|
86
|
+
// Outlook needs explicit pixel width on cells, not just percentages
|
|
87
|
+
return `<td
|
|
88
|
+
width="${Math.round(widthPx)}"
|
|
89
|
+
class="${[responsive ? "stack-column" : "", visibilityClass]
|
|
90
|
+
.filter(Boolean)
|
|
91
|
+
.join(" ")}"
|
|
92
|
+
style="vertical-align:${verticalAlign};word-break:break-word;${styles}">
|
|
93
|
+
${content}
|
|
94
|
+
</td>`;
|
|
95
|
+
}
|
|
96
|
+
function buildOutlookEmptyCell(options) {
|
|
97
|
+
const { widthPercent, widthPx, responsive } = options;
|
|
98
|
+
// Safe empty cell with explicit pixel width for Outlook
|
|
99
|
+
return `<td width="${Math.round(widthPx)}"
|
|
100
|
+
${responsive ? 'class="stack-column"' : ""}
|
|
101
|
+
style="vertical-align:top;"> </td>`;
|
|
102
|
+
}
|
|
103
|
+
async function buildOutlookVMLImage(options) {
|
|
104
|
+
const { imageUrl, outerContainerWidth, innerContainerWidth, style = {} } = options;
|
|
105
|
+
const image = await jimp_1.Jimp.read(imageUrl);
|
|
106
|
+
const originalWidth = image.bitmap.width;
|
|
107
|
+
const originalHeight = image.bitmap.height;
|
|
108
|
+
// Use inner container width for proper scaling
|
|
109
|
+
const widthScalingFactor = Math.min(innerContainerWidth / originalWidth, 1);
|
|
110
|
+
const scaledWidth = Math.round(originalWidth * widthScalingFactor);
|
|
111
|
+
const scaledHeight = Math.round(originalHeight * widthScalingFactor);
|
|
112
|
+
const borderWidth = parseInt(style?.borderWidth) || 0;
|
|
113
|
+
const borderColor = style?.borderColor || "transparent";
|
|
114
|
+
const borderRadius = parseInt(style?.borderRadius) || 0;
|
|
115
|
+
const useRoundRect = borderRadius > 0;
|
|
116
|
+
const arcsize = useRoundRect
|
|
117
|
+
? Math.min(borderRadius / scaledHeight, 1).toFixed(2)
|
|
118
|
+
: "";
|
|
119
|
+
const borderAttributes = borderWidth > 0
|
|
120
|
+
? `strokeweight="${borderWidth}px" strokecolor="${borderColor}"`
|
|
121
|
+
: `stroked="false"`;
|
|
122
|
+
return `<!--[if mso]>
|
|
123
|
+
<v:${useRoundRect ? "roundrect" : "rect"} xmlns:v="urn:schemas-microsoft-com:vml"
|
|
124
|
+
style="width:${scaledWidth}px;height:${scaledHeight}px;max-width:${scaledWidth}px;"
|
|
125
|
+
${borderAttributes}
|
|
126
|
+
${useRoundRect ? `arcsize="${arcsize}"` : ""}
|
|
127
|
+
fill="true" fillcolor="none">
|
|
128
|
+
<v:fill src="${imageUrl}" type="frame" />
|
|
129
|
+
<v:textbox inset="0,0,0,0"><div style="display:none;mso-hide:all;">.</div></v:textbox>
|
|
130
|
+
</v:${useRoundRect ? "roundrect" : "rect"}>
|
|
131
|
+
<![endif]-->`;
|
|
132
|
+
}
|
|
133
|
+
function buildOutlookVMLButton(options) {
|
|
134
|
+
const { navigateToUrl, text, buttonStyle: { width = 200, height = 44, borderRadius = 0, borderColor = "transparent", borderWidth = 0, buttonColor = "none", buttonPadding = { top: 0, bottom: 0, left: 0, right: 0 }, color = "#000000", fontFamily = "Arial, sans-serif", fontSize = 16, fontWeight = 400, }, } = options;
|
|
135
|
+
const borderAttributes = borderWidth > 0
|
|
136
|
+
? `strokeweight="${borderWidth}px" strokecolor="${borderColor}"`
|
|
137
|
+
: `stroked="false"`;
|
|
138
|
+
return `
|
|
139
|
+
<!--[if mso]>
|
|
140
|
+
<v:${borderRadius ? "roundrect" : "rect"} xmlns:v="urn:schemas-microsoft-com:vml" href="${navigateToUrl}"
|
|
141
|
+
style="height:${height}px;v-text-anchor:middle;width:${width}px;mso-width-relative:page;"
|
|
142
|
+
arcsize="${borderRadius / height}" ${borderAttributes}
|
|
143
|
+
fillcolor="${buttonColor}">
|
|
144
|
+
<w:anchorlock/>
|
|
145
|
+
<v:textbox inset="${buttonPadding.top}px,${buttonPadding.left}px,${buttonPadding.bottom}px,${buttonPadding.right}px">
|
|
146
|
+
<center style="font-family:${fontFamily};font-size:${fontSize}px;font-weight:${fontWeight};color:${color};">
|
|
147
|
+
${text}
|
|
148
|
+
</center>
|
|
149
|
+
</v:textbox>
|
|
150
|
+
</v:${borderRadius ? "roundrect" : "rect"}>
|
|
151
|
+
<![endif]-->
|
|
152
|
+
`;
|
|
153
|
+
}
|
|
154
|
+
function buildVMLShape(options) {
|
|
155
|
+
const { shape, widthPx, heightPx, imageUrl, backgroundColor, shapeColor, borderWidth, borderColor, borderRadius, text, textColor = "#000000", textSize = 14, verticalAlign = "middle", textAlign = "center", msoHasBakedText = false, } = options;
|
|
156
|
+
const bw = borderWidth || 0;
|
|
157
|
+
const bc = borderColor || "transparent";
|
|
158
|
+
const borderAttrs = bw > 0 ? `strokeweight="${bw}px" strokecolor="${bc}"` : `stroked="false"`;
|
|
159
|
+
const fillColor = shapeColor || backgroundColor || "#2F80ED";
|
|
160
|
+
const fillMarkup = `<v:fill ${imageUrl ? `src="${imageUrl}" type="frame" aspect="atleast"` : ""} color="${fillColor}" />`;
|
|
161
|
+
let tag = "rect";
|
|
162
|
+
let extraAttr = "";
|
|
163
|
+
if (shape === "circle" || shape === "oval") {
|
|
164
|
+
tag = "oval";
|
|
165
|
+
}
|
|
166
|
+
else if (shape === "rounded") {
|
|
167
|
+
tag = "roundrect";
|
|
168
|
+
extraAttr = `arcsize="${computeArcSize(borderRadius, widthPx)}"`;
|
|
169
|
+
}
|
|
170
|
+
const vAlignMap = { top: "top", middle: "middle", bottom: "bottom" };
|
|
171
|
+
const hAlignMap = {
|
|
172
|
+
left: "left",
|
|
173
|
+
center: "center",
|
|
174
|
+
right: "right",
|
|
175
|
+
justify: "left",
|
|
176
|
+
};
|
|
177
|
+
const vAlign = vAlignMap[verticalAlign] || "middle";
|
|
178
|
+
const hAlign = hAlignMap[textAlign] || "center";
|
|
179
|
+
const safeFontSize = Math.max(Math.round(textSize), 10);
|
|
180
|
+
const textboxMarkup = text && !msoHasBakedText
|
|
181
|
+
? `<v:textbox inset="6pt,6pt,6pt,6pt" style="mso-fit-shape-to-text:false;">
|
|
182
|
+
<div style="display:table;width:100%;height:100%;">
|
|
183
|
+
<div style="display:table-cell;vertical-align:${vAlign};text-align:${hAlign};padding:0 6px;">
|
|
184
|
+
<div style="color:${textColor};font-family:Arial, sans-serif;font-size:${safeFontSize}px;line-height:1.3;word-wrap:break-word;">
|
|
185
|
+
${text}
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
</div>
|
|
189
|
+
</v:textbox>`
|
|
190
|
+
: `<v:textbox inset="0,0,0,0"><div style="display:none;mso-hide:all;">.</div></v:textbox>`;
|
|
191
|
+
return `
|
|
192
|
+
<v:${tag} xmlns:v="urn:schemas-microsoft-com:vml"
|
|
193
|
+
style="width:${widthPx}px;height:${heightPx}px;mso-width-relative:page;max-width:${widthPx}px;"
|
|
194
|
+
${borderAttrs}
|
|
195
|
+
fill="true" fillcolor="${fillColor}"${extraAttr}>
|
|
196
|
+
${fillMarkup}
|
|
197
|
+
${textboxMarkup}
|
|
198
|
+
</v:${tag}>`;
|
|
199
|
+
}
|
|
200
|
+
function buildOutlookShapeWrapper(options) {
|
|
201
|
+
const { visibilityClass, widthPx, heightPx, opts } = options;
|
|
202
|
+
const pad = opts.padding || {};
|
|
203
|
+
const align = opts.alignment || "left";
|
|
204
|
+
const valign = opts.verticalAlign || "middle";
|
|
205
|
+
const vml = buildVMLShape({
|
|
206
|
+
shape: opts.shape,
|
|
207
|
+
widthPx,
|
|
208
|
+
heightPx,
|
|
209
|
+
imageUrl: opts.msoBakeImageWithText || opts.imageUrl,
|
|
210
|
+
backgroundColor: opts.shapeColor || opts.backgroundColor,
|
|
211
|
+
borderWidth: opts.borderWidth,
|
|
212
|
+
borderColor: opts.borderColor,
|
|
213
|
+
borderRadius: opts.borderRadius,
|
|
214
|
+
text: opts.text,
|
|
215
|
+
textColor: opts.textColor,
|
|
216
|
+
textSize: opts.textSize,
|
|
217
|
+
verticalAlign: opts.verticalAlign,
|
|
218
|
+
textAlign: opts.textAlign,
|
|
219
|
+
msoHasBakedText: Boolean(opts.msoBakeImageWithText),
|
|
220
|
+
});
|
|
221
|
+
if (shouldHideInOutlook(visibilityClass)) {
|
|
222
|
+
return `<!--[if !mso]><!-->
|
|
223
|
+
<table align="${align}" border="0" cellpadding="0" cellspacing="0"
|
|
224
|
+
style="width:${widthPx}px;height:${heightPx}px;border-collapse:collapse;" class="${visibilityClass}">
|
|
225
|
+
<tr>
|
|
226
|
+
<td valign="${valign}"
|
|
227
|
+
style="padding:${pad.top || 0}px ${pad.right || 0}px ${pad.bottom || 0}px ${pad.left || 0}px;">
|
|
228
|
+
${vml}
|
|
229
|
+
</td>
|
|
230
|
+
</tr>
|
|
231
|
+
</table>
|
|
232
|
+
<!--<![endif]-->`;
|
|
233
|
+
}
|
|
234
|
+
return `<!--[if mso]>
|
|
235
|
+
<table align="${align}" border="0" cellpadding="0" cellspacing="0"
|
|
236
|
+
style="width:${widthPx}px;height:${heightPx}px;border-collapse:collapse;" class="${visibilityClass}">
|
|
237
|
+
<tr>
|
|
238
|
+
<td valign="${valign}"
|
|
239
|
+
style="padding:${pad.top || 0}px ${pad.right || 0}px ${pad.bottom || 0}px ${pad.left || 0}px;">
|
|
240
|
+
${vml}
|
|
241
|
+
</td>
|
|
242
|
+
</tr>
|
|
243
|
+
</table>
|
|
244
|
+
<![endif]-->`;
|
|
245
|
+
}
|
|
246
|
+
function buildOutlookVMLVideo(options) {
|
|
247
|
+
const { innerContainerWidth, calculatedHeight, videoLink, resolvedThumbnail, borderWidth, borderColor, borderRadius, altText, hideOnDesktop, } = options;
|
|
248
|
+
const playIconWidth = 65;
|
|
249
|
+
const playIconHeight = 46;
|
|
250
|
+
const vmlLeft = innerContainerWidth / 2 - playIconWidth / 2;
|
|
251
|
+
const vmlTop = calculatedHeight / 2 - playIconHeight / 2;
|
|
252
|
+
if (hideOnDesktop) {
|
|
253
|
+
return `<!--[if !mso]><!-->
|
|
254
|
+
<v:group xmlns:v="urn:schemas-microsoft-com:vml"
|
|
255
|
+
coordsize="${innerContainerWidth},${calculatedHeight}"
|
|
256
|
+
href="${videoLink}"
|
|
257
|
+
style="width:${innerContainerWidth}px;height:${calculatedHeight}px;mso-width-relative:page;">
|
|
258
|
+
<v:rect fill="t" style="position:absolute;width:${innerContainerWidth}px;height:${calculatedHeight}px;" stroked="t"
|
|
259
|
+
strokeweight="${borderWidth}px"
|
|
260
|
+
strokecolor="${borderColor}"
|
|
261
|
+
${borderRadius > 0 ? `arcsize="${Math.min(borderRadius / calculatedHeight, 1).toFixed(2)}"` : ""}
|
|
262
|
+
>
|
|
263
|
+
<v:fill src="${resolvedThumbnail}" type="frame" color="#FFFFFF"/>
|
|
264
|
+
</v:rect>
|
|
265
|
+
<v:shape type="#_x0000_t75"
|
|
266
|
+
style="position:absolute;
|
|
267
|
+
left:${vmlLeft.toFixed(1)}px;
|
|
268
|
+
top:${vmlTop.toFixed(1)}px;
|
|
269
|
+
width:${playIconWidth}px;
|
|
270
|
+
height:${playIconHeight}px;"
|
|
271
|
+
alt="Play" href="${videoLink}" title="${altText || "Video"}"
|
|
272
|
+
stroked="f" filled="t">
|
|
273
|
+
<v:imagedata src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png" />
|
|
274
|
+
</v:shape>
|
|
275
|
+
</v:group>
|
|
276
|
+
<!--<![endif]-->`;
|
|
277
|
+
}
|
|
278
|
+
return `<!--[if mso]>
|
|
279
|
+
<v:group xmlns:v="urn:schemas-microsoft-com:vml"
|
|
280
|
+
coordsize="${innerContainerWidth},${calculatedHeight}"
|
|
281
|
+
href="${videoLink}"
|
|
282
|
+
style="width:${innerContainerWidth}px;height:${calculatedHeight}px;mso-width-relative:page;">
|
|
283
|
+
<v:rect fill="t" style="position:absolute;width:${innerContainerWidth}px;height:${calculatedHeight}px; stroked="t"
|
|
284
|
+
strokeweight="${borderWidth}px"
|
|
285
|
+
strokecolor="${borderColor}"
|
|
286
|
+
${borderRadius > 0 ? `arcsize="${Math.min(borderRadius / calculatedHeight, 1).toFixed(2)}"` : ""}
|
|
287
|
+
>
|
|
288
|
+
<v:fill src="${resolvedThumbnail}" type="frame" color="#FFFFFF"/>
|
|
289
|
+
</v:rect>
|
|
290
|
+
<v:shape type="#_x0000_t75"
|
|
291
|
+
style="position:absolute;
|
|
292
|
+
left:${vmlLeft.toFixed(1)}px;
|
|
293
|
+
top:${vmlTop.toFixed(1)}px;
|
|
294
|
+
width:${playIconWidth}px;
|
|
295
|
+
height:${playIconHeight}px;"
|
|
296
|
+
alt="Play" href="${videoLink}" title="${altText || "Video"}"
|
|
297
|
+
stroked="f" filled="t">
|
|
298
|
+
<v:imagedata src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png" />
|
|
299
|
+
</v:shape>
|
|
300
|
+
</v:group>
|
|
301
|
+
<![endif]-->`;
|
|
302
|
+
}
|
|
303
|
+
function buildOutlookVMLVDivider(options) {
|
|
304
|
+
const { width, height, dividerColor } = options;
|
|
305
|
+
return `<!--[if mso | IE]>
|
|
306
|
+
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fillcolor="${dividerColor}" style="width:${width}px;height:${height}px;mso-width-relative:page;" stroke="f"></v:rect>
|
|
307
|
+
<![endif]-->`;
|
|
308
|
+
}
|
|
309
|
+
function wrapNonOutlookContent(options) {
|
|
310
|
+
const { content, visibilityClass } = options;
|
|
311
|
+
return `<!--[if !mso]><!-->
|
|
312
|
+
${content}
|
|
313
|
+
<!--<![endif]-->`;
|
|
314
|
+
}
|
|
315
|
+
// ============================================================================
|
|
316
|
+
// OUTLOOK WRAPPER TABLE BUILDER
|
|
317
|
+
// ============================================================================
|
|
318
|
+
// Replaces the inline Outlook conditional logic in appendOutlookSupport()
|
|
319
|
+
exports.tableCommonStyle = "border-collapse:collapse; table-layout:fixed;";
|
|
320
|
+
function buildOutlookWrapperTable(options) {
|
|
321
|
+
const { content, contentStyle, visibilityClass = "", maxWidth = 600 } = options;
|
|
322
|
+
const shouldHideInOutlook = visibilityClass.includes("hide-desktop");
|
|
323
|
+
if (shouldHideInOutlook) {
|
|
324
|
+
return `
|
|
325
|
+
<!--[if !mso]><!-->
|
|
326
|
+
<table width="100%" style="${exports.tableCommonStyle}" class="${visibilityClass}"><tr><td style="${contentStyle}">${content}</td></tr></table>
|
|
327
|
+
<!--<![endif]-->
|
|
328
|
+
`;
|
|
329
|
+
}
|
|
330
|
+
return `
|
|
331
|
+
<table width="100%" style="${exports.tableCommonStyle}; max-width:${maxWidth}px;" class="${visibilityClass}"><tr><td style="${contentStyle}">${content}</td></tr></table>
|
|
332
|
+
`;
|
|
333
|
+
}
|
|
334
|
+
function buildOutlookImageWrapper(options) {
|
|
335
|
+
const { outlookVMLImage, nonMsoWrapper, containerStyles, visibilityClass } = options;
|
|
336
|
+
const wrappedOutlookImage = wrapNonOutlookContent({
|
|
337
|
+
content: outlookVMLImage,
|
|
338
|
+
visibilityClass,
|
|
339
|
+
});
|
|
340
|
+
const outlookImage = `
|
|
341
|
+
${wrappedOutlookImage}
|
|
342
|
+
<!--[if !mso]><!-->
|
|
343
|
+
${nonMsoWrapper}
|
|
344
|
+
<!--<![endif]-->
|
|
345
|
+
`;
|
|
346
|
+
return buildOutlookWrapperTable({
|
|
347
|
+
content: outlookImage,
|
|
348
|
+
contentStyle: containerStyles,
|
|
349
|
+
visibilityClass,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
function buildOutlookButtonWrapper(options) {
|
|
353
|
+
const { outlookVMLButton, buttonElement, convertedStyles, visibilityClass } = options;
|
|
354
|
+
return buildOutlookWrapperTable({
|
|
355
|
+
content: `${outlookVMLButton}${buttonElement}`,
|
|
356
|
+
contentStyle: convertedStyles,
|
|
357
|
+
visibilityClass,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
function buildOutlookVideoWrapper(options) {
|
|
361
|
+
const { videoContent, outerContainerStyles, cellWidthInPx, visibilityClass, percentWidth, textAlign = "left", } = options;
|
|
362
|
+
return `
|
|
363
|
+
<!--[if mso]>
|
|
364
|
+
<table width="${cellWidthInPx}" border="0" cellpadding="0" cellspacing="0" style="margin:0; padding:0; border-collapse: collapse; ${outerContainerStyles}">
|
|
365
|
+
<![endif]-->
|
|
366
|
+
<!--[if !mso]><!-->
|
|
367
|
+
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="margin:0; padding:0; border-collapse: collapse; max-width:${cellWidthInPx}px;" class="${visibilityClass}">
|
|
368
|
+
<!--<![endif]-->
|
|
369
|
+
<tr>
|
|
370
|
+
<td align="${textAlign}" style="padding:0;">
|
|
371
|
+
<!--[if mso]>
|
|
372
|
+
<table width="${percentWidth}" border="0" cellpadding="0" cellspacing="0" align="${textAlign}" style="border-collapse:collapse;">
|
|
373
|
+
<![endif]-->
|
|
374
|
+
<!--[if !mso]><!-->
|
|
375
|
+
<table border="0" cellpadding="0" cellspacing="0" role="presentation"
|
|
376
|
+
align="${textAlign}"
|
|
377
|
+
style="margin:0; width:${percentWidth}; border-collapse:collapse;">
|
|
378
|
+
<!--<![endif]-->
|
|
379
|
+
<tr>
|
|
380
|
+
<td align="${textAlign}" style="text-align:${textAlign}; padding:0;">
|
|
381
|
+
${videoContent}
|
|
382
|
+
</td>
|
|
383
|
+
</tr>
|
|
384
|
+
</table>
|
|
385
|
+
</td>
|
|
386
|
+
</tr>
|
|
387
|
+
</table>
|
|
388
|
+
`;
|
|
389
|
+
}
|
|
390
|
+
function buildOutlookVDividerWrapper(options) {
|
|
391
|
+
const { outlookVDividerVML, nonMsoDivider, convertedStyle, visibilityClass } = options;
|
|
392
|
+
const dividerContent = `
|
|
393
|
+
<table cellpadding="0" cellspacing="0" border="0" align="center" style="width:auto; ${convertedStyle}">
|
|
394
|
+
<tr>
|
|
395
|
+
<td style="vertical-align: middle; text-align: center;">
|
|
396
|
+
${outlookVDividerVML}
|
|
397
|
+
<!--[if !mso]><!-- -->
|
|
398
|
+
${nonMsoDivider}
|
|
399
|
+
<!--<![endif]-->
|
|
400
|
+
</td>
|
|
401
|
+
</tr>
|
|
402
|
+
</table>
|
|
403
|
+
`;
|
|
404
|
+
return buildOutlookWrapperTable({
|
|
405
|
+
content: dividerContent,
|
|
406
|
+
contentStyle: convertedStyle,
|
|
407
|
+
visibilityClass,
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
function buildOutlookShapeWrapperTable(options) {
|
|
411
|
+
const { outlookContent, nonMsoContent, padding, alignment, visibilityClass } = options;
|
|
412
|
+
return `
|
|
413
|
+
<table width="100%" style="border-collapse:collapse;table-layout:fixed;max-width:600px;" class="${visibilityClass}">
|
|
414
|
+
<tr>
|
|
415
|
+
<td style="padding:${padding.top || 0}px ${padding.right || 0}px ${padding.bottom || 0}px ${padding.left || 0}px;text-align:${alignment};">
|
|
416
|
+
${outlookContent}
|
|
417
|
+
<!--[if !mso]><!-->
|
|
418
|
+
${nonMsoContent}
|
|
419
|
+
<!--<![endif]-->
|
|
420
|
+
</td>
|
|
421
|
+
</tr>
|
|
422
|
+
</table>`;
|
|
423
|
+
}
|
|
424
|
+
function buildOutlookGridWrapper(options) {
|
|
425
|
+
const { columnGap, gridVisibilityClass, tableStyles, content, cellWidthInPx } = options;
|
|
426
|
+
// Use fixed width for MSO to prevent percentage calculation issues
|
|
427
|
+
// Add overflow:hidden and table-layout:fixed for proper constraint
|
|
428
|
+
return `<!--[if mso]>
|
|
429
|
+
<table border="0" cellpadding="0" cellspacing="${columnGap}" width="${cellWidthInPx}"
|
|
430
|
+
style="border-collapse:separate;border-spacing:${columnGap}px;${tableStyles};mso-table-lspace:0;mso-table-rspace:0;overflow:hidden;">
|
|
431
|
+
<![endif]-->
|
|
432
|
+
<!--[if !mso]><!-->
|
|
433
|
+
<table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%"
|
|
434
|
+
role="presentation"
|
|
435
|
+
style="border-collapse:separate;border-spacing:${columnGap}px; ${tableStyles}; max-width:${cellWidthInPx}px;overflow:hidden;"
|
|
436
|
+
class="${gridVisibilityClass}">
|
|
437
|
+
<!--<![endif]-->
|
|
438
|
+
${content}
|
|
439
|
+
</table>`;
|
|
440
|
+
}
|
|
441
|
+
function buildOutlookGridRow(options) {
|
|
442
|
+
return `<tr>${options.rowContent}</tr>`;
|
|
443
|
+
}
|
|
444
|
+
function buildOutlookGridCellWrapper(options) {
|
|
445
|
+
const { widthPx, widthPercent, verticalAlign, visibilityClass, responsive, styles, msoContent, nonMsoContent, } = options;
|
|
446
|
+
// For Outlook, we need explicit pixel widths to prevent percentage calculation issues
|
|
447
|
+
// Add overflow:hidden to both MSO and non-MSO cells to prevent overflow
|
|
448
|
+
return `<!--[if mso]>
|
|
449
|
+
<td width="${widthPx}" valign="${verticalAlign}" style="vertical-align:${verticalAlign};word-break:break-word;overflow:hidden;${styles}">
|
|
450
|
+
${msoContent}
|
|
451
|
+
</td>
|
|
452
|
+
<![endif]-->
|
|
453
|
+
<!--[if !mso]><!-->
|
|
454
|
+
<td
|
|
455
|
+
width="${widthPercent}%"
|
|
456
|
+
class="${[responsive ? "stack-column" : "", visibilityClass]
|
|
457
|
+
.filter(Boolean)
|
|
458
|
+
.join(" ")}"
|
|
459
|
+
style="vertical-align:${verticalAlign};word-break:break-word;overflow:hidden;${styles}">
|
|
460
|
+
${nonMsoContent}
|
|
461
|
+
</td>
|
|
462
|
+
<!--<![endif]-->`;
|
|
463
|
+
}
|
|
464
|
+
function buildOutlookEmptyCellWrapper(options) {
|
|
465
|
+
const { widthPx, widthPercent, responsive } = options;
|
|
466
|
+
// Add overflow:hidden to prevent content from breaking layout in Outlook
|
|
467
|
+
return `<!--[if mso]>
|
|
468
|
+
<td width="${widthPx}" ${responsive ? 'class="stack-column"' : ""} style="vertical-align:top;overflow:hidden;"> </td>
|
|
469
|
+
<![endif]-->
|
|
470
|
+
<!--[if !mso]><!-->
|
|
471
|
+
<td width="${widthPercent}%"
|
|
472
|
+
${responsive ? 'class="stack-column"' : ""}
|
|
473
|
+
style="vertical-align:top;overflow:hidden;"> </td>
|
|
474
|
+
<!--<![endif]-->`;
|
|
475
|
+
}
|
|
476
|
+
// ============================================================================
|
|
477
|
+
// EXPORT INDEX
|
|
478
|
+
// ============================================================================
|
|
479
|
+
__exportStar(require("./common"), exports);
|
package/package.json
CHANGED
|
@@ -1,33 +1,34 @@
|
|
|
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.45",
|
|
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
|
+
"user": "^0.0.0"
|
|
33
|
+
}
|
|
34
|
+
}
|