email-builder-utils 1.1.50 → 1.1.53
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/blocks/button.d.ts.map +1 -1
- package/dist/utils/blocks/button.js +1 -3
- package/dist/utils/blocks/grid.d.ts.map +1 -1
- package/dist/utils/blocks/grid.js +20 -8
- package/dist/utils/blocks/text.d.ts.map +1 -1
- package/dist/utils/blocks/text.js +4 -1
- package/dist/utils/common.d.ts.map +1 -1
- package/dist/utils/common.js +4 -1
- package/dist/utils/convertJsonToHtml.js +6 -6
- package/dist/utils/outlookSupport.d.ts.map +1 -1
- package/dist/utils/outlookSupport.js +18 -8
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/button.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/button.ts"],"names":[],"mappings":"AA2IA,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,GAAG,UAuFhD"}
|
|
@@ -79,9 +79,7 @@ function appendOutlookForButton(buttonData) {
|
|
|
79
79
|
${strokeAttrs}
|
|
80
80
|
fillcolor="${bgColor}">
|
|
81
81
|
<w:anchorlock/>
|
|
82
|
-
<
|
|
83
|
-
<center style="color:${safeColor};font-family:${safeFF};font-size:${fs}px;font-weight:${fontWeight};mso-line-height-rule:exactly;line-height:${finalHeight}px;text-decoration:none;">${text}</center>
|
|
84
|
-
</v:textbox>
|
|
82
|
+
<center style="color:${safeColor};font-family:${safeFF};font-size:${fs}px;font-weight:${fontWeight};mso-line-height-rule:exactly;line-height:${fs}px;text-decoration:none;">${text}</center>
|
|
85
83
|
</v:roundrect>
|
|
86
84
|
<![endif]-->`;
|
|
87
85
|
const innerContent = containerAlign === "center"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/grid.ts"],"names":[],"mappings":"AAMA,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,GAAG,EACd,QAAQ,EAAE,GAAG,EACb,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/grid.ts"],"names":[],"mappings":"AAMA,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,GAAG,EACd,QAAQ,EAAE,GAAG,EACb,aAAa,EAAE,MAAM,mBA0TtB;AAED,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,GAAG,EACd,QAAQ,EAAE,GAAG,EACb,gBAAgB,EAAE,MAAM,EACxB,iBAAiB,EAAE,MAAM,EACzB,mBAAmB,UAAQ;;;GA0G5B"}
|
|
@@ -157,10 +157,16 @@ async function convertGridBlock(blockData, rootData, cellWidthInPx) {
|
|
|
157
157
|
const visibilityClass = (0, common_1.getVisibilityClass)(childProps);
|
|
158
158
|
if (childVisible) {
|
|
159
159
|
const { html: childHtml, styles } = await convertGridCellBlock(child, rootData, widthPercent, adjustedTableWidth, Boolean(divBorderStyle));
|
|
160
|
-
// bgcolor on the cell <td>
|
|
161
|
-
//
|
|
160
|
+
// bgcolor on the cell <td> for Old Outlook (Word engine).
|
|
161
|
+
// When the cell has no border-radius and the grid has no border, use the grid's
|
|
162
|
+
// backgroundColor as the fallback so the grid background shows through empty cells.
|
|
163
|
+
// Skipped for border-radius cells — bgcolor is rectangular and would bleed through
|
|
164
|
+
// the div's rounded-corner clip in CSS-capable clients (corner squares).
|
|
162
165
|
const cellBgColor = cellStyle.backgroundColor || '';
|
|
163
|
-
const
|
|
166
|
+
const cellHasBorderRadius = Boolean(cellStyle.borderRadius);
|
|
167
|
+
const canApplyGridBgFallback = !cellHasBorderRadius && !divBorderStyle;
|
|
168
|
+
const effectiveCellBg = cellBgColor || (canApplyGridBgFallback ? msoBgColor : '');
|
|
169
|
+
const cellBgAttr = (0, common_1.buildOutlookBgAttr)(effectiveCellBg);
|
|
164
170
|
html += `
|
|
165
171
|
<td
|
|
166
172
|
width="${Math.max(1, Math.round(widthPercent))}%"${cellBgAttr}
|
|
@@ -173,18 +179,22 @@ async function convertGridBlock(blockData, rootData, cellWidthInPx) {
|
|
|
173
179
|
// Outlook mobile (which strips <style>) treats it proportionally, not as a fixed blocker.
|
|
174
180
|
// col-gap-spacer class hides it when columns stack via CSS media query.
|
|
175
181
|
if (columnGap > 0 && c !== lastVisibleCol) {
|
|
176
|
-
|
|
182
|
+
const gapBgAttr = divBorderStyle ? '' : (0, common_1.buildOutlookBgAttr)(msoBgColor);
|
|
183
|
+
html += `<td width="${columnGap}"${gapBgAttr} class="col-gap-spacer" style="font-size:0;line-height:0;padding:0;" aria-hidden="true"></td>`;
|
|
177
184
|
}
|
|
178
185
|
}
|
|
179
186
|
}
|
|
180
187
|
else {
|
|
188
|
+
const emptyBgAttr = divBorderStyle ? '' : (0, common_1.buildOutlookBgAttr)(msoBgColor);
|
|
181
189
|
html += `
|
|
182
190
|
<td width="${Math.max(1, Math.round(widthPercent))}%"
|
|
191
|
+
${emptyBgAttr}
|
|
183
192
|
${responsive ? 'class="stack-column"' : ""}
|
|
184
193
|
style="width:${widthPercent}%;vertical-align:top;">
|
|
185
194
|
</td>`;
|
|
186
195
|
if (columnGap > 0 && c !== lastVisibleCol) {
|
|
187
|
-
|
|
196
|
+
const gapBgAttr = divBorderStyle ? '' : (0, common_1.buildOutlookBgAttr)(msoBgColor);
|
|
197
|
+
html += `<td width="${columnGap}"${gapBgAttr} class="col-gap-spacer" style="font-size:0;line-height:0;padding:0;" aria-hidden="true"></td>`;
|
|
188
198
|
}
|
|
189
199
|
}
|
|
190
200
|
}
|
|
@@ -310,7 +320,7 @@ async function convertGridCellBlock(blockData, rootData, cellWidthPercent, paren
|
|
|
310
320
|
}
|
|
311
321
|
}
|
|
312
322
|
const borderRadius = cellBorderRadius || 0;
|
|
313
|
-
const bgColor = styleWithoutBorder?.backgroundColor || "
|
|
323
|
+
const bgColor = styleWithoutBorder?.backgroundColor || "";
|
|
314
324
|
// Build border CSS for the div wrapper.
|
|
315
325
|
// When the parent grid already has a divBorderStyle wrapper (border + border-radius +
|
|
316
326
|
// overflow:hidden), the cell must NOT duplicate the same border/radius — that causes
|
|
@@ -332,8 +342,10 @@ async function convertGridCellBlock(blockData, rootData, cellWidthPercent, paren
|
|
|
332
342
|
}
|
|
333
343
|
const cellDivBorderStyle = cellDivBorderParts.join(' ');
|
|
334
344
|
// Unconditional div — visible to all clients (Gmail, Outlook new/old, Apple Mail).
|
|
335
|
-
// background-color on the div covers modern clients
|
|
336
|
-
|
|
345
|
+
// background-color on the div covers modern clients when a real color is set.
|
|
346
|
+
// When no color is set, omit the property entirely — writing background-color:transparent
|
|
347
|
+
// defeats the bgcolor attribute on the parent <td> in Old Outlook's Word engine.
|
|
348
|
+
const divStyleParts = bgColor ? [`background-color:${bgColor};`] : [];
|
|
337
349
|
const formatPad = (value) => (typeof value === 'number' ? `${value}px` : (value || '0'));
|
|
338
350
|
const cellPadTop = formatPad(cellPad.top);
|
|
339
351
|
const cellPadBottom = formatPad(cellPad.bottom);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/text.ts"],"names":[],"mappings":"AASA,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/utils/blocks/text.ts"],"names":[],"mappings":"AASA,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,CAAC,EAAE,MAAM,UAqLtE"}
|
|
@@ -101,9 +101,12 @@ function convertTextBlock(blockData, cellWidthInPx) {
|
|
|
101
101
|
return `<v:fill type="gradient" color="${c1}" color2="${c2}" angle="${vmlAngle}" />`;
|
|
102
102
|
})()
|
|
103
103
|
: `<v:fill type="frame" src="${rawBgImageUrl}" color="${fallbackBgColor}" />`;
|
|
104
|
+
const bgPosition = rest.backgroundPosition || 'center center';
|
|
105
|
+
const bgSize = rest.backgroundSize || 'cover';
|
|
106
|
+
const bgRepeat = rest.backgroundRepeat || 'no-repeat';
|
|
104
107
|
const bgCss = isGradient
|
|
105
108
|
? `background:${effectiveGradient};`
|
|
106
|
-
: `background-image:url('${rawBgImageUrl}'); background-position
|
|
109
|
+
: `background-image:url('${rawBgImageUrl}'); background-position:${bgPosition}; background-size:${bgSize}; background-repeat:${bgRepeat};`;
|
|
107
110
|
const wrappedContent = `
|
|
108
111
|
<table border="0" cellpadding="0" cellspacing="0" width="100%" role="presentation"
|
|
109
112
|
style="border-collapse:collapse;width:100%;max-width:${msoWidth}px;" class="${visibilityClass}">
|
|
@@ -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;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAQvE;
|
|
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;AAcD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGxD"}
|
package/dist/utils/common.js
CHANGED
|
@@ -57,8 +57,11 @@ function encodeBlockPropsAttr(props) {
|
|
|
57
57
|
function toOutlookBgColor(color) {
|
|
58
58
|
if (!color || color === 'transparent')
|
|
59
59
|
return '';
|
|
60
|
-
const m = color.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*[\d.]+)?\s*\)/);
|
|
60
|
+
const m = color.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\d.]+))?\s*\)/);
|
|
61
61
|
if (m) {
|
|
62
|
+
const alpha = m[4] !== undefined ? parseFloat(m[4]) : 1;
|
|
63
|
+
if (alpha < 1)
|
|
64
|
+
return '';
|
|
62
65
|
return '#' + [m[1], m[2], m[3]].map(n => parseInt(n).toString(16).padStart(2, '0')).join('');
|
|
63
66
|
}
|
|
64
67
|
return color;
|
|
@@ -141,17 +141,17 @@ const convertJsonToHtml = async (jsonData) => {
|
|
|
141
141
|
}
|
|
142
142
|
</style>
|
|
143
143
|
</head>
|
|
144
|
-
<body style="margin:0; padding:0; background-color
|
|
145
|
-
<center style="width:100%;
|
|
144
|
+
<body bgcolor="#ffffff" style="margin:0; padding:0; background-color:#ffffff;">
|
|
145
|
+
<center style="width:100%;">
|
|
146
146
|
|
|
147
|
-
<table role="presentation" width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="
|
|
147
|
+
<table role="presentation" width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#ffffff">
|
|
148
148
|
<tr>
|
|
149
|
-
<td align="center">
|
|
149
|
+
<td align="center" bgcolor="#ffffff">
|
|
150
150
|
|
|
151
151
|
<!--[if mso]>
|
|
152
152
|
<table role="presentation" border="0" cellspacing="0" cellpadding="0" width="600">
|
|
153
153
|
<tr>
|
|
154
|
-
<td>
|
|
154
|
+
<td bgcolor="${canvasColor || '#ffffff'}">
|
|
155
155
|
<![endif]-->
|
|
156
156
|
|
|
157
157
|
<table
|
|
@@ -177,7 +177,7 @@ const convertJsonToHtml = async (jsonData) => {
|
|
|
177
177
|
>
|
|
178
178
|
<tbody>
|
|
179
179
|
<tr>
|
|
180
|
-
<td style="padding: ${top}px ${right}px ${bottom}px ${left}px; max-width: 600px; overflow: hidden; box-sizing: border-box; word-break: break-word; overflow-wrap: anywhere;">
|
|
180
|
+
<td bgcolor="${canvasColor || '#ffffff'}" style="padding: ${top}px ${right}px ${bottom}px ${left}px; max-width: 600px; overflow: hidden; box-sizing: border-box; word-break: break-word; overflow-wrap: anywhere;">
|
|
181
181
|
${blocksHtml.join("")}
|
|
182
182
|
</td>
|
|
183
183
|
</tr>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outlookSupport.d.ts","sourceRoot":"","sources":["../../src/utils/outlookSupport.ts"],"names":[],"mappings":"AAKA,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"outlookSupport.d.ts","sourceRoot":"","sources":["../../src/utils/outlookSupport.ts"],"names":[],"mappings":"AAKA,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAStD;AAOD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,UAyClB;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,mBA2FrB;AAED,wBAAsB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAe7G"}
|
|
@@ -11,8 +11,11 @@ const common_1 = require("./common");
|
|
|
11
11
|
function toOutlookBgColor(color) {
|
|
12
12
|
if (!color || color === 'transparent')
|
|
13
13
|
return '';
|
|
14
|
-
const m = color.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*[\d.]+)?\s*\)/);
|
|
14
|
+
const m = color.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\d.]+))?\s*\)/);
|
|
15
15
|
if (m) {
|
|
16
|
+
const alpha = m[4] !== undefined ? parseFloat(m[4]) : 1;
|
|
17
|
+
if (alpha < 1)
|
|
18
|
+
return '';
|
|
16
19
|
return '#' + [m[1], m[2], m[3]].map(n => parseInt(n).toString(16).padStart(2, '0')).join('');
|
|
17
20
|
}
|
|
18
21
|
return color;
|
|
@@ -126,7 +129,7 @@ async function appendOutlookForImage(content, outerContainerWidth, innerContaine
|
|
|
126
129
|
<table border="0" cellpadding="0" cellspacing="0" width="${vmlWidth}" style="width:${vmlWidth}px;">
|
|
127
130
|
<tr>
|
|
128
131
|
<td align="center" valign="top" width="${vmlWidth}" style="width:${vmlWidth}px;">
|
|
129
|
-
<img src="${imageUrl}" alt="Image" border="0" width="${vmlWidth}"
|
|
132
|
+
<img src="${imageUrl}" alt="Image" border="0" width="${vmlWidth}" style="display:block; width:${vmlWidth}px; height:auto; max-width:${vmlWidth}px; ${borderStyleAttr}" />
|
|
130
133
|
</td>
|
|
131
134
|
</tr>
|
|
132
135
|
</table>
|
|
@@ -140,10 +143,17 @@ async function appendOutlookForImage(content, outerContainerWidth, innerContaine
|
|
|
140
143
|
`;
|
|
141
144
|
}
|
|
142
145
|
async function loadImageNaturalDimensions(imageUrl) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
146
|
+
// Browser environment: use native Image element
|
|
147
|
+
if (typeof window !== 'undefined' && typeof Image !== 'undefined') {
|
|
148
|
+
return new Promise((resolve, reject) => {
|
|
149
|
+
const img = new Image();
|
|
150
|
+
img.onload = () => resolve({ width: img.naturalWidth, height: img.naturalHeight });
|
|
151
|
+
img.onerror = () => reject(new Error(`Failed to load image: ${imageUrl}`));
|
|
152
|
+
img.src = imageUrl;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// Node.js (BE) environment: use jimp to fetch and read dimensions
|
|
156
|
+
const { Jimp } = await import('jimp');
|
|
157
|
+
const image = await Jimp.read(imageUrl);
|
|
158
|
+
return { width: image.bitmap.width, height: image.bitmap.height };
|
|
149
159
|
}
|