@emailens/engine 0.11.7 → 0.11.9
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/compile/index.d.cts +2 -2
- package/dist/compile/index.d.ts +2 -2
- package/dist/index.cjs +70 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -9
- package/dist/index.d.ts +29 -9
- package/dist/index.js +70 -12
- package/dist/index.js.map +1 -1
- package/dist/{react-email-BROBcC8u.d.ts → react-email-B82A1R_K.d.ts} +1 -1
- package/dist/{react-email-DuZAgJtw.d.cts → react-email-DRkmpgX-.d.cts} +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/{types-bvGDId6f.d.cts → types-DiseE-UH.d.cts} +26 -1
- package/dist/{types-bvGDId6f.d.ts → types-DiseE-UH.d.ts} +26 -1
- package/package.json +2 -2
package/dist/compile/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { x as InputFormat } from '../types-
|
|
2
|
-
export { C as CompileError, a as CompileReactEmailOptions, S as SandboxStrategy, c as compileReactEmail } from '../react-email-
|
|
1
|
+
import { x as InputFormat } from '../types-DiseE-UH.cjs';
|
|
2
|
+
export { C as CompileError, a as CompileReactEmailOptions, S as SandboxStrategy, c as compileReactEmail } from '../react-email-DRkmpgX-.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Compile an MJML source string into an HTML email string.
|
package/dist/compile/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { x as InputFormat } from '../types-
|
|
2
|
-
export { C as CompileError, a as CompileReactEmailOptions, S as SandboxStrategy, c as compileReactEmail } from '../react-email-
|
|
1
|
+
import { x as InputFormat } from '../types-DiseE-UH.js';
|
|
2
|
+
export { C as CompileError, a as CompileReactEmailOptions, S as SandboxStrategy, c as compileReactEmail } from '../react-email-B82A1R_K.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Compile an MJML source string into an HTML email string.
|
package/dist/index.cjs
CHANGED
|
@@ -9068,10 +9068,6 @@ function splitTopLevel(value) {
|
|
|
9068
9068
|
return parts;
|
|
9069
9069
|
}
|
|
9070
9070
|
|
|
9071
|
-
// src/downlevel.ts
|
|
9072
|
-
var cheerio = __toESM(require("cheerio"), 1);
|
|
9073
|
-
var csstree = __toESM(require("css-tree"), 1);
|
|
9074
|
-
|
|
9075
9071
|
// src/color-utils.ts
|
|
9076
9072
|
var NAMED_COLORS = {
|
|
9077
9073
|
aliceblue: [240, 248, 255],
|
|
@@ -9509,6 +9505,8 @@ function colorDistance(a, b) {
|
|
|
9509
9505
|
}
|
|
9510
9506
|
|
|
9511
9507
|
// src/downlevel.ts
|
|
9508
|
+
var cheerio = __toESM(require("cheerio"), 1);
|
|
9509
|
+
var csstree = __toESM(require("css-tree"), 1);
|
|
9512
9510
|
var LOGICAL_PROPERTY_MAP = {
|
|
9513
9511
|
"padding-inline": ["padding-left", "padding-right"],
|
|
9514
9512
|
"padding-block": ["padding-top", "padding-bottom"],
|
|
@@ -9959,10 +9957,23 @@ function vmlToCss(html) {
|
|
|
9959
9957
|
solid ? `background-color:${solid}` : "",
|
|
9960
9958
|
`padding:${padding}`
|
|
9961
9959
|
].filter(Boolean).join(";");
|
|
9960
|
+
if (/data-vml="/.test(content)) {
|
|
9961
|
+
return `<div data-vml="rect" data-vml-outlook="container-dropped">${content}</div>`;
|
|
9962
|
+
}
|
|
9962
9963
|
return `<div data-vml="rect" style="${background}${box}">${content}</div>`;
|
|
9963
9964
|
}
|
|
9964
9965
|
);
|
|
9965
|
-
|
|
9966
|
+
out = out.replace(/<\/?v:(?:fill|textbox|stroke|shadow|imagedata|path|formulas|handles)[^>]*?\/?>/gi, "");
|
|
9967
|
+
return blankLabelsAfterNestedShape(out);
|
|
9968
|
+
}
|
|
9969
|
+
function blankLabelsAfterNestedShape(html) {
|
|
9970
|
+
const at = html.indexOf('data-vml-outlook="container-dropped"');
|
|
9971
|
+
if (at === -1) return html;
|
|
9972
|
+
const tail = html.slice(at).replace(
|
|
9973
|
+
/(<div data-vml="roundrect")([^>]*>)([\s\S]*?)(<\/div>)/gi,
|
|
9974
|
+
(whole, open, rest, label, close) => label.trim() ? `${open}${rest.slice(0, -1)} data-vml-outlook="label-dropped">${close}` : whole
|
|
9975
|
+
);
|
|
9976
|
+
return html.slice(0, at) + tail;
|
|
9966
9977
|
}
|
|
9967
9978
|
function renderOutlookBranch(html) {
|
|
9968
9979
|
if (!/<!--\[if/i.test(html)) return html;
|
|
@@ -10014,6 +10025,7 @@ var EMPTY_SPAM = { score: 100, level: "low", issues: [] };
|
|
|
10014
10025
|
var EMPTY_LINKS = {
|
|
10015
10026
|
totalLinks: 0,
|
|
10016
10027
|
issues: [],
|
|
10028
|
+
links: [],
|
|
10017
10029
|
breakdown: { https: 0, http: 0, mailto: 0, tel: 0, anchor: 0, javascript: 0, protocolRelative: 0, other: 0 }
|
|
10018
10030
|
};
|
|
10019
10031
|
var EMPTY_ACCESSIBILITY = { score: 100, issues: [] };
|
|
@@ -10393,13 +10405,17 @@ var CLIENT_CONFIGS = {
|
|
|
10393
10405
|
strippedProperties: OUTLOOK_WORD_UNSUPPORTED,
|
|
10394
10406
|
stripMode: "strip",
|
|
10395
10407
|
valueStrips: [
|
|
10396
|
-
|
|
10397
|
-
|
|
10408
|
+
// Gradients and image URLs alike: the Word engine paints neither. Only
|
|
10409
|
+
// VML does, and vmlToCss runs after this pass, so a hero built the
|
|
10410
|
+
// bulletproof way keeps the background this strip would otherwise take.
|
|
10411
|
+
{ prop: "background", pattern: /linear-gradient|radial-gradient|url\(/ },
|
|
10412
|
+
{ prop: "background-image", pattern: /linear-gradient|radial-gradient|url\(/ }
|
|
10398
10413
|
],
|
|
10399
10414
|
inlineAndStripStyles: false,
|
|
10400
10415
|
stripExternalStylesheets: false,
|
|
10401
10416
|
stripForms: false,
|
|
10402
10417
|
stripSvg: false,
|
|
10418
|
+
stripBackgroundAttribute: true,
|
|
10403
10419
|
additionalChecks: outlookWindowsAdditionalChecks
|
|
10404
10420
|
},
|
|
10405
10421
|
"outlook-web": {
|
|
@@ -10620,6 +10636,11 @@ function applyTransform(html, config, framework) {
|
|
|
10620
10636
|
$(el).replaceWith('<img alt="[SVG not supported]" />');
|
|
10621
10637
|
});
|
|
10622
10638
|
}
|
|
10639
|
+
if (config.stripBackgroundAttribute) {
|
|
10640
|
+
$("[background]").each((_, el) => {
|
|
10641
|
+
$(el).removeAttr("background");
|
|
10642
|
+
});
|
|
10643
|
+
}
|
|
10623
10644
|
if (config.strippedProperties.size > 0 || config.valueStrips && config.valueStrips.length > 0) {
|
|
10624
10645
|
$("[style]").each((_, el) => {
|
|
10625
10646
|
const style = $(el).attr("style") || "";
|
|
@@ -10644,7 +10665,9 @@ function applyTransform(html, config, framework) {
|
|
|
10644
10665
|
for (const vs of (_a = config.valueStrips) != null ? _a : []) {
|
|
10645
10666
|
if (prop === vs.prop && vs.pattern.test(value)) {
|
|
10646
10667
|
removed.push(prop);
|
|
10647
|
-
|
|
10668
|
+
const fallback = prop === "background" ? backgroundShorthandColor(value) : null;
|
|
10669
|
+
if (fallback) props.set(prop, fallback);
|
|
10670
|
+
else props.delete(prop);
|
|
10648
10671
|
return;
|
|
10649
10672
|
}
|
|
10650
10673
|
}
|
|
@@ -13114,6 +13137,7 @@ function isPlaceholderHref(href) {
|
|
|
13114
13137
|
}
|
|
13115
13138
|
function validateLinksFromDom($) {
|
|
13116
13139
|
const issues = [];
|
|
13140
|
+
const inventory = [];
|
|
13117
13141
|
const breakdown = { https: 0, http: 0, mailto: 0, tel: 0, anchor: 0, javascript: 0, protocolRelative: 0, other: 0 };
|
|
13118
13142
|
const links = $("a");
|
|
13119
13143
|
const totalLinks = links.length;
|
|
@@ -13123,13 +13147,22 @@ function validateLinksFromDom($) {
|
|
|
13123
13147
|
rule: "no-links",
|
|
13124
13148
|
message: "Email contains no links"
|
|
13125
13149
|
});
|
|
13126
|
-
return { totalLinks: 0, issues, breakdown };
|
|
13150
|
+
return { totalLinks: 0, issues, breakdown, links: [] };
|
|
13127
13151
|
}
|
|
13128
13152
|
const hrefCounts = /* @__PURE__ */ new Map();
|
|
13129
13153
|
links.each((_, el) => {
|
|
13130
13154
|
const href = $(el).attr("href") || "";
|
|
13131
13155
|
const text = $(el).text().trim();
|
|
13132
13156
|
const category = classifyHref(href);
|
|
13157
|
+
const entry = {
|
|
13158
|
+
href,
|
|
13159
|
+
text: text.slice(0, 80),
|
|
13160
|
+
scheme: category,
|
|
13161
|
+
isPlaceholder: isPlaceholderHref(href),
|
|
13162
|
+
issues: []
|
|
13163
|
+
};
|
|
13164
|
+
inventory.push(entry);
|
|
13165
|
+
const flag = (rule) => entry.issues.push(rule);
|
|
13133
13166
|
const elLoc = locOfElement(el);
|
|
13134
13167
|
const hrefLoc = href ? locOfAttr(el, "href") : elLoc;
|
|
13135
13168
|
switch (category) {
|
|
@@ -13162,6 +13195,7 @@ function validateLinksFromDom($) {
|
|
|
13162
13195
|
hrefCounts.set(href, (hrefCounts.get(href) || 0) + 1);
|
|
13163
13196
|
}
|
|
13164
13197
|
if (!href || !href.trim()) {
|
|
13198
|
+
flag("empty-href");
|
|
13165
13199
|
issues.push(__spreadValues({
|
|
13166
13200
|
severity: "error",
|
|
13167
13201
|
rule: "empty-href",
|
|
@@ -13171,6 +13205,7 @@ function validateLinksFromDom($) {
|
|
|
13171
13205
|
return;
|
|
13172
13206
|
}
|
|
13173
13207
|
if (category === "javascript" && !isPlaceholderHref(href)) {
|
|
13208
|
+
flag("javascript-href");
|
|
13174
13209
|
issues.push(__spreadValues({
|
|
13175
13210
|
severity: "error",
|
|
13176
13211
|
rule: "javascript-href",
|
|
@@ -13181,6 +13216,7 @@ function validateLinksFromDom($) {
|
|
|
13181
13216
|
return;
|
|
13182
13217
|
}
|
|
13183
13218
|
if (isPlaceholderHref(href)) {
|
|
13219
|
+
flag("placeholder-href");
|
|
13184
13220
|
issues.push(__spreadValues({
|
|
13185
13221
|
severity: "warning",
|
|
13186
13222
|
rule: "placeholder-href",
|
|
@@ -13191,6 +13227,7 @@ function validateLinksFromDom($) {
|
|
|
13191
13227
|
return;
|
|
13192
13228
|
}
|
|
13193
13229
|
if (category === "http") {
|
|
13230
|
+
flag("insecure-link");
|
|
13194
13231
|
issues.push(__spreadValues({
|
|
13195
13232
|
severity: "warning",
|
|
13196
13233
|
rule: "insecure-link",
|
|
@@ -13200,6 +13237,7 @@ function validateLinksFromDom($) {
|
|
|
13200
13237
|
}, hrefLoc ? { loc: hrefLoc } : {}));
|
|
13201
13238
|
}
|
|
13202
13239
|
if (category === "protocol-relative") {
|
|
13240
|
+
flag("protocol-relative");
|
|
13203
13241
|
issues.push(__spreadValues({
|
|
13204
13242
|
severity: "warning",
|
|
13205
13243
|
rule: "protocol-relative",
|
|
@@ -13209,6 +13247,7 @@ function validateLinksFromDom($) {
|
|
|
13209
13247
|
}, hrefLoc ? { loc: hrefLoc } : {}));
|
|
13210
13248
|
}
|
|
13211
13249
|
if (text && GENERIC_LINK_TEXT.has(text.toLowerCase())) {
|
|
13250
|
+
flag("generic-link-text");
|
|
13212
13251
|
issues.push(__spreadValues({
|
|
13213
13252
|
severity: "warning",
|
|
13214
13253
|
rule: "generic-link-text",
|
|
@@ -13218,6 +13257,7 @@ function validateLinksFromDom($) {
|
|
|
13218
13257
|
}, elLoc ? { loc: elLoc } : {}));
|
|
13219
13258
|
}
|
|
13220
13259
|
if (!text && !$(el).attr("aria-label") && !$(el).find("img[alt]").length) {
|
|
13260
|
+
flag("empty-link-text");
|
|
13221
13261
|
issues.push(__spreadValues({
|
|
13222
13262
|
severity: "error",
|
|
13223
13263
|
rule: "empty-link-text",
|
|
@@ -13226,6 +13266,7 @@ function validateLinksFromDom($) {
|
|
|
13226
13266
|
}, elLoc ? { loc: elLoc } : {}));
|
|
13227
13267
|
}
|
|
13228
13268
|
if (category === "mailto" && href.trim().toLowerCase() === "mailto:") {
|
|
13269
|
+
flag("empty-mailto");
|
|
13229
13270
|
issues.push(__spreadValues({
|
|
13230
13271
|
severity: "error",
|
|
13231
13272
|
rule: "empty-mailto",
|
|
@@ -13235,6 +13276,7 @@ function validateLinksFromDom($) {
|
|
|
13235
13276
|
}, hrefLoc ? { loc: hrefLoc } : {}));
|
|
13236
13277
|
}
|
|
13237
13278
|
if (category === "tel" && href.trim().toLowerCase() === "tel:") {
|
|
13279
|
+
flag("empty-tel");
|
|
13238
13280
|
issues.push(__spreadValues({
|
|
13239
13281
|
severity: "error",
|
|
13240
13282
|
rule: "empty-tel",
|
|
@@ -13244,6 +13286,7 @@ function validateLinksFromDom($) {
|
|
|
13244
13286
|
}, hrefLoc ? { loc: hrefLoc } : {}));
|
|
13245
13287
|
}
|
|
13246
13288
|
if (href.length > 2e3) {
|
|
13289
|
+
flag("long-url");
|
|
13247
13290
|
issues.push(__spreadValues({
|
|
13248
13291
|
severity: "info",
|
|
13249
13292
|
rule: "long-url",
|
|
@@ -13253,7 +13296,8 @@ function validateLinksFromDom($) {
|
|
|
13253
13296
|
}, hrefLoc ? { loc: hrefLoc } : {}));
|
|
13254
13297
|
}
|
|
13255
13298
|
});
|
|
13256
|
-
links.each((
|
|
13299
|
+
links.each((i, el) => {
|
|
13300
|
+
var _a;
|
|
13257
13301
|
const href = $(el).attr("href") || "";
|
|
13258
13302
|
const trimmed = href.trim();
|
|
13259
13303
|
if (trimmed.startsWith("#") && trimmed.length > 1) {
|
|
@@ -13261,6 +13305,7 @@ function validateLinksFromDom($) {
|
|
|
13261
13305
|
const target = $(`[id="${targetId}"]`);
|
|
13262
13306
|
const anchorLoc = locOfAttr(el, "href");
|
|
13263
13307
|
if (target.length === 0) {
|
|
13308
|
+
(_a = inventory[i]) == null ? void 0 : _a.issues.push("broken-anchor");
|
|
13264
13309
|
issues.push(__spreadValues({
|
|
13265
13310
|
severity: "error",
|
|
13266
13311
|
rule: "broken-anchor",
|
|
@@ -13281,7 +13326,7 @@ function validateLinksFromDom($) {
|
|
|
13281
13326
|
});
|
|
13282
13327
|
}
|
|
13283
13328
|
}
|
|
13284
|
-
return { totalLinks, issues, breakdown };
|
|
13329
|
+
return { totalLinks, issues, breakdown, links: inventory };
|
|
13285
13330
|
}
|
|
13286
13331
|
function validateLinks(html, options) {
|
|
13287
13332
|
return fromHtml(html, EMPTY_LINKS, validateLinksFromDom, options);
|
|
@@ -14820,7 +14865,20 @@ function checkVml(html, options) {
|
|
|
14820
14865
|
rule: "vml-nested-shape",
|
|
14821
14866
|
severity: "error",
|
|
14822
14867
|
message: `<v:${name}> is nested inside <v:${parent.name}>. Outlook does not support nesting one VML shape inside another.`,
|
|
14823
|
-
|
|
14868
|
+
// Two effects, not the three this used to claim. The withdrawn one
|
|
14869
|
+
// said the table structure terminates early so content after the
|
|
14870
|
+
// shape falls outside the email frame. It had no methodology behind
|
|
14871
|
+
// it, and `T1c-blast-radius.html`, the fixture built to measure
|
|
14872
|
+
// exactly this, contradicts it: the block after the nested shape
|
|
14873
|
+
// rendered in place inside the same table with its background and
|
|
14874
|
+
// borders intact, and only the VML labels were missing. The likely
|
|
14875
|
+
// origin is over-reading "layout breaks after it" from a run where a
|
|
14876
|
+
// 600px hero band vanished and everything below shifted up.
|
|
14877
|
+
//
|
|
14878
|
+
// Kept as a warning to whoever edits this next: the probe sentence
|
|
14879
|
+
// below covers the downstream text suppression only. Do not let it
|
|
14880
|
+
// lend its authority to a neighbouring clause again.
|
|
14881
|
+
detail: `Verified in Outlook Classic, and the damage is not local. Two things happen: the containing <v:${parent.name}> does not render at all (its fill and everything inside it disappear, leaving the inner shape stranded); and every VML shape further down the email stops drawing its text, so buttons and headings after this point ship as blank coloured blocks. That second effect was confirmed with byte-identical probes either side of one nested shape: the one before it renders its labels, the one after it does not. Every other client renders the HTML fallback correctly, which is why none of this is visible outside the Word engine. Fix: lift the inner shape out of <v:${parent.name}>, or drop the container shape and keep the inner one (a framed background can degrade to a solid fill colour on the <td> instead).`
|
|
14824
14882
|
}, loc));
|
|
14825
14883
|
}
|
|
14826
14884
|
if (!tag.selfClosing) openShapes.push(tag);
|