email-builder-utils 1.1.23 → 1.1.26
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.
|
@@ -24,6 +24,5 @@ interface IBlockData {
|
|
|
24
24
|
export declare const tableCommonStyle = "border-collapse:collapse; table-layout:fixed;";
|
|
25
25
|
export declare function convertToHtml(blockData: IBlockData, rootData: any, cellWidthInPx: number): Promise<string>;
|
|
26
26
|
export declare function convertVideoBlock(blockData: any, cellWidthInPx: number): Promise<string>;
|
|
27
|
-
export declare function convertShapeBlock(blockData: IBlockData): Promise<string>;
|
|
28
27
|
export {};
|
|
29
28
|
//# sourceMappingURL=jsonToHTML.d.ts.map
|
|
@@ -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;AAUrC,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;CAChB;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;AAOD,eAAO,MAAM,gBAAgB,kDAAkD,CAAC;AAiDhF,wBAAsB,aAAa,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,mBAqB9F;
|
|
1
|
+
{"version":3,"file":"jsonToHTML.d.ts","sourceRoot":"","sources":["../../src/utils/jsonToHTML.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAUrC,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;CAChB;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;AAOD,eAAO,MAAM,gBAAgB,kDAAkD,CAAC;AAiDhF,wBAAsB,aAAa,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,mBAqB9F;AAsVD,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,mBAoK5E"}
|
package/dist/utils/jsonToHTML.js
CHANGED
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.tableCommonStyle = void 0;
|
|
4
4
|
exports.convertToHtml = convertToHtml;
|
|
5
5
|
exports.convertVideoBlock = convertVideoBlock;
|
|
6
|
-
exports.convertShapeBlock = convertShapeBlock;
|
|
7
6
|
const jimp_1 = require("jimp");
|
|
8
7
|
const types_1 = require("../types");
|
|
9
8
|
const common_1 = require("./common");
|
|
@@ -266,9 +265,9 @@ async function convertGridBlock(blockData, rootData, cellWidthInPx) {
|
|
|
266
265
|
const visualRows = Math.ceil(total / columns);
|
|
267
266
|
let html = `
|
|
268
267
|
<!--[if mso]>
|
|
269
|
-
<table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%" style="${exports.tableCommonStyle}">
|
|
268
|
+
<table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%" style="${exports.tableCommonStyle}border-collapse: separate;border-spacing:${columnGap}px;">
|
|
270
269
|
<![endif]-->
|
|
271
|
-
<table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%" role="presentation" style="${exports.tableCommonStyle} ${tableStyles}">
|
|
270
|
+
<table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%" role="presentation" style="${exports.tableCommonStyle} ${tableStyles}border-collapse: separate;border-spacing:${columnGap}px;">
|
|
272
271
|
`;
|
|
273
272
|
for (let r = 0; r < visualRows; r++) {
|
|
274
273
|
html += "<tr>";
|
|
@@ -285,13 +284,13 @@ async function convertGridBlock(blockData, rootData, cellWidthInPx) {
|
|
|
285
284
|
<td
|
|
286
285
|
width="${widthPercent}%"
|
|
287
286
|
${responsive ? 'class="stack-column"' : ""}
|
|
288
|
-
style="vertical-align:${verticalAlign};
|
|
287
|
+
style="vertical-align:${verticalAlign}; word-break:break-word; ${styles} "
|
|
289
288
|
>
|
|
290
289
|
${childHtml}
|
|
291
290
|
</td>`;
|
|
292
291
|
}
|
|
293
292
|
else {
|
|
294
|
-
html += `<td width="${widthPercent}%" ${responsive ? 'class="stack-column"' : ""} style="
|
|
293
|
+
html += `<td width="${widthPercent}%" ${responsive ? 'class="stack-column"' : ""} style=""></td>`;
|
|
295
294
|
}
|
|
296
295
|
}
|
|
297
296
|
html += "</tr>";
|
|
@@ -320,7 +319,7 @@ async function convertGridCellBlock(blockData, rootData, cellWidthPercent, paren
|
|
|
320
319
|
}
|
|
321
320
|
async function convertVideoBlock(blockData, cellWidthInPx) {
|
|
322
321
|
const { style, props } = blockData.data;
|
|
323
|
-
const { videoUrl, youtubeVideoUrl, thumbnailUrl, altText } = props
|
|
322
|
+
const { videoUrl, youtubeVideoUrl, thumbnailUrl, altText } = props;
|
|
324
323
|
const videoLink = youtubeVideoUrl || videoUrl || "#";
|
|
325
324
|
let resolvedThumbnail = thumbnailUrl || "https://via.placeholder.com/480x360?text=No+Thumbnail";
|
|
326
325
|
if (youtubeVideoUrl) {
|
|
@@ -351,12 +350,19 @@ async function convertVideoBlock(blockData, cellWidthInPx) {
|
|
|
351
350
|
else {
|
|
352
351
|
percentWidth = "100%";
|
|
353
352
|
}
|
|
354
|
-
const innerContainerWidth = (parseFloat(percentWidth) / 100) *
|
|
353
|
+
const innerContainerWidth = (parseFloat(percentWidth) / 100) *
|
|
354
|
+
(cellWidthInPx -
|
|
355
|
+
(style?.padding?.left || 0) -
|
|
356
|
+
(style?.padding?.right || 0));
|
|
355
357
|
const aspectRatio = 16 / 9;
|
|
356
358
|
const calculatedHeight = innerContainerWidth / aspectRatio;
|
|
357
359
|
const outerContainerStyles = buildStyles({
|
|
358
360
|
...style,
|
|
359
361
|
width: undefined,
|
|
362
|
+
borderColor: undefined,
|
|
363
|
+
borderRadius: undefined,
|
|
364
|
+
borderWidth: undefined,
|
|
365
|
+
borderStyle: undefined,
|
|
360
366
|
}, {
|
|
361
367
|
perChanges: addPxOrPerToAttributes,
|
|
362
368
|
pxChanges: addPxToAttributes,
|
|
@@ -371,72 +377,94 @@ async function convertVideoBlock(blockData, cellWidthInPx) {
|
|
|
371
377
|
const vmlLeft = innerContainerWidth / 2 - playIconWidth / 2;
|
|
372
378
|
const vmlTop = calculatedHeight / 2 - playIconHeight / 2;
|
|
373
379
|
const videoContent = `
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
style="position:absolute;
|
|
384
|
-
left:${vmlLeft.toFixed(1)}px;
|
|
385
|
-
top:${vmlTop.toFixed(1)}px;
|
|
386
|
-
width:${playIconWidth}px;
|
|
387
|
-
height:${playIconHeight}px;"
|
|
388
|
-
alt="Play" href="${videoLink}" title="${altText || "Video"}"
|
|
389
|
-
stroked="f" filled="t">
|
|
390
|
-
<v:imagedata src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png" />
|
|
391
|
-
</v:shape>
|
|
392
|
-
</v:group>
|
|
393
|
-
<![endif]-->
|
|
394
|
-
|
|
395
|
-
<!--[if !mso]><!-->
|
|
396
|
-
<table
|
|
397
|
-
width="${innerContainerWidth}"
|
|
398
|
-
cellpadding="0"
|
|
399
|
-
cellspacing="0"
|
|
400
|
-
border="0"
|
|
401
|
-
role="presentation"
|
|
402
|
-
style="
|
|
403
|
-
background-image: url('${resolvedThumbnail}');
|
|
404
|
-
background-size: cover;
|
|
405
|
-
background-position: center;
|
|
406
|
-
|
|
407
|
-
max-width: ${innerContainerWidth}px;
|
|
408
|
-
height: ${calculatedHeight}px;
|
|
409
|
-
box-sizing: border-box;
|
|
410
|
-
"
|
|
411
|
-
align="center"
|
|
380
|
+
<!--[if mso]>
|
|
381
|
+
<v:group xmlns:v="urn:schemas-microsoft-com:vml"
|
|
382
|
+
coordsize="${innerContainerWidth},${calculatedHeight}"
|
|
383
|
+
href="${videoLink}"
|
|
384
|
+
style="width:${innerContainerWidth}px;height:${calculatedHeight}px;">
|
|
385
|
+
<v:rect fill="t" style="position:absolute;width:${innerContainerWidth}px;height:${calculatedHeight}px; stroked="t"
|
|
386
|
+
strokeweight="${borderWidth}px"
|
|
387
|
+
strokecolor="${borderColor}"
|
|
388
|
+
${borderRadius > 0 ? `arcsize="${Math.min(borderRadius / calculatedHeight, 1).toFixed(2)}"` : ""}
|
|
412
389
|
>
|
|
413
|
-
<
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
390
|
+
<v:fill src="${resolvedThumbnail}" type="frame" color="${style?.backgroundColor || "#FFFFFF"}"/>
|
|
391
|
+
</v:rect>
|
|
392
|
+
<v:shape type="#_x0000_t75"
|
|
393
|
+
style="position:absolute;
|
|
394
|
+
left:${vmlLeft.toFixed(1)}px;
|
|
395
|
+
top:${vmlTop.toFixed(1)}px;
|
|
396
|
+
width:${playIconWidth}px;
|
|
397
|
+
height:${playIconHeight}px;"
|
|
398
|
+
alt="Play" href="${videoLink}" title="${altText || "Video"}"
|
|
399
|
+
stroked="f" filled="t">
|
|
400
|
+
<v:imagedata src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png" />
|
|
401
|
+
</v:shape>
|
|
402
|
+
</v:group>
|
|
403
|
+
<![endif]-->
|
|
404
|
+
|
|
405
|
+
<!--[if !mso]><!-->
|
|
406
|
+
<table
|
|
407
|
+
width="${innerContainerWidth}"
|
|
408
|
+
cellpadding="0"
|
|
409
|
+
cellspacing="0"
|
|
410
|
+
border="0"
|
|
411
|
+
role="presentation"
|
|
412
|
+
align="${style?.textAlign || "left"}"
|
|
413
|
+
style="
|
|
414
|
+
max-width: ${innerContainerWidth}px;
|
|
415
|
+
width: 100%;
|
|
416
|
+
height: ${calculatedHeight}px;
|
|
417
|
+
background-color: ${style?.backgroundColor || "#FFFFFF"};
|
|
418
|
+
background-image: url('${resolvedThumbnail}');
|
|
419
|
+
background-size: cover;
|
|
420
|
+
background-position: center;
|
|
421
|
+
background-repeat: no-repeat;
|
|
422
|
+
box-sizing: border-box;
|
|
423
|
+
border: ${borderWidth}px ${style?.borderStyle || "solid"} ${borderColor};
|
|
424
|
+
border-radius: ${borderRadius}px;
|
|
425
|
+
"
|
|
426
|
+
>
|
|
427
|
+
<tr>
|
|
428
|
+
<td style="padding: 0; height: ${calculatedHeight}px; text-align: center; vertical-align: middle;" valign="middle">
|
|
429
|
+
<a href="${videoLink}" target="_blank" style="display:inline-block; border: 0; outline: none; text-decoration: none;">
|
|
430
|
+
<img
|
|
431
|
+
src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png"
|
|
432
|
+
width="${playIconWidth}"
|
|
433
|
+
alt="Play"
|
|
434
|
+
style="display: block;
|
|
435
|
+
border: 0;
|
|
436
|
+
outline: none;
|
|
437
|
+
text-decoration: none;
|
|
438
|
+
height: auto;"
|
|
439
|
+
/>
|
|
440
|
+
</a>
|
|
441
|
+
</td>
|
|
442
|
+
</tr>
|
|
443
|
+
</table>
|
|
444
|
+
<!--<![endif]-->
|
|
445
|
+
`;
|
|
429
446
|
const wrapperHtml = `
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
447
|
+
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="margin:0; padding:0; border-collapse: collapse;">
|
|
448
|
+
<tr>
|
|
449
|
+
<td align="${style?.textAlign || "left"}" style="padding:0; ${outerContainerStyles}">
|
|
450
|
+
<table border="0" cellpadding="0" cellspacing="0" role="presentation"
|
|
451
|
+
align="${style?.textAlign || "left"}"
|
|
452
|
+
style="
|
|
453
|
+
margin:0;
|
|
454
|
+
max-width:${cellWidthInPx}px;
|
|
455
|
+
width:${percentWidth};
|
|
456
|
+
border-collapse:collapse;
|
|
457
|
+
">
|
|
458
|
+
<tr>
|
|
459
|
+
<td align="${style?.textAlign || "left"}" style="text-align:${style?.textAlign || "left"}; padding:0;">
|
|
460
|
+
${videoContent}
|
|
461
|
+
</td>
|
|
462
|
+
</tr>
|
|
463
|
+
</table>
|
|
464
|
+
</td>
|
|
465
|
+
</tr>
|
|
466
|
+
</table>
|
|
467
|
+
`;
|
|
440
468
|
return wrapperHtml;
|
|
441
469
|
}
|
|
442
470
|
// Enhanced Shape Block HTML Conversion using appendOutlookForShape
|
|
@@ -534,24 +562,31 @@ function buildVMLShape({ shape, widthPx, heightPx, imageUrl, backgroundColor, bo
|
|
|
534
562
|
// ---------- convertShapeBlock (updated, keeps your structure) ----------
|
|
535
563
|
async function convertShapeBlock(blockData) {
|
|
536
564
|
const { style, props } = blockData.data;
|
|
537
|
-
const { shape, text, textColor = "#000000", imageUrl } = props
|
|
538
|
-
const { width = "100", height = "150", padding = {}, backgroundColor = "#2F80ED", borderRadius, borderWidth = 0, borderStyle = "solid", borderColor = "transparent", customCss, shapeColor, alignment = "left", msoBakeImageWithText
|
|
565
|
+
const { shape, text, textColor = "#000000", imageUrl } = props;
|
|
566
|
+
const { width = "100", height = "150", padding = {}, backgroundColor = "#2F80ED", borderRadius, borderWidth = 0, borderStyle = "solid", borderColor = "transparent", customCss, shapeColor, alignment = "left", msoBakeImageWithText } = style || {};
|
|
539
567
|
const borderRadiusMap = {
|
|
540
568
|
rectangle: "0",
|
|
541
569
|
rounded: "10px",
|
|
542
570
|
circle: "50%",
|
|
543
|
-
oval: "50%",
|
|
571
|
+
oval: "50%", // Keep this for modern browsers
|
|
544
572
|
};
|
|
545
573
|
let resolvedBorderRadius = borderRadius || borderRadiusMap[shape] || "0";
|
|
546
|
-
let resolvedWidthPx = typeof width === "number"
|
|
547
|
-
|
|
548
|
-
|
|
574
|
+
let resolvedWidthPx = typeof width === "number"
|
|
575
|
+
? width
|
|
576
|
+
: parseInt(width.toString().replace("px", ""), 10) || 100;
|
|
577
|
+
let resolvedHeightPx = typeof height === "number"
|
|
578
|
+
? height
|
|
579
|
+
: parseInt(height.toString().replace("px", ""), 10) || 150;
|
|
580
|
+
// Special handling for different shapes
|
|
549
581
|
if (shape === "circle") {
|
|
582
|
+
// Circle: make it a perfect square with 50% border radius
|
|
550
583
|
const side = Math.min(resolvedWidthPx, resolvedHeightPx);
|
|
551
584
|
resolvedWidthPx = side;
|
|
552
585
|
resolvedHeightPx = side;
|
|
553
586
|
resolvedBorderRadius = "50%";
|
|
554
587
|
}
|
|
588
|
+
else if (shape === "oval") {
|
|
589
|
+
}
|
|
555
590
|
const finalWidthPx = resolvedWidthPx;
|
|
556
591
|
const finalHeightPx = resolvedHeightPx;
|
|
557
592
|
const alignmentStyles = {
|
|
@@ -563,12 +598,14 @@ async function convertShapeBlock(blockData) {
|
|
|
563
598
|
const finalBackgroundColor = shapeColor || backgroundColor;
|
|
564
599
|
// --- Modern clients content ---
|
|
565
600
|
let nonMsoContent = "";
|
|
601
|
+
// For modern browsers, use CSS border-radius
|
|
602
|
+
const modernBorderRadius = shape === "oval" ? "50%" : resolvedBorderRadius;
|
|
566
603
|
// Case 1: Image + Text → use background-image
|
|
567
604
|
if (imageUrl && text) {
|
|
568
605
|
nonMsoContent = `
|
|
569
606
|
<div style="display:inline-block;width:${finalWidthPx}px;height:${finalHeightPx}px;
|
|
570
607
|
border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
571
|
-
border-radius:${
|
|
608
|
+
border-radius:${modernBorderRadius};
|
|
572
609
|
background:${finalBackgroundColor} url('${imageUrl}') center/cover no-repeat;
|
|
573
610
|
overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
574
611
|
<div style="width:100%;height:100%;display:flex;align-items:center;justify-content:center;">
|
|
@@ -584,11 +621,11 @@ async function convertShapeBlock(blockData) {
|
|
|
584
621
|
nonMsoContent = `
|
|
585
622
|
<div style="display:inline-block;width:${finalWidthPx}px;height:${finalHeightPx}px;
|
|
586
623
|
border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
587
|
-
border-radius:${
|
|
624
|
+
border-radius:${modernBorderRadius};
|
|
588
625
|
overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
589
626
|
<img src="${imageUrl}" alt="${text || "Shape image"}"
|
|
590
627
|
width="${finalWidthPx}" height="${finalHeightPx}"
|
|
591
|
-
style="width:100%;height:100%;object-fit:cover;border-radius:${
|
|
628
|
+
style="width:100%;height:100%;object-fit:cover;border-radius:${modernBorderRadius};display:block;" />
|
|
592
629
|
</div>`;
|
|
593
630
|
}
|
|
594
631
|
// Case 3: No image → solid background
|
|
@@ -597,7 +634,7 @@ async function convertShapeBlock(blockData) {
|
|
|
597
634
|
<div style="display:inline-block;width:${finalWidthPx}px;height:${finalHeightPx}px;
|
|
598
635
|
background:${finalBackgroundColor};
|
|
599
636
|
border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
600
|
-
border-radius:${
|
|
637
|
+
border-radius:${modernBorderRadius};
|
|
601
638
|
${alignmentStyle}${customCss || ""}">
|
|
602
639
|
<div style="width:100%;height:100%;display:flex;align-items:center;justify-content:center;
|
|
603
640
|
color:${textColor};text-align:center;padding:8px;box-sizing:border-box;word-break:break-word;">
|
|
@@ -619,7 +656,7 @@ async function convertShapeBlock(blockData) {
|
|
|
619
656
|
textColor,
|
|
620
657
|
alignment,
|
|
621
658
|
padding,
|
|
622
|
-
msoBakeImageWithText
|
|
659
|
+
msoBakeImageWithText
|
|
623
660
|
});
|
|
624
661
|
// Wrap in container table
|
|
625
662
|
const containerTable = `
|