email-builder-utils 1.1.28 → 1.1.29
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Template.d.ts","sourceRoot":"","sources":["../../src/types/Template.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,IAAI,YAAY;IAChB,KAAK,UAAU;IACf,QAAQ,WAAW;IACnB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,WAAW,gBAAgB;IAC3B,KAAK,UAAU;IACf,KAAK,UAAU;IACf,QAAQ,aAAa;CACtB;AAED,oBAAY,UAAU;IACpB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,WAAW,gBAAgB;CAC5B;AAED,UAAU,MAAM;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,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;
|
|
1
|
+
{"version":3,"file":"Template.d.ts","sourceRoot":"","sources":["../../src/types/Template.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,IAAI,YAAY;IAChB,KAAK,UAAU;IACf,QAAQ,WAAW;IACnB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,WAAW,gBAAgB;IAC3B,KAAK,UAAU;IACf,KAAK,UAAU;IACf,QAAQ,aAAa;CACtB;AAED,oBAAY,UAAU;IACpB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,WAAW,gBAAgB;CAC5B;AAED,UAAU,MAAM;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,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;CAGhB;AAED,UAAU,MAAM;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;CACH"}
|
|
@@ -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;
|
|
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;CAGhB;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;AA2DhF,wBAAsB,aAAa,CACjC,SAAS,EAAE,UAAU,EACrB,QAAQ,EAAE,GAAG,EACb,aAAa,EAAE,MAAM,mBAwBtB;AAsbD,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,mBA8K5E"}
|
package/dist/utils/jsonToHTML.js
CHANGED
|
@@ -90,16 +90,17 @@ function appendOutlookSupport(content, contentStyle) {
|
|
|
90
90
|
`;
|
|
91
91
|
}
|
|
92
92
|
function convertDividerBlockToHtml(blockData) {
|
|
93
|
-
const { style } = blockData.data;
|
|
94
|
-
const { thickness, dividerColor, ...rest } = style;
|
|
93
|
+
const { style, props } = blockData.data;
|
|
94
|
+
const { thickness, dividerColor, width, ...rest } = style;
|
|
95
95
|
const convertedStyle = buildStyles(rest, {
|
|
96
96
|
perChanges: [],
|
|
97
97
|
pxChanges: allPxAttributes,
|
|
98
98
|
});
|
|
99
|
+
const dividerWidth = width || "100%";
|
|
99
100
|
const dividerContent = `
|
|
100
|
-
<table width="
|
|
101
|
+
<table width="${dividerWidth}%" cellpadding="0" cellspacing="0">
|
|
101
102
|
<tr>
|
|
102
|
-
<td height="${thickness}" style="font-size:1px; line-height:1px; background:${dividerColor};"> </td>
|
|
103
|
+
<td height="${thickness}" style="font-size:1px; line-height:1px; background:${dividerColor}; width:${dividerWidth};"> </td>
|
|
103
104
|
</tr>
|
|
104
105
|
</table>
|
|
105
106
|
`;
|
|
@@ -522,10 +523,278 @@ function computeArcSize(borderRadius, widthPx) {
|
|
|
522
523
|
return Math.min(px / widthPx, 1).toFixed(2);
|
|
523
524
|
}
|
|
524
525
|
// ---------- Updated convertShapeBlock function ----------
|
|
526
|
+
// async function convertShapeBlock(blockData: IBlockData) {
|
|
527
|
+
// const { style, props } = blockData.data;
|
|
528
|
+
// const { shape, text, imageUrl } = props as any;
|
|
529
|
+
// const {
|
|
530
|
+
// width = "100",
|
|
531
|
+
// height = "150",
|
|
532
|
+
// padding = {},
|
|
533
|
+
// backgroundColor = "#2F80ED",
|
|
534
|
+
// borderRadius,
|
|
535
|
+
// borderWidth = 0,
|
|
536
|
+
// borderStyle = "solid",
|
|
537
|
+
// borderColor = "transparent",
|
|
538
|
+
// customCss,
|
|
539
|
+
// shapeColor,
|
|
540
|
+
// alignment = "left",
|
|
541
|
+
// msoBakeImageWithText,
|
|
542
|
+
// color = "#000000",
|
|
543
|
+
// fontSize = 14,
|
|
544
|
+
// verticalAlign = "center",
|
|
545
|
+
// } = style || {};
|
|
546
|
+
// const borderRadiusMap: Record<string, string> = {
|
|
547
|
+
// rectangle: "0",
|
|
548
|
+
// rounded: "10px",
|
|
549
|
+
// circle: "50%",
|
|
550
|
+
// oval: "50%",
|
|
551
|
+
// };
|
|
552
|
+
// let resolvedBorderRadius = borderRadius || borderRadiusMap[shape] || "0";
|
|
553
|
+
// let resolvedWidthPx =
|
|
554
|
+
// typeof width === "number"
|
|
555
|
+
// ? width
|
|
556
|
+
// : parseInt(width.toString().replace("px", ""), 10) || 100;
|
|
557
|
+
// let resolvedHeightPx =
|
|
558
|
+
// typeof height === "number"
|
|
559
|
+
// ? height
|
|
560
|
+
// : parseInt(height.toString().replace("px", ""), 10) || 150;
|
|
561
|
+
// // --- Shape specific constraints ---
|
|
562
|
+
// if (shape === "circle") {
|
|
563
|
+
// const side = Math.min(resolvedWidthPx, resolvedHeightPx);
|
|
564
|
+
// resolvedWidthPx = side;
|
|
565
|
+
// resolvedHeightPx = side;
|
|
566
|
+
// resolvedBorderRadius = "50%";
|
|
567
|
+
// } else if (shape === "oval") {
|
|
568
|
+
// resolvedBorderRadius = "50% / 50%";
|
|
569
|
+
// }
|
|
570
|
+
// const finalBackgroundColor = shapeColor || backgroundColor;
|
|
571
|
+
// const alignmentStyles = {
|
|
572
|
+
// left: "margin-right:auto;margin-left:0;",
|
|
573
|
+
// center: "margin-left:auto;margin-right:auto;",
|
|
574
|
+
// right: "margin-left:auto;margin-right:0;",
|
|
575
|
+
// };
|
|
576
|
+
// const alignmentStyle =
|
|
577
|
+
// alignmentStyles[alignment as keyof typeof alignmentStyles] || "";
|
|
578
|
+
// const verticalAlignStyles = {
|
|
579
|
+
// top: "align-items:flex-start;padding-top:8px;",
|
|
580
|
+
// center: "align-items:center;",
|
|
581
|
+
// bottom: "align-items:flex-end;padding-bottom:8px;",
|
|
582
|
+
// };
|
|
583
|
+
// const verticalAlignStyle =
|
|
584
|
+
// verticalAlignStyles[verticalAlign as keyof typeof verticalAlignStyles] ||
|
|
585
|
+
// verticalAlignStyles.center;
|
|
586
|
+
// // Text styling (safe across clients)
|
|
587
|
+
// const textSizeStyle = `font-size:${fontSize}px;line-height:1.3;word-break:break-word;overflow-wrap:break-word;text-align:center;color:${color};`;
|
|
588
|
+
// // ============================
|
|
589
|
+
// // Modern HTML (non-MSO)
|
|
590
|
+
// // ============================
|
|
591
|
+
// let nonMsoContent = "";
|
|
592
|
+
// if (imageUrl && text) {
|
|
593
|
+
// nonMsoContent = `
|
|
594
|
+
// <div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
595
|
+
// border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
596
|
+
// border-radius:${resolvedBorderRadius};
|
|
597
|
+
// background:${finalBackgroundColor} url('${imageUrl}') center/cover no-repeat;
|
|
598
|
+
// overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
599
|
+
// <div style="width:100%;height:100%;display:flex;${verticalAlignStyle}justify-content:center;overflow:hidden;">
|
|
600
|
+
// <div style="${textSizeStyle}padding:6px;max-width:90%;-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;">
|
|
601
|
+
// ${text}
|
|
602
|
+
// </div>
|
|
603
|
+
// </div>
|
|
604
|
+
// </div>`;
|
|
605
|
+
// } else if (imageUrl) {
|
|
606
|
+
// nonMsoContent = `
|
|
607
|
+
// <div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
608
|
+
// border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
609
|
+
// border-radius:${resolvedBorderRadius};
|
|
610
|
+
// overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
611
|
+
// <img src="${imageUrl}" alt="${text || "shape image"}"
|
|
612
|
+
// width="${resolvedWidthPx}" height="${resolvedHeightPx}"
|
|
613
|
+
// style="width:100%;height:100%;object-fit:cover;border-radius:${resolvedBorderRadius};display:block;" />
|
|
614
|
+
// </div>`;
|
|
615
|
+
// } else {
|
|
616
|
+
// const circlePadding =
|
|
617
|
+
// shape === "circle" ? Math.round(resolvedHeightPx * 0.15) : 8;
|
|
618
|
+
// nonMsoContent = `
|
|
619
|
+
// <div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
620
|
+
// background:${finalBackgroundColor};
|
|
621
|
+
// border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
622
|
+
// border-radius:${resolvedBorderRadius};
|
|
623
|
+
// overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
624
|
+
// <div style="width:100%;height:100%;display:flex;${verticalAlignStyle}justify-content:center;padding:${circlePadding}px;box-sizing:border-box;">
|
|
625
|
+
// <div style="${textSizeStyle}max-width:90%;overflow:hidden;">
|
|
626
|
+
// ${text || ""}
|
|
627
|
+
// </div>
|
|
628
|
+
// </div>
|
|
629
|
+
// </div>`;
|
|
630
|
+
// }
|
|
631
|
+
// // ============================
|
|
632
|
+
// // Outlook (VML) version
|
|
633
|
+
// // ============================
|
|
634
|
+
// const outlookContent = await appendOutlookForShape(
|
|
635
|
+
// nonMsoContent,
|
|
636
|
+
// resolvedWidthPx,
|
|
637
|
+
// resolvedWidthPx,
|
|
638
|
+
// {
|
|
639
|
+
// shape,
|
|
640
|
+
// imageUrl,
|
|
641
|
+
// backgroundColor,
|
|
642
|
+
// shapeColor,
|
|
643
|
+
// borderWidth,
|
|
644
|
+
// borderColor,
|
|
645
|
+
// borderRadius: resolvedBorderRadius,
|
|
646
|
+
// heightPx: resolvedHeightPx,
|
|
647
|
+
// text,
|
|
648
|
+
// textColor: color,
|
|
649
|
+
// textSize: fontSize,
|
|
650
|
+
// verticalAlign,
|
|
651
|
+
// alignment,
|
|
652
|
+
// padding,
|
|
653
|
+
// msoBakeImageWithText,
|
|
654
|
+
// }
|
|
655
|
+
// );
|
|
656
|
+
// // ============================
|
|
657
|
+
// // Final combined block
|
|
658
|
+
// // ============================
|
|
659
|
+
// return `
|
|
660
|
+
// <table width="100%" style="border-collapse:collapse;table-layout:fixed;">
|
|
661
|
+
// <tr>
|
|
662
|
+
// <td style="padding:${padding.top || 0}px ${padding.right || 0}px ${
|
|
663
|
+
// padding.bottom || 0
|
|
664
|
+
// }px ${padding.left || 0}px;text-align:${alignment};">
|
|
665
|
+
// ${outlookContent}
|
|
666
|
+
// <!--[if !mso]><!-->
|
|
667
|
+
// ${nonMsoContent}
|
|
668
|
+
// <!--<![endif]-->
|
|
669
|
+
// </td>
|
|
670
|
+
// </tr>
|
|
671
|
+
// </table>`;
|
|
672
|
+
// }
|
|
673
|
+
// // ---------- Updated VML builder with better text containment ----------
|
|
674
|
+
// function buildVMLShape({
|
|
675
|
+
// shape,
|
|
676
|
+
// widthPx,
|
|
677
|
+
// heightPx,
|
|
678
|
+
// imageUrl,
|
|
679
|
+
// backgroundColor,
|
|
680
|
+
// borderWidth,
|
|
681
|
+
// borderColor,
|
|
682
|
+
// borderRadius,
|
|
683
|
+
// text,
|
|
684
|
+
// textColor = "#000000",
|
|
685
|
+
// textSize = 14,
|
|
686
|
+
// verticalAlign = "center",
|
|
687
|
+
// msoHasBakedText = false,
|
|
688
|
+
// }: any) {
|
|
689
|
+
// // --- Basic setup ---
|
|
690
|
+
// const bw = borderWidth || 0;
|
|
691
|
+
// const bc = borderColor || "transparent";
|
|
692
|
+
// const borderAttrs =
|
|
693
|
+
// bw > 0 ? `strokeweight="${bw}px" strokecolor="${bc}"` : `stroked="false"`;
|
|
694
|
+
// const fillColor = backgroundColor || "#2F80ED";
|
|
695
|
+
// const fillMarkup = `<v:fill ${
|
|
696
|
+
// imageUrl ? `src="${imageUrl}" type="frame" aspect="atleast"` : ""
|
|
697
|
+
// } color="${fillColor}" />`;
|
|
698
|
+
// // --- Shape tag ---
|
|
699
|
+
// let tag = "rect";
|
|
700
|
+
// let extraAttr = "";
|
|
701
|
+
// if (shape === "circle" || shape === "oval") {
|
|
702
|
+
// tag = "oval";
|
|
703
|
+
// } else if (shape === "rounded") {
|
|
704
|
+
// tag = "roundrect";
|
|
705
|
+
// extraAttr = `arcsize="${computeArcSize(borderRadius, widthPx)}"`;
|
|
706
|
+
// }
|
|
707
|
+
// // --- Text alignment ---
|
|
708
|
+
// const vAlignMap = { top: "top", center: "middle", bottom: "bottom" };
|
|
709
|
+
// const vAlign = vAlignMap[verticalAlign as keyof typeof vAlignMap] || "middle";
|
|
710
|
+
// const safeFontSize = Math.max(textSize, 10);
|
|
711
|
+
// // --- Text inside shape ---
|
|
712
|
+
// const textboxMarkup =
|
|
713
|
+
// text && !msoHasBakedText
|
|
714
|
+
// ? `<v:textbox inset="6pt,6pt,6pt,6pt" style="mso-fit-shape-to-text:false;">
|
|
715
|
+
// <div style="display:table;width:100%;height:100%;">
|
|
716
|
+
// <div style="display:table-cell;vertical-align:${vAlign};text-align:center;">
|
|
717
|
+
// <div style="color:${textColor};font-family:Arial, sans-serif;font-size:${safeFontSize}px;line-height:1.3;word-wrap:break-word;">
|
|
718
|
+
// ${text}
|
|
719
|
+
// </div>
|
|
720
|
+
// </div>
|
|
721
|
+
// </div>
|
|
722
|
+
// </v:textbox>`
|
|
723
|
+
// : `<v:textbox inset="0,0,0,0"><div style="display:none;">.</div></v:textbox>`;
|
|
724
|
+
// // --- Final shape markup ---
|
|
725
|
+
// return `
|
|
726
|
+
// <v:${tag} xmlns:v="urn:schemas-microsoft-com:vml"
|
|
727
|
+
// style="width:${widthPx}px;height:${heightPx}px;
|
|
728
|
+
// mso-position-horizontal:center;
|
|
729
|
+
// mso-position-vertical:center;"
|
|
730
|
+
// ${borderAttrs}
|
|
731
|
+
// fill="true" fillcolor="${fillColor}"${extraAttr}>
|
|
732
|
+
// ${fillMarkup}
|
|
733
|
+
// ${textboxMarkup}
|
|
734
|
+
// </v:${tag}>`;
|
|
735
|
+
// }
|
|
736
|
+
// // ---------- Updated appendOutlookForShape ----------
|
|
737
|
+
// async function appendOutlookForShape(
|
|
738
|
+
// content: string,
|
|
739
|
+
// outerContainerWidth: number,
|
|
740
|
+
// innerContainerWidth: number,
|
|
741
|
+
// opts: {
|
|
742
|
+
// shape: string;
|
|
743
|
+
// imageUrl?: string;
|
|
744
|
+
// backgroundColor?: string;
|
|
745
|
+
// shapeColor?: string;
|
|
746
|
+
// borderWidth?: number;
|
|
747
|
+
// borderColor?: string;
|
|
748
|
+
// borderRadius?: string | number;
|
|
749
|
+
// heightPx: number;
|
|
750
|
+
// text?: string;
|
|
751
|
+
// textColor?: string;
|
|
752
|
+
// textSize?: number;
|
|
753
|
+
// verticalAlign?: "top" | "middle" | "bottom";
|
|
754
|
+
// alignment?: "left" | "center" | "right";
|
|
755
|
+
// padding?: { top?: number; right?: number; bottom?: number; left?: number };
|
|
756
|
+
// msoBakeImageWithText?: string;
|
|
757
|
+
// }
|
|
758
|
+
// ) {
|
|
759
|
+
// const widthPx = Math.round(
|
|
760
|
+
// Math.min(outerContainerWidth, innerContainerWidth)
|
|
761
|
+
// );
|
|
762
|
+
// const heightPx = Math.max(1, Math.round(opts.heightPx));
|
|
763
|
+
// const vml = buildVMLShape({
|
|
764
|
+
// shape: opts.shape,
|
|
765
|
+
// widthPx,
|
|
766
|
+
// heightPx,
|
|
767
|
+
// imageUrl: opts.msoBakeImageWithText || opts.imageUrl,
|
|
768
|
+
// backgroundColor: opts.shapeColor || opts.backgroundColor,
|
|
769
|
+
// borderWidth: opts.borderWidth,
|
|
770
|
+
// borderColor: opts.borderColor,
|
|
771
|
+
// borderRadius: opts.borderRadius,
|
|
772
|
+
// text: opts.text,
|
|
773
|
+
// textColor: opts.textColor,
|
|
774
|
+
// textSize: opts.textSize,
|
|
775
|
+
// msoHasBakedText: Boolean(opts.msoBakeImageWithText),
|
|
776
|
+
// });
|
|
777
|
+
// const pad = opts.padding || {};
|
|
778
|
+
// const align = opts.alignment || "left";
|
|
779
|
+
// const valign = opts.verticalAlign || "middle";
|
|
780
|
+
// return `<!--[if mso]>
|
|
781
|
+
// <table align="${align}" border="0" cellpadding="0" cellspacing="0"
|
|
782
|
+
// style="width:${widthPx}px;height:${heightPx}px;">
|
|
783
|
+
// <tr>
|
|
784
|
+
// <td valign="${valign}"
|
|
785
|
+
// style="padding:${pad.top || 0}px ${pad.right || 0}px ${
|
|
786
|
+
// pad.bottom || 0
|
|
787
|
+
// }px ${pad.left || 0}px;">
|
|
788
|
+
// ${vml}
|
|
789
|
+
// </td>
|
|
790
|
+
// </tr>
|
|
791
|
+
// </table>
|
|
792
|
+
// <![endif]-->`;
|
|
793
|
+
// }
|
|
525
794
|
async function convertShapeBlock(blockData) {
|
|
526
795
|
const { style, props } = blockData.data;
|
|
527
796
|
const { shape, text, imageUrl } = props;
|
|
528
|
-
const { width = "100", height = "150", padding = {}, backgroundColor = "#2F80ED", borderRadius, borderWidth = 0, borderStyle = "solid", borderColor = "transparent", customCss, shapeColor, alignment = "left", msoBakeImageWithText, color = "#000000", fontSize = 14,
|
|
797
|
+
const { width = "100", height = "150", padding = {}, backgroundColor = "#2F80ED", borderRadius, borderWidth = 0, borderStyle = "solid", borderColor = "transparent", customCss, shapeColor, alignment = "left", msoBakeImageWithText, color = "#000000", fontSize = 14, textAlign = "center", verticalAlign = "middle", } = style || {};
|
|
529
798
|
const borderRadiusMap = {
|
|
530
799
|
rectangle: "0",
|
|
531
800
|
rounded: "10px",
|
|
@@ -539,7 +808,7 @@ async function convertShapeBlock(blockData) {
|
|
|
539
808
|
let resolvedHeightPx = typeof height === "number"
|
|
540
809
|
? height
|
|
541
810
|
: parseInt(height.toString().replace("px", ""), 10) || 150;
|
|
542
|
-
// --- Shape
|
|
811
|
+
// --- Shape-specific constraints ---
|
|
543
812
|
if (shape === "circle") {
|
|
544
813
|
const side = Math.min(resolvedWidthPx, resolvedHeightPx);
|
|
545
814
|
resolvedWidthPx = side;
|
|
@@ -550,25 +819,38 @@ async function convertShapeBlock(blockData) {
|
|
|
550
819
|
resolvedBorderRadius = "50% / 50%";
|
|
551
820
|
}
|
|
552
821
|
const finalBackgroundColor = shapeColor || backgroundColor;
|
|
822
|
+
// --- Horizontal alignment for outer container ---
|
|
553
823
|
const alignmentStyles = {
|
|
554
824
|
left: "margin-right:auto;margin-left:0;",
|
|
555
825
|
center: "margin-left:auto;margin-right:auto;",
|
|
556
826
|
right: "margin-left:auto;margin-right:0;",
|
|
557
827
|
};
|
|
558
828
|
const alignmentStyle = alignmentStyles[alignment] || "";
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
829
|
+
// --- Text + vertical alignment maps ---
|
|
830
|
+
const textAlignMap = {
|
|
831
|
+
left: "left",
|
|
832
|
+
center: "center",
|
|
833
|
+
right: "right",
|
|
834
|
+
justify: "justify",
|
|
563
835
|
};
|
|
564
|
-
const
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
836
|
+
const textAlignStyle = textAlignMap[textAlign] || "center";
|
|
837
|
+
const flexJustify = textAlign === "left"
|
|
838
|
+
? "flex-start"
|
|
839
|
+
: textAlign === "right"
|
|
840
|
+
? "flex-end"
|
|
841
|
+
: "center";
|
|
842
|
+
const flexAlign = verticalAlign === "top"
|
|
843
|
+
? "flex-start"
|
|
844
|
+
: verticalAlign === "bottom"
|
|
845
|
+
? "flex-end"
|
|
846
|
+
: "center";
|
|
847
|
+
// --- Text styling ---
|
|
848
|
+
const textSizeStyle = `font-size:${fontSize}px;line-height:1.3;word-break:break-word;overflow-wrap:break-word;color:${color};`;
|
|
568
849
|
// ============================
|
|
569
850
|
// Modern HTML (non-MSO)
|
|
570
851
|
// ============================
|
|
571
852
|
let nonMsoContent = "";
|
|
853
|
+
// --- Case 1: Image + Text ---
|
|
572
854
|
if (imageUrl && text) {
|
|
573
855
|
nonMsoContent = `
|
|
574
856
|
<div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
@@ -576,13 +858,14 @@ async function convertShapeBlock(blockData) {
|
|
|
576
858
|
border-radius:${resolvedBorderRadius};
|
|
577
859
|
background:${finalBackgroundColor} url('${imageUrl}') center/cover no-repeat;
|
|
578
860
|
overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
579
|
-
<div style="width:100%;height:100%;display:flex
|
|
580
|
-
<div style="${textSizeStyle}
|
|
861
|
+
<div style="width:100%;height:100%;display:flex;justify-content:${flexJustify};align-items:${flexAlign};overflow:hidden;padding:6px;box-sizing:border-box;">
|
|
862
|
+
<div style="${textSizeStyle}text-align:${textAlignStyle};max-width:90%;overflow:hidden;">
|
|
581
863
|
${text}
|
|
582
864
|
</div>
|
|
583
865
|
</div>
|
|
584
866
|
</div>`;
|
|
585
867
|
}
|
|
868
|
+
// --- Case 2: Image only ---
|
|
586
869
|
else if (imageUrl) {
|
|
587
870
|
nonMsoContent = `
|
|
588
871
|
<div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
@@ -594,24 +877,22 @@ async function convertShapeBlock(blockData) {
|
|
|
594
877
|
style="width:100%;height:100%;object-fit:cover;border-radius:${resolvedBorderRadius};display:block;" />
|
|
595
878
|
</div>`;
|
|
596
879
|
}
|
|
880
|
+
// --- Case 3: Text only ---
|
|
597
881
|
else {
|
|
598
|
-
const circlePadding = shape === "circle" ? Math.round(resolvedHeightPx * 0.15) : 8;
|
|
599
882
|
nonMsoContent = `
|
|
600
883
|
<div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
|
|
601
884
|
background:${finalBackgroundColor};
|
|
602
885
|
border:${borderWidth}px ${borderStyle} ${borderColor};
|
|
603
886
|
border-radius:${resolvedBorderRadius};
|
|
604
887
|
overflow:hidden;${alignmentStyle}${customCss || ""}">
|
|
605
|
-
<div style="width:100%;height:100%;display:flex
|
|
606
|
-
<div style="${textSizeStyle}max-width:90%;overflow:hidden;">
|
|
888
|
+
<div style="width:100%;height:100%;display:flex;justify-content:${flexJustify};align-items:${flexAlign};padding:8px;box-sizing:border-box;">
|
|
889
|
+
<div style="${textSizeStyle}text-align:${textAlignStyle};max-width:90%;overflow:hidden;">
|
|
607
890
|
${text || ""}
|
|
608
891
|
</div>
|
|
609
892
|
</div>
|
|
610
893
|
</div>`;
|
|
611
894
|
}
|
|
612
|
-
//
|
|
613
|
-
// Outlook (VML) version
|
|
614
|
-
// ============================
|
|
895
|
+
// Outlook (VML) fallback
|
|
615
896
|
const outlookContent = await appendOutlookForShape(nonMsoContent, resolvedWidthPx, resolvedWidthPx, {
|
|
616
897
|
shape,
|
|
617
898
|
imageUrl,
|
|
@@ -625,13 +906,12 @@ async function convertShapeBlock(blockData) {
|
|
|
625
906
|
textColor: color,
|
|
626
907
|
textSize: fontSize,
|
|
627
908
|
verticalAlign,
|
|
909
|
+
textAlign, // ✅ added
|
|
628
910
|
alignment,
|
|
629
911
|
padding,
|
|
630
912
|
msoBakeImageWithText,
|
|
631
913
|
});
|
|
632
|
-
//
|
|
633
|
-
// Final combined block
|
|
634
|
-
// ============================
|
|
914
|
+
// Combine into table wrapper
|
|
635
915
|
return `
|
|
636
916
|
<table width="100%" style="border-collapse:collapse;table-layout:fixed;">
|
|
637
917
|
<tr>
|
|
@@ -644,15 +924,14 @@ async function convertShapeBlock(blockData) {
|
|
|
644
924
|
</tr>
|
|
645
925
|
</table>`;
|
|
646
926
|
}
|
|
647
|
-
// ---------- Updated VML builder
|
|
648
|
-
function buildVMLShape({ shape, widthPx, heightPx, imageUrl, backgroundColor, borderWidth, borderColor, borderRadius, text, textColor = "#000000", textSize = 14, verticalAlign = "center", msoHasBakedText = false, }) {
|
|
649
|
-
// --- Basic setup ---
|
|
927
|
+
// ---------- Updated VML builder ----------
|
|
928
|
+
function buildVMLShape({ shape, widthPx, heightPx, imageUrl, backgroundColor, borderWidth, borderColor, borderRadius, text, textColor = "#000000", textSize = 14, verticalAlign = "middle", textAlign = "center", msoHasBakedText = false, }) {
|
|
650
929
|
const bw = borderWidth || 0;
|
|
651
930
|
const bc = borderColor || "transparent";
|
|
652
931
|
const borderAttrs = bw > 0 ? `strokeweight="${bw}px" strokecolor="${bc}"` : `stroked="false"`;
|
|
653
932
|
const fillColor = backgroundColor || "#2F80ED";
|
|
933
|
+
// Use frame for img fill so sizing is preserved
|
|
654
934
|
const fillMarkup = `<v:fill ${imageUrl ? `src="${imageUrl}" type="frame" aspect="atleast"` : ""} color="${fillColor}" />`;
|
|
655
|
-
// --- Shape tag ---
|
|
656
935
|
let tag = "rect";
|
|
657
936
|
let extraAttr = "";
|
|
658
937
|
if (shape === "circle" || shape === "oval") {
|
|
@@ -662,15 +941,22 @@ function buildVMLShape({ shape, widthPx, heightPx, imageUrl, backgroundColor, bo
|
|
|
662
941
|
tag = "roundrect";
|
|
663
942
|
extraAttr = `arcsize="${computeArcSize(borderRadius, widthPx)}"`;
|
|
664
943
|
}
|
|
665
|
-
//
|
|
666
|
-
const vAlignMap = { top: "top",
|
|
944
|
+
// maps for vml
|
|
945
|
+
const vAlignMap = { top: "top", middle: "middle", bottom: "bottom" };
|
|
946
|
+
const hAlignMap = {
|
|
947
|
+
left: "left",
|
|
948
|
+
center: "center",
|
|
949
|
+
right: "right",
|
|
950
|
+
justify: "left",
|
|
951
|
+
}; // justify -> left fallback in VML
|
|
667
952
|
const vAlign = vAlignMap[verticalAlign] || "middle";
|
|
668
|
-
const
|
|
669
|
-
|
|
953
|
+
const hAlign = hAlignMap[textAlign] || "center";
|
|
954
|
+
const safeFontSize = Math.max(Math.round(textSize), 10);
|
|
955
|
+
// Build the textbox with table/cell for reliable vertical centering in Outlook
|
|
670
956
|
const textboxMarkup = text && !msoHasBakedText
|
|
671
957
|
? `<v:textbox inset="6pt,6pt,6pt,6pt" style="mso-fit-shape-to-text:false;">
|
|
672
958
|
<div style="display:table;width:100%;height:100%;">
|
|
673
|
-
<div style="display:table-cell;vertical-align:${vAlign};text-align:
|
|
959
|
+
<div style="display:table-cell;vertical-align:${vAlign};text-align:${hAlign};padding:0 6px;">
|
|
674
960
|
<div style="color:${textColor};font-family:Arial, sans-serif;font-size:${safeFontSize}px;line-height:1.3;word-wrap:break-word;">
|
|
675
961
|
${text}
|
|
676
962
|
</div>
|
|
@@ -678,20 +964,17 @@ function buildVMLShape({ shape, widthPx, heightPx, imageUrl, backgroundColor, bo
|
|
|
678
964
|
</div>
|
|
679
965
|
</v:textbox>`
|
|
680
966
|
: `<v:textbox inset="0,0,0,0"><div style="display:none;">.</div></v:textbox>`;
|
|
681
|
-
//
|
|
967
|
+
// Return VML shape
|
|
682
968
|
return `
|
|
683
969
|
<v:${tag} xmlns:v="urn:schemas-microsoft-com:vml"
|
|
684
|
-
style="width:${widthPx}px;height:${heightPx}px;
|
|
685
|
-
mso-position-horizontal:center;
|
|
686
|
-
mso-position-vertical:center;"
|
|
970
|
+
style="width:${widthPx}px;height:${heightPx}px;display:inline-block;"
|
|
687
971
|
${borderAttrs}
|
|
688
972
|
fill="true" fillcolor="${fillColor}"${extraAttr}>
|
|
689
973
|
${fillMarkup}
|
|
690
974
|
${textboxMarkup}
|
|
691
975
|
</v:${tag}>`;
|
|
692
976
|
}
|
|
693
|
-
|
|
694
|
-
async function appendOutlookForShape(content, outerContainerWidth, innerContainerWidth, opts) {
|
|
977
|
+
function appendOutlookForShape(content, outerContainerWidth, innerContainerWidth, opts) {
|
|
695
978
|
const widthPx = Math.round(Math.min(outerContainerWidth, innerContainerWidth));
|
|
696
979
|
const heightPx = Math.max(1, Math.round(opts.heightPx));
|
|
697
980
|
const vml = buildVMLShape({
|
|
@@ -706,14 +989,17 @@ async function appendOutlookForShape(content, outerContainerWidth, innerContaine
|
|
|
706
989
|
text: opts.text,
|
|
707
990
|
textColor: opts.textColor,
|
|
708
991
|
textSize: opts.textSize,
|
|
992
|
+
verticalAlign: opts.verticalAlign,
|
|
993
|
+
textAlign: opts.textAlign,
|
|
709
994
|
msoHasBakedText: Boolean(opts.msoBakeImageWithText),
|
|
710
995
|
});
|
|
711
996
|
const pad = opts.padding || {};
|
|
712
997
|
const align = opts.alignment || "left";
|
|
713
998
|
const valign = opts.verticalAlign || "middle";
|
|
999
|
+
// Outlook wrapper table ensures the cell's valign works if vml alone doesn't
|
|
714
1000
|
return `<!--[if mso]>
|
|
715
1001
|
<table align="${align}" border="0" cellpadding="0" cellspacing="0"
|
|
716
|
-
style="width:${widthPx}px;height:${heightPx}px;">
|
|
1002
|
+
style="width:${widthPx}px;height:${heightPx}px;border-collapse:collapse;">
|
|
717
1003
|
<tr>
|
|
718
1004
|
<td valign="${valign}"
|
|
719
1005
|
style="padding:${pad.top || 0}px ${pad.right || 0}px ${pad.bottom || 0}px ${pad.left || 0}px;">
|
|
@@ -721,7 +1007,7 @@ async function appendOutlookForShape(content, outerContainerWidth, innerContaine
|
|
|
721
1007
|
</td>
|
|
722
1008
|
</tr>
|
|
723
1009
|
</table>
|
|
724
|
-
|
|
1010
|
+
<![endif]-->`;
|
|
725
1011
|
}
|
|
726
1012
|
function convertVerticalDividerBlockToHtml(blockData) {
|
|
727
1013
|
const { style } = blockData.data;
|