email-builder-utils 1.1.47 → 1.1.49

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":"button.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/button.ts"],"names":[],"mappings":"AAYA,wBAAgB,sBAAsB,CAAC,UAAU,EAAE;IAAE,KAAK,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;EA6ErG;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,GAAG,UAgEhD"}
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/button.ts"],"names":[],"mappings":"AAIA,wBAAgB,sBAAsB,CAAC,UAAU,EAAE;IAAE,KAAK,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;EA6ErG;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,GAAG,UAgEhD"}
@@ -5,13 +5,6 @@ exports.convertButtonBlock = convertButtonBlock;
5
5
  const buildStyles_1 = require("../buildStyles");
6
6
  const fontFallback_1 = require("../fontFallback");
7
7
  const common_1 = require("../common");
8
- function encodeBlockPropsAttr(props) {
9
- return JSON.stringify(props)
10
- .replace(/&/g, "&")
11
- .replace(/"/g, """)
12
- .replace(/</g, "&lt;")
13
- .replace(/>/g, "&gt;");
14
- }
15
8
  function appendOutlookForButton(buttonData) {
16
9
  const { style, text, navigateToUrl } = buttonData;
17
10
  const pad = style.buttonPadding || {};
@@ -93,7 +86,7 @@ function convertButtonBlock(blockData) {
93
86
  text: text || "",
94
87
  navigateToUrl: navigateToUrl || "",
95
88
  });
96
- const buttonBlockProps = encodeBlockPropsAttr({
89
+ const buttonBlockProps = (0, common_1.encodeBlockPropsAttr)({
97
90
  buttonText: text || "",
98
91
  navigateToUrl: navigateToUrl || "",
99
92
  buttonColor: computed.bgColor,
@@ -1 +1 @@
1
- {"version":3,"file":"dividers.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/dividers.ts"],"names":[],"mappings":"AAIA,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,GAAG,UAuCvD;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,GAAG,UAKtD;AAED,wBAAgB,iCAAiC,CAAC,SAAS,EAAE,GAAG,UAuB/D"}
1
+ {"version":3,"file":"dividers.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/dividers.ts"],"names":[],"mappings":"AAIA,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,GAAG,UAuCvD;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,GAAG,UAKtD;AAED,wBAAgB,iCAAiC,CAAC,SAAS,EAAE,GAAG,UAwB/D"}
@@ -52,11 +52,12 @@ function convertVerticalDividerBlockToHtml(blockData) {
52
52
  const { width, height, dividerColor, padding, backgroundColor } = style;
53
53
  const visibilityClass = (0, common_1.getVisibilityClass)(props);
54
54
  const outerStyles = (0, buildStyles_1.buildStyles)({ padding, backgroundColor }, {
55
- perChanges: [], pxChanges: buildStyles_1.allPxAttributes,
55
+ perChanges: [],
56
+ pxChanges: buildStyles_1.allPxAttributes,
56
57
  });
57
58
  return `
58
59
  <table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
59
- style="${buildStyles_1.tableCommonStyle}; max-width:600px;" class="${visibilityClass}">
60
+ style="${buildStyles_1.tableCommonStyle}; max-width:600px;" class="${visibilityClass}" data-block-type="vdivider">
60
61
  <tr>
61
62
  <td style="${outerStyles}; text-align:center; vertical-align:middle;">
62
63
  <!--[if mso | IE]>
@@ -1 +1 @@
1
- {"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/grid.ts"],"names":[],"mappings":"AAKA,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,mBAiO1F;AAED,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,GAAG,EACd,QAAQ,EAAE,GAAG,EACb,gBAAgB,EAAE,MAAM,EACxB,iBAAiB,EAAE,MAAM,EACzB,mBAAmB,UAAQ;;;GAuD5B"}
1
+ {"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/grid.ts"],"names":[],"mappings":"AAMA,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,mBAiO1F;AAED,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,GAAG,EACd,QAAQ,EAAE,GAAG,EACb,gBAAgB,EAAE,MAAM,EACxB,iBAAiB,EAAE,MAAM,EACzB,mBAAmB,UAAQ;;;GAoE5B"}
@@ -6,6 +6,7 @@ const buildStyles_1 = require("../buildStyles");
6
6
  const gradientUtils_1 = require("../gradientUtils");
7
7
  const common_1 = require("../common");
8
8
  const jsonToHTML_1 = require("../jsonToHTML");
9
+ const outlookSupport_1 = require("../outlookSupport");
9
10
  async function convertGridBlock(blockData, rootData, cellWidthInPx) {
10
11
  const { style = {}, childrenIds = [], props } = blockData.data;
11
12
  const { columns = 1, cellWidths = [], responsive = true } = props;
@@ -56,10 +57,10 @@ async function convertGridBlock(blockData, rootData, cellWidthInPx) {
56
57
  const visualRows = Math.ceil(total / columns);
57
58
  const msoTableWidth = Math.min(cellWidthInPx, 600);
58
59
  const msoBgColor = !rawBgImageUrl && !isGradient ? (backgroundColor || '') : '';
59
- const msoBgAttr = msoBgColor ? ` bgcolor="${msoBgColor}"` : '';
60
+ const msoBgAttr = msoBgColor ? ` bgcolor="${(0, outlookSupport_1.toOutlookBgColor)(msoBgColor)}"` : '';
60
61
  const msoBgStyle = msoBgColor ? `background-color:${msoBgColor};` : '';
61
62
  const innerBgTransparent = (rawBgImageUrl || isGradient) ? 'background-color:transparent;' : '';
62
- const nonMsoBgAttr = !rawBgImageUrl && !isGradient && backgroundColor && !divBorderStyle ? ` bgcolor="${backgroundColor}"` : '';
63
+ const nonMsoBgAttr = !rawBgImageUrl && !isGradient && backgroundColor && !divBorderStyle ? ` bgcolor="${(0, outlookSupport_1.toOutlookBgColor)(backgroundColor)}"` : '';
63
64
  const divWrapBg = divBorderStyle && backgroundColor && !rawBgImageUrl && !isGradient
64
65
  ? ` background-color:${backgroundColor};`
65
66
  : '';
@@ -124,7 +125,7 @@ async function convertGridBlock(blockData, rootData, cellWidthInPx) {
124
125
  if (childVisible) {
125
126
  const { html: childHtml, styles } = await convertGridCellBlock(child, rootData, widthPercent, adjustedTableWidth, Boolean(divBorderStyle));
126
127
  const cellBgColor = cellStyle.backgroundColor || '';
127
- const cellBgAttr = cellBgColor ? ` bgcolor="${cellBgColor}"` : '';
128
+ const cellBgAttr = cellBgColor ? ` bgcolor="${(0, outlookSupport_1.toOutlookBgColor)(cellBgColor)}"` : '';
128
129
  html += `
129
130
  <td
130
131
  width="${cellWidthPx}"${cellBgAttr}
@@ -207,15 +208,41 @@ async function convertGridCellBlock(blockData, rootData, cellWidthPercent, paren
207
208
  const { style = {}, childrenIds = [], props = {} } = blockData.data;
208
209
  const { borderRadius: cellBorderRadius, borderWidth: cellBorderWidth, borderStyle: cellBorderStyleProp, borderColor: cellBorderColor, border: cellBorderShorthand, ...styleWithoutBorder } = style;
209
210
  const stripBgFromTd = Boolean(cellBorderRadius) || parentGridHasBorder;
211
+ // Omit backgroundColor entirely rather than setting 'transparent' — an explicit
212
+ // background-color:transparent can defeat the bgcolor HTML attribute in Old Outlook
213
+ // (Word engine), leaving the cell with no background at all.
210
214
  const styleForTd = stripBgFromTd
211
- ? { ...styleWithoutBorder, backgroundColor: 'transparent' }
215
+ ? { ...styleWithoutBorder, backgroundColor: undefined }
212
216
  : styleWithoutBorder;
213
217
  const styles = (0, buildStyles_1.buildStyles)(styleForTd, { perChanges: [], pxChanges: buildStyles_1.allPxAttributes });
214
218
  const parts = [];
215
219
  const cellWidthPx = Math.round((cellWidthPercent / 100) * parentCellWidthPx);
216
- const cellPad = styleWithoutBorder?.padding || {};
217
- const cellPadLeft = Number.isFinite(cellPad.left) ? cellPad.left : 0;
218
- const cellPadRight = Number.isFinite(cellPad.right) ? cellPad.right : 0;
220
+ const rawPad = styleWithoutBorder?.padding;
221
+ let cellPadLeft = 0;
222
+ let cellPadRight = 0;
223
+ if (rawPad && typeof rawPad === 'object') {
224
+ cellPadLeft = Number.isFinite(rawPad.left) ? rawPad.left : 0;
225
+ cellPadRight = Number.isFinite(rawPad.right) ? rawPad.right : 0;
226
+ }
227
+ else if (typeof rawPad === 'string') {
228
+ const parts = rawPad.trim().split(/\s+/).map(v => parseFloat(v) || 0);
229
+ if (parts.length >= 4) {
230
+ cellPadRight = parts[1];
231
+ cellPadLeft = parts[3];
232
+ }
233
+ else if (parts.length === 3) {
234
+ cellPadRight = parts[1];
235
+ cellPadLeft = parts[1];
236
+ }
237
+ else if (parts.length === 2) {
238
+ cellPadRight = parts[1];
239
+ cellPadLeft = parts[1];
240
+ }
241
+ else if (parts.length === 1) {
242
+ cellPadRight = parts[0];
243
+ cellPadLeft = parts[0];
244
+ }
245
+ }
219
246
  const contentWidthPx = Math.max(cellWidthPx - cellPadLeft - cellPadRight, 20);
220
247
  const safeCellWidthPx = Math.min(contentWidthPx, 600);
221
248
  for (const childId of childrenIds) {
@@ -42,7 +42,7 @@ async function convertImageBlock(blockData, cellWidthInPx) {
42
42
  const finalWidth = Math.min(scaledWidth, innerContainerWidth, originalWidth);
43
43
  const finalHeight = Math.round((finalWidth / originalWidth) * originalHeight);
44
44
  const imageTagStyles = (0, buildStyles_1.buildStyles)({ borderStyle, borderRadius, borderColor, borderWidth }, { perChanges: [], pxChanges: buildStyles_1.addPxToAttributes });
45
- const imageElement = `<img src="${imageUrl}" alt="${altText || "Image"}" border="0" width="${finalWidth}" height="${finalHeight}" style="${imageTagStyles}; display:block; max-width:100%; height:auto; line-height: 0;" />`;
45
+ const imageElement = `<img src="${imageUrl}" alt="${altText || "Image"}" border="0" width="${finalWidth}" height="${finalHeight}" style="${imageTagStyles}; display:block; width:${finalWidth}px; height:${finalHeight}px; max-width:100%; line-height:0; -ms-interpolation-mode:bicubic;" />`;
46
46
  const percentWidth = typeof width === "string" && width.endsWith("%")
47
47
  ? width
48
48
  : typeof width === "number" ? `${width}%` : "100%";
@@ -1 +1 @@
1
- {"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/shape.ts"],"names":[],"mappings":"AAuHA,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,GAAG,mBAyHrD"}
1
+ {"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/shape.ts"],"names":[],"mappings":"AAuHA,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,GAAG,mBA2MrD"}
@@ -100,11 +100,19 @@ async function convertShapeBlock(blockData) {
100
100
  const visibilityClass = (0, common_1.getVisibilityClass)(props);
101
101
  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 || {};
102
102
  const borderRadiusMap = {
103
- rectangle: "0", rounded: "10px", circle: "50%", oval: "50%",
103
+ rectangle: "0",
104
+ rounded: "10px",
105
+ circle: "50%",
106
+ oval: "50%",
104
107
  };
105
108
  let resolvedBorderRadius = borderRadius || borderRadiusMap[shape] || "0";
106
- let resolvedWidthPx = typeof width === "number" ? width : parseInt(width.toString().replace("px", ""), 10) || 100;
107
- let resolvedHeightPx = typeof height === "number" ? height : parseInt(height.toString().replace("px", ""), 10) || 150;
109
+ let resolvedWidthPx = typeof width === "number"
110
+ ? width
111
+ : parseInt(width.toString().replace("px", ""), 10) || 100;
112
+ let resolvedHeightPx = typeof height === "number"
113
+ ? height
114
+ : parseInt(height.toString().replace("px", ""), 10) || 150;
115
+ // --- Shape-specific constraints ---
108
116
  if (shape === "circle") {
109
117
  const side = Math.min(resolvedWidthPx, resolvedHeightPx);
110
118
  resolvedWidthPx = side;
@@ -115,16 +123,28 @@ async function convertShapeBlock(blockData) {
115
123
  resolvedBorderRadius = "50% / 50%";
116
124
  }
117
125
  const finalBackgroundColor = shapeColor || backgroundColor;
126
+ // --- Horizontal alignment for outer container ---
118
127
  const alignmentStyles = {
119
128
  left: "margin-right:auto;margin-left:0;",
120
129
  center: "margin-left:auto;margin-right:auto;",
121
130
  right: "margin-left:auto;margin-right:0;",
122
131
  };
123
132
  const alignmentStyle = alignmentStyles[alignment] || "";
124
- const textAlignMap = { left: "left", center: "center", right: "right", justify: "justify" };
133
+ // --- Text + vertical alignment maps ---
134
+ const textAlignMap = {
135
+ left: "left",
136
+ center: "center",
137
+ right: "right",
138
+ justify: "justify",
139
+ };
125
140
  const textAlignStyle = textAlignMap[textAlign] || "center";
141
+ // --- Text styling ---
126
142
  const textSizeStyle = `font-size:${fontSize}px;line-height:1.3;word-break:break-word;overflow-wrap:break-word;color:${color};`;
143
+ // ============================
144
+ // Modern HTML (non-MSO)
145
+ // ============================
127
146
  let nonMsoContent = "";
147
+ // --- Case 1: Image + Text ---
128
148
  if (imageUrl && text) {
129
149
  nonMsoContent = `
130
150
  <div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
@@ -148,6 +168,7 @@ async function convertShapeBlock(blockData) {
148
168
  </table>
149
169
  </div>`;
150
170
  }
171
+ // --- Case 2: Image only ---
151
172
  else if (imageUrl) {
152
173
  nonMsoContent = `
153
174
  <div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
@@ -159,6 +180,7 @@ async function convertShapeBlock(blockData) {
159
180
  style="width:100%;height:100%;object-fit:cover;border-radius:${resolvedBorderRadius};display:block;" />
160
181
  </div>`;
161
182
  }
183
+ // --- Case 3: Text only ---
162
184
  else {
163
185
  nonMsoContent = `
164
186
  <div style="display:inline-block;width:${resolvedWidthPx}px;height:${resolvedHeightPx}px;
@@ -178,15 +200,50 @@ async function convertShapeBlock(blockData) {
178
200
  </table>
179
201
  </div>`;
180
202
  }
203
+ // Outlook (VML) fallback
181
204
  const outlookContent = appendOutlookForShape(nonMsoContent, resolvedWidthPx, resolvedWidthPx, {
182
- shape, imageUrl, backgroundColor, shapeColor,
183
- borderWidth, borderColor, borderRadius: resolvedBorderRadius,
184
- heightPx: resolvedHeightPx, text, textColor: color,
185
- textSize: fontSize, verticalAlign, textAlign, alignment,
186
- padding, msoBakeImageWithText,
205
+ shape,
206
+ imageUrl,
207
+ backgroundColor,
208
+ shapeColor,
209
+ borderWidth,
210
+ borderColor,
211
+ borderRadius: resolvedBorderRadius,
212
+ heightPx: resolvedHeightPx,
213
+ text,
214
+ textColor: color,
215
+ textSize: fontSize,
216
+ verticalAlign,
217
+ textAlign, // ✅ added
218
+ alignment,
219
+ padding,
220
+ msoBakeImageWithText,
187
221
  }, visibilityClass);
222
+ const shapeBlockProps = (0, common_1.encodeBlockPropsAttr)({
223
+ shape: shape || 'rectangle',
224
+ width: resolvedWidthPx,
225
+ height: resolvedHeightPx,
226
+ shapeColor: shapeColor || '',
227
+ backgroundColor: backgroundColor || '',
228
+ borderRadius: resolvedBorderRadius,
229
+ borderWidth,
230
+ borderColor,
231
+ borderStyle,
232
+ imageUrl: imageUrl || '',
233
+ text: text || '',
234
+ color,
235
+ fontSize,
236
+ textAlign,
237
+ verticalAlign,
238
+ alignment,
239
+ padding,
240
+ customCss: customCss || '',
241
+ hideOnDesktop: Boolean(props.hideOnDesktop),
242
+ hideOnMobile: Boolean(props.hideOnMobile),
243
+ });
244
+ // Combine into table wrapper
188
245
  return `
189
- <table width="100%" style="border-collapse:collapse;table-layout:fixed;max-width:600px;" class="${visibilityClass}">
246
+ <table width="100%" style="border-collapse:collapse;table-layout:fixed;max-width:600px;" class="${visibilityClass}" data-block-type="shape" data-block-props="${shapeBlockProps}">
190
247
  <tr>
191
248
  <td style="padding:${padding.top || 0}px ${padding.right || 0}px ${padding.bottom || 0}px ${padding.left || 0}px;text-align:${alignment};">
192
249
  ${outlookContent}
@@ -1 +1 @@
1
- {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/text.ts"],"names":[],"mappings":"AAKA,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,CAAC,EAAE,MAAM,UAsItE"}
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/text.ts"],"names":[],"mappings":"AAKA,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,CAAC,EAAE,MAAM,UA4ItE"}
@@ -8,7 +8,7 @@ const common_1 = require("../common");
8
8
  function convertTextBlock(blockData, cellWidthInPx) {
9
9
  const { style, props } = blockData.data;
10
10
  const visibilityClass = (0, common_1.getVisibilityClass)(props);
11
- const { width, backgroundColor, padding, borderRadius, borderStyle, borderColor, borderWidth, textContainerBackgroundColor, textContainerPadding, fontSize, backgroundImage, whiteSpace: _whiteSpace, ...rest } = style;
11
+ const { width, backgroundColor, padding, borderRadius, borderStyle, borderColor, borderWidth, textContainerBackgroundColor, textContainerPadding, fontSize, backgroundImage, backgroundPosition, backgroundRepeat, backgroundSize, whiteSpace: _whiteSpace, ...rest } = style;
12
12
  const bgImageStr = typeof backgroundImage === 'string' ? backgroundImage : '';
13
13
  const customCssStr = rest.customCss || '';
14
14
  const gradientInCustomCss = !bgImageStr.includes('gradient(') && customCssStr.includes('gradient(')
@@ -67,9 +67,12 @@ function convertTextBlock(blockData, cellWidthInPx) {
67
67
  return `<v:fill type="gradient" color="${c1}" color2="${c2}" angle="${vmlAngle}" />`;
68
68
  })()
69
69
  : `<v:fill type="frame" src="${rawBgImageUrl}" color="${fallbackBgColor}" />`;
70
+ const bgPosition = backgroundPosition ?? 'center center';
71
+ const bgSize = backgroundSize ?? 'cover';
72
+ const bgRepeat = backgroundRepeat ?? 'no-repeat';
70
73
  const bgCss = isGradient
71
74
  ? `background:${effectiveGradient};`
72
- : `background-image:url('${rawBgImageUrl}'); background-position:center center; background-size:cover; background-repeat:no-repeat;`;
75
+ : `background-image:url('${rawBgImageUrl}'); background-position:${bgPosition}; background-size:${bgSize}; background-repeat:${bgRepeat};`;
73
76
  const wrappedContent = `
74
77
  <table border="0" cellpadding="0" cellspacing="0" width="100%" role="presentation"
75
78
  style="border-collapse:collapse;width:100%;max-width:${msoWidth}px;" class="${visibilityClass}">
@@ -1 +1 @@
1
- {"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/video.ts"],"names":[],"mappings":"AAUA,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,mBA0H5E"}
1
+ {"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/video.ts"],"names":[],"mappings":"AAUA,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,GAAG,EACd,aAAa,EAAE,MAAM,mBAiKtB"}
@@ -30,6 +30,7 @@ async function convertVideoBlock(blockData, cellWidthInPx) {
30
30
  catch (_) { }
31
31
  }
32
32
  }
33
+ // Width / dimensions
33
34
  let percentWidth = '100%';
34
35
  if (typeof style?.width === 'string' && style.width.trim().endsWith('%')) {
35
36
  percentWidth = style.width.trim();
@@ -42,24 +43,51 @@ async function convertVideoBlock(blockData, cellWidthInPx) {
42
43
  const innerContainerWidth = (parseFloat(percentWidth) / 100) * (cellWidthInPx - paddingLeft - paddingRight);
43
44
  const thumbnailW = Math.round(innerContainerWidth);
44
45
  const thumbnailH = Math.round(thumbnailW / (16 / 9));
46
+ // Border
45
47
  const borderRadius = parseInt(style?.borderRadius || 0);
46
48
  const borderWidth = parseInt(style?.borderWidth || 0);
47
49
  const borderColor = style?.borderColor || 'transparent';
48
50
  const borderStyleProp = style?.borderStyle || 'solid';
49
- const outerContainerStyles = (0, buildStyles_1.buildStyles)({ ...style, width: undefined, borderColor: undefined, borderRadius: undefined, borderWidth: undefined, borderStyle: undefined }, { perChanges: buildStyles_1.addPxOrPerToAttributes, pxChanges: buildStyles_1.addPxToAttributes });
51
+ const outerContainerStyles = (0, buildStyles_1.buildStyles)({
52
+ ...style,
53
+ width: undefined,
54
+ borderColor: undefined,
55
+ borderRadius: undefined,
56
+ borderWidth: undefined,
57
+ borderStyle: undefined,
58
+ }, { perChanges: buildStyles_1.addPxOrPerToAttributes, pxChanges: buildStyles_1.addPxToAttributes });
50
59
  const align = style?.textAlign || 'left';
51
60
  const playIconW = 65;
52
61
  const playIconH = 46;
62
+ // ── Industry-standard VML + background-image table approach ──────────────────
63
+ // Mirrors the pattern used by professional email builders (e.g. Beefree):
64
+ //
65
+ // VML (<!--[if vml]>): all Outlook / Word rendering engine versions.
66
+ // v:group wraps thumbnail (v:rect frame fill) + vector play button
67
+ // (v:oval white circle + v:shape black triangle). No external image needed.
68
+ //
69
+ // Non-VML (<!--[if !vml]>): Gmail, Apple Mail, Yahoo, Outlook.com, EML viewers.
70
+ // thumbnail as `background` attribute + inline background-image on <table>.
71
+ // 3-column layout: [25% spacer GIF] [50% play icon, centred] [25% spacer].
72
+ // The spacer GIF has a 4:9 aspect ratio — when it fills the 25% column its
73
+ // rendered height equals thumbnailWidth × 9/16, keeping the table at 16:9
74
+ // without any fixed `height` CSS (which is stripped by many clients).
75
+ // VML coordinate positions for the play button (in the v:group coord space).
53
76
  const ovalSize = 65;
54
77
  const ovalLeft = Math.round(thumbnailW / 2 - ovalSize / 2);
55
78
  const ovalTop = Math.round(thumbnailH / 2 - ovalSize / 2);
56
79
  const triW = 23;
57
80
  const triH = 33;
81
+ // Triangle centre is slightly right of geometric centre for visual balance.
58
82
  const triLeft = Math.round(thumbnailW / 2 - triW / 2 + 3);
59
83
  const triTop = Math.round(thumbnailH / 2 - triH / 2);
60
- const borderCss = borderWidth > 0 ? `border:${borderWidth}px ${borderStyleProp} ${borderColor};` : '';
84
+ const borderCss = borderWidth > 0
85
+ ? `border:${borderWidth}px ${borderStyleProp} ${borderColor};`
86
+ : '';
61
87
  const radiusCss = borderRadius > 0 ? `border-radius:${borderRadius}px; overflow:hidden;` : '';
88
+ // min-height fallback for clients that ignore the spacer GIF (e.g. some webmail).
62
89
  const minHeight = Math.round(thumbnailW * 0.3);
90
+ // VML block — shown only in Outlook (Word engine supports VML, not standard HTML).
63
91
  const outlookContent = hideOnDesktop ? '' : `<!--[if vml]>
64
92
  <v:group xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word"
65
93
  coordsize="${thumbnailW},${thumbnailH}" coordorigin="0,0"
@@ -76,6 +104,7 @@ async function convertVideoBlock(blockData, cellWidthInPx) {
76
104
  style="position:absolute;left:${triLeft};top:${triTop};width:${triW};height:${triH};" />
77
105
  </v:group>
78
106
  <![endif]-->`;
107
+ // Non-VML block — shown in all clients except Outlook.
79
108
  const nonMsoContent = `<!--[if !vml]><!-->
80
109
  <a href="${videoLink}" target="_blank"
81
110
  style="display:block; text-decoration:none; background-image:url('${resolvedThumbnail}'); background-size:cover; background-position:center; ${borderCss}${radiusCss}">
@@ -101,7 +130,10 @@ async function convertVideoBlock(blockData, cellWidthInPx) {
101
130
  return `
102
131
  <table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
103
132
  style="border-collapse:collapse; max-width:600px; margin:0; padding:0;"
104
- class="${visibilityClass}">
133
+ class="${visibilityClass}" data-block-type="video"
134
+ data-video-url="${videoUrl || ''}" data-youtube-url="${youtubeVideoUrl || ''}"
135
+ data-thumbnail-url="${thumbnailUrl || ''}" data-alt-text="${altText || ''}"
136
+ data-width="${typeof style?.width === 'number' ? style.width : 100}">
105
137
  <tr>
106
138
  <td align="${align}" style="${outerContainerStyles}">
107
139
  <table border="0" cellpadding="0" cellspacing="0" role="presentation"
@@ -4,4 +4,5 @@ export declare function getVisibilityClass(props?: {
4
4
  hideOnDesktop?: boolean;
5
5
  hideOnMobile?: boolean;
6
6
  }): string;
7
+ export declare function encodeBlockPropsAttr(props: Record<string, any>): string;
7
8
  //# sourceMappingURL=common.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/utils/common.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAqBvD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAIrD,CAAC;AAGF,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,UASA"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/utils/common.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAqBvD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAIrD,CAAC;AAGF,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,UASA;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAQvE"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.extractVimeoId = exports.extractYouTubeId = void 0;
4
4
  exports.getVisibilityClass = getVisibilityClass;
5
+ exports.encodeBlockPropsAttr = encodeBlockPropsAttr;
5
6
  const extractYouTubeId = (url) => {
6
7
  try {
7
8
  const u = new URL(url);
@@ -43,3 +44,12 @@ function getVisibilityClass(props) {
43
44
  .filter(Boolean)
44
45
  .join(" ");
45
46
  }
47
+ function encodeBlockPropsAttr(props) {
48
+ // HTML attribute-safe JSON string.
49
+ // Keep it minimal and deterministic: the importer reads it back via getAttribute + JSON.parse.
50
+ return JSON.stringify(props)
51
+ .replace(/&/g, "&amp;")
52
+ .replace(/"/g, "&quot;")
53
+ .replace(/</g, "&lt;")
54
+ .replace(/>/g, "&gt;");
55
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"convertJsonToHtml.d.ts","sourceRoot":"","sources":["../../src/utils/convertJsonToHtml.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,GAAU,UAAU,GAAG,oBAwHpD,CAAC"}
1
+ {"version":3,"file":"convertJsonToHtml.d.ts","sourceRoot":"","sources":["../../src/utils/convertJsonToHtml.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,GAAU,UAAU,GAAG,oBAuLpD,CAAC"}
@@ -20,6 +20,7 @@ const convertJsonToHtml = async (jsonData) => {
20
20
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
21
21
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
22
22
  <meta name="x-apple-disable-message-reformatting" />
23
+ <meta name="format-detection" content="telephone=no,address=no,email=no,date=no,url=no" />
23
24
  <!--[if gte mso 9]><xml>
24
25
  <o:OfficeDocumentSettings>
25
26
  <o:AllowPNG/>
@@ -27,83 +28,145 @@ const convertJsonToHtml = async (jsonData) => {
27
28
  </o:OfficeDocumentSettings>
28
29
  </xml><![endif]-->
29
30
  <style>
30
- .responsive-table {
31
- width: 100%;
32
- max-width: 600px;
31
+ html, body {
32
+ margin: 0 !important;
33
+ padding: 0 !important;
34
+ width: 100% !important;
35
+ -ms-text-size-adjust: 100%;
36
+ -webkit-text-size-adjust: 100%;
37
+ }
38
+
39
+ body, table, td, p, a {
40
+ font-family: ${(0, fontFallback_1.withFontFallback)(fontFamily)};
41
+ }
42
+
43
+ table, td {
44
+ mso-table-lspace: 0pt;
45
+ mso-table-rspace: 0pt;
46
+ border-collapse: collapse !important;
47
+ }
48
+
49
+ img {
50
+ -ms-interpolation-mode: bicubic;
51
+ border: 0;
52
+ outline: none;
53
+ text-decoration: none;
54
+ display: block;
55
+ height: auto;
56
+ line-height: 100%;
57
+ }
58
+
59
+ a {
60
+ text-decoration: none;
61
+ color: inherit;
62
+ }
63
+
64
+ .email-container {
65
+ width: 100%;
66
+ max-width: 600px;
67
+ margin: 0 auto;
68
+ }
69
+
70
+ .stack-column,
71
+ .stack-column-cell {
72
+ vertical-align: top;
73
+ }
74
+
75
+ .hide-mobile {
76
+ display: block !important;
77
+ max-height: none !important;
78
+ overflow: visible !important;
79
+ }
80
+
81
+ .hide-desktop {
82
+ display: none !important;
83
+ max-height: 0 !important;
84
+ overflow: hidden !important;
85
+ mso-hide: all !important;
86
+ }
87
+
88
+ @media only screen and (max-width: 600px) {
89
+ .email-container {
90
+ width: 100% !important;
91
+ max-width: 100% !important;
33
92
  }
34
- @media only screen and (max-width: 600px) {
35
- .responsive-table {
36
- width: 100% !important;
37
- }
38
- .stack-column,
39
- .stack-column td {
40
- display: block !important;
41
- width: 100% !important;
42
- max-width: 100% !important;
43
- }
93
+
94
+ .stack-column,
95
+ .stack-column-cell {
96
+ display: block !important;
97
+ width: 100% !important;
98
+ max-width: 100% !important;
44
99
  }
100
+
45
101
  .hide-mobile {
46
- display: block !important;
47
- }
48
-
49
- .hide-desktop {
50
- display: block !important;
51
- mso-hide: all !important; /* Hide in Outlook (treated as desktop) */
52
- }
53
-
54
- @media only screen and (max-width: 600px) {
55
- .hide-mobile {
56
- display: none !important;
57
- max-height: 0 !important;
58
- overflow: hidden !important;
59
- mso-hide: all !important;
60
- }
61
- }
62
-
63
- @media only screen and (min-width: 601px) {
64
- .hide-desktop {
65
- display: none !important;
66
- max-height: 0 !important;
67
- overflow: hidden !important;
68
- mso-hide: all !important;
69
- }
70
- }
71
-
72
- </style>
73
- </head>
74
- <body style="margin:0; padding:0; background-color:${canvasColor};">
75
- <center style="width:100%; background-color:${canvasColor};">
76
- <table
77
- class="responsive-table"
78
- role="presentation"
79
- bgcolor="${canvasColor}"
80
- cellpadding="0"
81
- cellspacing="0"
82
- border="0"
83
- width="600"
84
- align="center"
85
- style="
86
- font-family: ${(0, fontFallback_1.withFontFallback)(fontFamily)};
87
- margin: 0 auto;
88
- table-layout:fixed;
89
- width:600px;
90
- max-width:600px;
91
- background-color: ${canvasColor};
92
- ${textColor ? `color: ${textColor};` : ''}
93
- ${borderWidth ? `border: ${borderWidth}px ${borderStyle || 'solid'} ${borderColor || 'transparent'};` : ''}
94
- ${borderRadius ? `border-radius: ${borderRadius}px;` : ''}"
95
- >
96
- <tbody>
97
- <tr>
98
- <td style="padding: ${top}px ${right}px ${bottom}px ${left}px;">
99
- ${blocksHtml.join("")}
100
- </td>
101
- </tr>
102
- </tbody>
103
- </table>
104
- </center>
105
- </body>
106
- </html>`;
102
+ display: none !important;
103
+ max-height: 0 !important;
104
+ overflow: hidden !important;
105
+ mso-hide: all !important;
106
+ }
107
+
108
+ .hide-desktop {
109
+ display: block !important;
110
+ max-height: none !important;
111
+ overflow: visible !important;
112
+ }
113
+ }
114
+ </style>
115
+ </head>
116
+ <body style="margin:0; padding:0; background-color:${canvasColor || '#ffffff'};">
117
+ <center style="width:100%; background-color:${canvasColor || '#ffffff'};">
118
+
119
+ <table role="presentation" width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="${canvasColor || '#ffffff'}">
120
+ <tr>
121
+ <td align="center">
122
+
123
+ <!--[if mso]>
124
+ <table role="presentation" border="0" cellspacing="0" cellpadding="0" width="600">
125
+ <tr>
126
+ <td>
127
+ <![endif]-->
128
+
129
+ <table
130
+ role="presentation"
131
+ class="email-container"
132
+ bgcolor="${canvasColor || '#ffffff'}"
133
+ cellpadding="0"
134
+ cellspacing="0"
135
+ border="0"
136
+ width="100%"
137
+ style="
138
+ font-family: ${(0, fontFallback_1.withFontFallback)(fontFamily)};
139
+ table-layout: fixed;
140
+ width: 100%;
141
+ max-width: 600px;
142
+ margin: 0 auto;
143
+ background-color: ${canvasColor || '#ffffff'};
144
+ ${textColor ? `color: ${textColor};` : ''}
145
+ ${borderWidth ? `border: ${borderWidth}px ${borderStyle || 'solid'} ${borderColor || 'transparent'};` : ''}
146
+ ${borderRadius ? `border-radius: ${borderRadius}px;` : ''}"
147
+ >
148
+ <tbody>
149
+ <tr>
150
+ <td style="padding: ${top}px ${right}px ${bottom}px ${left}px;">
151
+ ${blocksHtml.join("")}
152
+ </td>
153
+ </tr>
154
+ </tbody>
155
+ </table>
156
+
157
+ <!--[if mso]>
158
+ </td>
159
+ </tr>
160
+ </table>
161
+ <![endif]-->
162
+
163
+ </td>
164
+ </tr>
165
+ </table>
166
+
167
+ </center>
168
+ </body>
169
+ </html>`;
107
170
  return rawHtml;
108
171
  };
109
172
  exports.convertJsonToHtml = convertJsonToHtml;
@@ -1,3 +1,2 @@
1
- export { tableCommonStyle } from "./buildStyles";
2
1
  export declare function convertToHtml(blockData: any, rootData: any, cellWidthInPx: number): Promise<string>;
3
2
  //# sourceMappingURL=jsonToHTML.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jsonToHTML.d.ts","sourceRoot":"","sources":["../../src/utils/jsonToHTML.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,wBAAsB,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,mBAuBvF"}
1
+ {"version":3,"file":"jsonToHTML.d.ts","sourceRoot":"","sources":["../../src/utils/jsonToHTML.ts"],"names":[],"mappings":"AAaA,wBAAsB,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,mBAuBvF"}
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.tableCommonStyle = void 0;
4
3
  exports.convertToHtml = convertToHtml;
5
4
  const types_1 = require("../types");
6
5
  const text_1 = require("./blocks/text");
@@ -10,8 +9,8 @@ const grid_1 = require("./blocks/grid");
10
9
  const dividers_1 = require("./blocks/dividers");
11
10
  const video_1 = require("./blocks/video");
12
11
  const shape_1 = require("./blocks/shape");
13
- var buildStyles_1 = require("./buildStyles");
14
- Object.defineProperty(exports, "tableCommonStyle", { enumerable: true, get: function () { return buildStyles_1.tableCommonStyle; } });
12
+ // Update: Use Gmail Mobile friendly tableCommonStyle
13
+ // export const tableCommonStyle = "border-collapse:collapse; table-layout:fixed; width:100%; max-width:600px; margin:0 auto;";
15
14
  async function convertToHtml(blockData, rootData, cellWidthInPx) {
16
15
  switch (blockData.type) {
17
16
  case types_1.BlockType.TEXT:
@@ -1,3 +1,4 @@
1
+ export declare function toOutlookBgColor(color: string): string;
1
2
  export declare function appendOutlookSupport(content: string, contentStyle: string, className?: string, msoWidth?: number): string;
2
3
  export declare function appendOutlookForImage(content: string, outerContainerWidth: number, innerContainerWidth: number, imageUrl: string, style?: any, finalWidth?: number, finalHeight?: number): Promise<string>;
3
4
  export declare function loadImageNaturalDimensions(imageUrl: string): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"outlookSupport.d.ts","sourceRoot":"","sources":["../../src/utils/outlookSupport.ts"],"names":[],"mappings":"AAEA,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,UAgClB;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,EACf,mBAAmB,EAAE,MAAM,EAC3B,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,GAAQ,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,mBA2ErB;AAED,wBAAsB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAO7G"}
1
+ {"version":3,"file":"outlookSupport.d.ts","sourceRoot":"","sources":["../../src/utils/outlookSupport.ts"],"names":[],"mappings":"AAIA,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOtD;AAOD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,UAqClB;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,EACf,mBAAmB,EAAE,MAAM,EAC3B,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,GAAQ,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,mBA2ErB;AAED,wBAAsB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAO7G"}
@@ -1,26 +1,46 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toOutlookBgColor = toOutlookBgColor;
3
4
  exports.appendOutlookSupport = appendOutlookSupport;
4
5
  exports.appendOutlookForImage = appendOutlookForImage;
5
6
  exports.loadImageNaturalDimensions = loadImageNaturalDimensions;
6
7
  const buildStyles_1 = require("./buildStyles");
8
+ // Converts rgba(r,g,b,a) → #rrggbb for use in HTML bgcolor attributes.
9
+ // Old Outlook's bgcolor attribute only accepts solid hex or named colors — rgba is silently ignored.
10
+ function toOutlookBgColor(color) {
11
+ if (!color || color === 'transparent')
12
+ return '';
13
+ const m = color.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*[\d.]+)?\s*\)/);
14
+ if (m) {
15
+ return '#' + [m[1], m[2], m[3]].map(n => parseInt(n).toString(16).padStart(2, '0')).join('');
16
+ }
17
+ return color;
18
+ }
19
+ function extractBgColor(styleStr) {
20
+ const m = styleStr.match(/background-color\s*:\s*([^;]+)/i);
21
+ return m ? m[1].trim() : '';
22
+ }
7
23
  function appendOutlookSupport(content, contentStyle, className, msoWidth) {
8
24
  const visibilityClass = className || "";
9
25
  const shouldHideInOutlook = visibilityClass.includes("hide-desktop");
26
+ // bgcolor attribute is the reliable fallback for solid colors in Outlook and webmail
27
+ // forwarding chains where CSS background-color gets stripped.
28
+ const rawBg = extractBgColor(contentStyle);
29
+ const bgAttr = rawBg ? ` bgcolor="${toOutlookBgColor(rawBg)}"` : '';
10
30
  if (shouldHideInOutlook) {
11
31
  return `
12
32
  <!--[if !mso]><!-->
13
- <table data-ebr-role="wrapper" role="presentation" width="100%" style="${buildStyles_1.tableCommonStyle}" class="${visibilityClass}"><tr><td style="${contentStyle}">${content}</td></tr></table>
33
+ <table data-ebr-role="wrapper" role="presentation" width="100%" style="${buildStyles_1.tableCommonStyle}" class="${visibilityClass}"><tr><td${bgAttr} style="${contentStyle}">${content}</td></tr></table>
14
34
  <!--<![endif]-->
15
35
  `;
16
36
  }
17
37
  if (msoWidth) {
18
38
  return `
19
39
  <!--[if mso]>
20
- <table role="presentation" border="0" cellpadding="0" cellspacing="0" width="${msoWidth}" style="border-collapse:collapse;width:${msoWidth}px;"><tr><td width="${msoWidth}" style="${contentStyle}">
40
+ <table role="presentation" border="0" cellpadding="0" cellspacing="0" width="${msoWidth}" style="border-collapse:collapse;width:${msoWidth}px;"><tr><td width="${msoWidth}"${bgAttr} style="${contentStyle}">
21
41
  <![endif]-->
22
42
  <!--[if !mso]><!-->
23
- <table data-ebr-role="wrapper" role="presentation" width="100%" border="0" cellpadding="0" cellspacing="0" style="${buildStyles_1.tableCommonStyle}; max-width:600px;" class="${visibilityClass}"><tr><td width="100%" style="${contentStyle}">
43
+ <table data-ebr-role="wrapper" role="presentation" width="100%" border="0" cellpadding="0" cellspacing="0" style="${buildStyles_1.tableCommonStyle}; max-width:600px;" class="${visibilityClass}"><tr><td width="100%"${bgAttr} style="${contentStyle}">
24
44
  <!--<![endif]-->
25
45
  ${content}
26
46
  <!--[if mso]></td></tr></table><![endif]-->
@@ -30,7 +50,7 @@ ${content}
30
50
  `;
31
51
  }
32
52
  return `
33
- <table data-ebr-role="wrapper" role="presentation" width="100%" border="0" cellpadding="0" cellspacing="0" style="${buildStyles_1.tableCommonStyle}; max-width:600px;" class="${visibilityClass}"><tr><td width="100%" style="${contentStyle}">${content}</td></tr></table>
53
+ <table data-ebr-role="wrapper" role="presentation" width="100%" border="0" cellpadding="0" cellspacing="0" style="${buildStyles_1.tableCommonStyle}; max-width:600px;" class="${visibilityClass}"><tr><td width="100%"${bgAttr} style="${contentStyle}">${content}</td></tr></table>
34
54
  `;
35
55
  }
36
56
  async function appendOutlookForImage(content, outerContainerWidth, innerContainerWidth, imageUrl, style = {}, finalWidth, finalHeight) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "email-builder-utils",
3
- "version": "1.1.47",
3
+ "version": "1.1.49",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [