@emailens/engine 0.12.0 → 0.12.2
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/{chunk-UFSYNSDP.js → chunk-KKWC2C3R.js} +3 -3
- package/dist/chunk-KKWC2C3R.js.map +1 -0
- package/dist/{chunk-PW6EUG2G.js → chunk-OA6VNA5L.js} +16 -4
- package/dist/chunk-OA6VNA5L.js.map +1 -0
- package/dist/compile/index.cjs +18 -6
- package/dist/compile/index.cjs.map +1 -1
- package/dist/compile/index.d.cts +2 -21
- package/dist/compile/index.d.ts +2 -21
- package/dist/compile/index.js +4 -4
- package/dist/index.cjs +388 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +98 -5
- package/dist/index.d.ts +98 -5
- package/dist/index.js +387 -29
- package/dist/index.js.map +1 -1
- package/dist/maizzle-R5KU3HHZ.js +11 -0
- package/dist/{react-email-CVZZNVZ2.js → react-email-2DGTHWTN.js} +2 -2
- package/dist/{react-email-BzyXjPrH.d.ts → react-email-BTIw8QV8.d.ts} +9 -4
- package/dist/{react-email-DHkCZ7TG.d.cts → react-email-Dmn1QpXz.d.cts} +9 -4
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/{types-edFeUest.d.cts → types-DdFHwMtT.d.cts} +23 -88
- package/dist/{types-edFeUest.d.ts → types-DdFHwMtT.d.ts} +23 -88
- package/package.json +1 -1
- package/dist/chunk-PW6EUG2G.js.map +0 -1
- package/dist/chunk-UFSYNSDP.js.map +0 -1
- package/dist/maizzle-KKJF7XY7.js +0 -9
- /package/dist/{maizzle-KKJF7XY7.js.map → maizzle-R5KU3HHZ.js.map} +0 -0
- /package/dist/{react-email-CVZZNVZ2.js.map → react-email-2DGTHWTN.js.map} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
compileReactEmail
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KKWC2C3R.js";
|
|
4
4
|
import "./chunk-Z22AD2IU.js";
|
|
5
5
|
import "./chunk-2NMEKWO5.js";
|
|
6
6
|
export {
|
|
7
7
|
compileReactEmail
|
|
8
8
|
};
|
|
9
|
-
//# sourceMappingURL=react-email-
|
|
9
|
+
//# sourceMappingURL=react-email-2DGTHWTN.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { y as InputFormat } from './types-DdFHwMtT.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Unified error class for all email compilation failures.
|
|
@@ -17,9 +17,14 @@ declare class CompileError extends Error {
|
|
|
17
17
|
/**
|
|
18
18
|
* Sandbox strategy for JSX execution.
|
|
19
19
|
*
|
|
20
|
-
* - `"vm"`: `node:vm` with hardened globals. Fast, zero-dependency,
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* - `"vm"`: `node:vm` with hardened globals. Fast, zero-dependency, and NOT a
|
|
21
|
+
* security boundary. The hardening removes `process`, `Buffer` and timers
|
|
22
|
+
* from the sandbox and sets `codeGeneration.strings: false`, but host
|
|
23
|
+
* intrinsics are passed in, and the `Function` constructor reached through
|
|
24
|
+
* one of them compiles in the *host* realm where that flag does not apply:
|
|
25
|
+
* `Object.constructor("return process")()` returns the real process, and
|
|
26
|
+
* `process.env` with it. Demonstrated in the test suite. Use it only for
|
|
27
|
+
* templates you already trust, such as a developer compiling their own.
|
|
23
28
|
*
|
|
24
29
|
* - `"isolated-vm"` (default): Separate V8 isolate via the `isolated-vm`
|
|
25
30
|
* npm package. True heap isolation; escapes require a V8 engine bug.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { y as InputFormat } from './types-DdFHwMtT.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Unified error class for all email compilation failures.
|
|
@@ -17,9 +17,14 @@ declare class CompileError extends Error {
|
|
|
17
17
|
/**
|
|
18
18
|
* Sandbox strategy for JSX execution.
|
|
19
19
|
*
|
|
20
|
-
* - `"vm"`: `node:vm` with hardened globals. Fast, zero-dependency,
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* - `"vm"`: `node:vm` with hardened globals. Fast, zero-dependency, and NOT a
|
|
21
|
+
* security boundary. The hardening removes `process`, `Buffer` and timers
|
|
22
|
+
* from the sandbox and sets `codeGeneration.strings: false`, but host
|
|
23
|
+
* intrinsics are passed in, and the `Function` constructor reached through
|
|
24
|
+
* one of them compiles in the *host* realm where that flag does not apply:
|
|
25
|
+
* `Object.constructor("return process")()` returns the real process, and
|
|
26
|
+
* `process.env` with it. Demonstrated in the test suite. Use it only for
|
|
27
|
+
* templates you already trust, such as a developer compiling their own.
|
|
23
28
|
*
|
|
24
29
|
* - `"isolated-vm"` (default): Separate V8 isolate via the `isolated-vm`
|
|
25
30
|
* npm package. True heap isolation; escapes require a V8 engine bug.
|
package/dist/server.d.cts
CHANGED
package/dist/server.d.ts
CHANGED
|
@@ -98,97 +98,11 @@ declare function estimateAiFixTokens(options: EstimateOptions): Promise<TokenEst
|
|
|
98
98
|
*/
|
|
99
99
|
declare function heuristicTokenCount(text: string): number;
|
|
100
100
|
|
|
101
|
-
/**
|
|
102
|
-
* CSS/HTML feature support matrix, auto-generated from caniemail.com.
|
|
103
|
-
* Last synced: 2026-09-02
|
|
104
|
-
* caniemail last updated: 2026-08-10 15:16:24 +0000
|
|
105
|
-
*
|
|
106
|
-
* 298 features and 14 image formats across 21 email clients.
|
|
107
|
-
*
|
|
108
|
-
* Support levels:
|
|
109
|
-
* - "supported": fully supported
|
|
110
|
-
* - "partial": partially supported (with caveats)
|
|
111
|
-
* - "unsupported": not supported at all
|
|
112
|
-
* - "unknown": no data available
|
|
113
|
-
*
|
|
114
|
-
* Data sources:
|
|
115
|
-
* - Most clients: caniemail.com API (verified data)
|
|
116
|
-
* - hey-mail: caniemail.com (WebKit-based)
|
|
117
|
-
* - superhuman: Manual overrides (Chromium/Blink-based, best-effort estimates)
|
|
118
|
-
*
|
|
119
|
-
* A client we ship as one entry although caniemail tests it on several
|
|
120
|
-
* platforms (Proton Mail, AOL, Thunderbird) is graded on its worst
|
|
121
|
-
* platform. Gmail, Outlook, Yahoo and Apple Mail ship as separate clients
|
|
122
|
-
* per platform instead.
|
|
123
|
-
*
|
|
124
|
-
* DO NOT EDIT; regenerate with: bun run sync:caniemail
|
|
125
|
-
*/
|
|
126
|
-
/** The clients every row answers for, in report order. */
|
|
127
|
-
declare const SUPPORT_CLIENTS: readonly ["gmail-web", "gmail-android", "gmail-ios", "outlook-web", "outlook-windows", "outlook-windows-legacy", "outlook-ios", "outlook-android", "outlook-macos", "apple-mail-macos", "apple-mail-ios", "yahoo-mail", "yahoo-mail-android", "yahoo-mail-ios", "samsung-mail", "thunderbird", "hey-mail", "protonmail", "aol", "fastmail", "superhuman"];
|
|
128
|
-
declare const CSS_SUPPORT: Record<string, Record<ClientId, SupportLevel>>;
|
|
129
|
-
/**
|
|
130
|
-
* Caveat notes per (feature, client) from caniemail: the "why" behind a
|
|
131
|
-
* partial/buggy/unsupported rating. Sparse: only cells with a note appear.
|
|
132
|
-
*/
|
|
133
|
-
declare const CSS_SUPPORT_NOTES: Record<string, Record<string, string[]>>;
|
|
134
|
-
/**
|
|
135
|
-
* Image format support, keyed by format. Kept out of CSS_SUPPORT because an
|
|
136
|
-
* image format is a property of the `src`, not of a stylesheet: the image
|
|
137
|
-
* analyzer looks these up, the CSS analyzer never should.
|
|
138
|
-
*/
|
|
139
|
-
/** The image formats caniemail grades. */
|
|
140
|
-
declare const IMAGE_FORMATS: readonly ["apng", "avif", "base64", "bmp", "gif", "hdr", "heif", "ico", "jpg", "mp4", "png", "svg", "tiff", "webp"];
|
|
141
|
-
declare const IMAGE_SUPPORT: Record<string, Record<ClientId, SupportLevel>>;
|
|
142
|
-
/** Caveat notes per (image format, client), same shape as CSS_SUPPORT_NOTES. */
|
|
143
|
-
declare const IMAGE_SUPPORT_NOTES: Record<string, Record<string, string[]>>;
|
|
144
|
-
/**
|
|
145
|
-
* Features a client merely ignores when it "does not support" them: the
|
|
146
|
-
* email renders the same either way, so these report as info, not warnings.
|
|
147
|
-
*/
|
|
148
|
-
declare const GRACEFUL_FEATURES: ReadonlySet<string>;
|
|
149
|
-
/**
|
|
150
|
-
* Properties that require HTML structural changes (not just CSS swaps)
|
|
151
|
-
* to fix. These cannot be solved by replacing one CSS value with another.
|
|
152
|
-
*/
|
|
153
|
-
declare const STRUCTURAL_FIX_PROPERTIES: Set<string>;
|
|
154
|
-
/** HTML element features in the support matrix (for data-driven detection). */
|
|
155
|
-
declare const HTML_ELEMENT_FEATURES: readonly ["<abbr>", "<acronym>", "<address>", "<audio>", "<base>", "<bdi>", "<blockquote>", "<body>", "<button type=\"reset\">", "<button type=\"submit\">", "<code>", "<del>", "<dfn>", "<dialog>", "<div>", "<form>", "<h1>", "<hr>", "<img>", "<input type=\"checkbox\">", "<input type=\"hidden\">", "<input type=\"radio\">", "<input type=\"reset\">", "<input type=\"submit\">", "<input type=\"text\">", "<link>", "<marquee>", "<meter>", "<object>", "<p>", "<picture>", "<pre>", "<progress>", "<rp>", "<rt>", "<ruby>", "<select>", "<small>", "<span>", "<strike>", "<strong>", "<style>", "<svg>", "<table>", "<textarea>", "<ul>", "<video>", "<wbr>"];
|
|
156
|
-
/** HTML attribute features. Each key is also the cheerio selector that finds it. */
|
|
157
|
-
declare const HTML_ATTRIBUTE_FEATURES: readonly ["[align]", "[aria-describedby]", "[aria-hidden]", "[aria-label]", "[aria-labelledby]", "[aria-live]", "[background]", "[cellpadding]", "[cellspacing]", "[command]", "[dir]", "[height]", "[hidden]", "[lang]", "[loading]", "[popover]", "[required]", "[role]", "[srcset]", "[target]", "[valign]", "[width]"];
|
|
158
|
-
/** Document-level and link-shaped HTML features; each has a bespoke detector. */
|
|
159
|
-
declare const HTML_MISC_FEATURES: readonly ["amp4email", "anchor-links", "doctype", "html-comments", "html5-semantics", "image-maps", "mailto-links", "meta-color-scheme"];
|
|
160
|
-
/** CSS at-rule features, including the media features that qualify `@media`. */
|
|
161
|
-
declare const AT_RULE_FEATURES: readonly ["@font-face", "@import", "@keyframes", "@media", "@media device-pixel-ratio", "@media hover", "@media orientation", "@media prefers-color-scheme", "@media prefers-reduced-motion", "@supports"];
|
|
162
|
-
/** One property paired with one value, e.g. "display:flex". */
|
|
163
|
-
declare const COMPOUND_VALUE_FEATURES: readonly ["display:flex", "display:grid", "display:none"];
|
|
164
|
-
/** Pseudo-classes, pseudo-elements and combinators, e.g. ":hover", "::after". */
|
|
165
|
-
declare const SELECTOR_FEATURES: readonly ["::after", "::before", "::first-letter", "::first-line", "::marker", "::placeholder", ":adjacent-sibling", ":attribute-selector", ":chaining", ":checked", ":child-combinator", ":class-selector", ":descendant-combinator", ":first-child", ":first-of-type", ":focus", ":focus-visible", ":focus-within", ":general-sibling", ":grouping", ":has", ":hover", ":id-selector", ":lang", ":last-child", ":last-of-type", ":link", ":not", ":nth-child", ":nth-last-child", ":nth-of-type", ":only-child", ":only-of-type", ":target", ":type-selector", ":universal-selector", ":visited"];
|
|
166
|
-
/** CSS function features (e.g., "linear-gradient"). */
|
|
167
|
-
declare const CSS_FUNCTION_FEATURES: readonly ["calc", "clamp", "conic-gradient", "fit-content", "linear-gradient", "max", "min", "radial-gradient"];
|
|
168
|
-
/** Plain CSS property names: what an inline style or declaration can match. */
|
|
169
|
-
declare const CSS_PROPERTY_FEATURES: readonly ["!important", "accent-color", "align-items", "animation", "aspect-ratio", "backdrop-filter", "background", "background-blend-mode", "background-clip", "background-color", "background-image", "background-origin", "background-position", "background-repeat", "background-size", "bimi", "block-size", "border", "border-collapse", "border-image", "border-inline", "border-inline-individual", "border-inline-longhand", "border-radius", "border-radius-logical", "border-spacing", "bottom", "box-shadow", "box-sizing", "caption-side", "clear", "clip-path", "color", "color-scheme", "column-count", "columns", "css-comments", "cursor", "custom-properties", "direction", "display", "empty-cells", "filter", "flex-direction", "flex-wrap", "float", "font", "font-family", "font-kerning", "font-size", "font-size-adjust", "font-stretch", "font-weight", "gap", "grid-template-columns", "height", "hyphenate-character", "hyphenate-limit-chars", "hyphens", "inert", "inline-size", "inset", "justify-content", "left", "letter-spacing", "light-dark", "line-height", "list-style", "list-style-image", "list-style-position", "list-style-type", "margin", "margin-block-start-end", "margin-inline-block", "margin-inline-start-end", "mask-image", "max-block-size", "max-height", "max-inline-size", "max-width", "min-block-size", "min-height", "min-inline-size", "min-width", "mix-blend-mode", "modern-color", "nesting", "object-fit", "object-position", "opacity", "orphans", "outline", "outline-offset", "overflow", "overflow-wrap", "padding", "padding-block-start-end", "padding-inline-block", "padding-inline-start-end", "position", "pseudo-class-active", "pseudo-class-default", "pseudo-class-nth-last-of-type", "resize", "rgb", "rgba", "right", "scroll-snap", "shape-margin", "shape-outside", "system-ui", "tab-size", "table-layout", "text-align", "text-align-last", "text-decoration", "text-decoration-color", "text-decoration-line", "text-decoration-skip-ink", "text-decoration-style", "text-decoration-thickness", "text-emphasis", "text-emphasis-position", "text-indent", "text-justify", "text-orientation", "text-overflow", "text-shadow", "text-transform", "text-underline-offset", "text-underline-position", "text-wrap", "top", "transform", "transition", "unit-ch", "unit-cm", "unit-em", "unit-ex", "unit-in", "unit-initial", "unit-mm", "unit-pc", "unit-percent", "unit-pt", "unit-px", "unit-rem", "unit-vh", "unit-vmax", "unit-vmin", "unit-vw", "user-select", "vertical-align", "visibility", "white-space", "white-space-collapse", "widows", "width", "word-break", "word-spacing", "writing-mode", "z-index"];
|
|
170
|
-
/** Every feature key in CSS_SUPPORT, as a type. */
|
|
171
|
-
type FeatureKey = (typeof HTML_ELEMENT_FEATURES)[number] | (typeof HTML_ATTRIBUTE_FEATURES)[number] | (typeof HTML_MISC_FEATURES)[number] | (typeof AT_RULE_FEATURES)[number] | (typeof COMPOUND_VALUE_FEATURES)[number] | (typeof SELECTOR_FEATURES)[number] | (typeof CSS_FUNCTION_FEATURES)[number] | (typeof CSS_PROPERTY_FEATURES)[number];
|
|
172
|
-
/** An image format caniemail grades. */
|
|
173
|
-
type ImageFormat = (typeof IMAGE_FORMATS)[number];
|
|
174
|
-
/** A client the matrix answers for. */
|
|
175
|
-
type ClientId = (typeof SUPPORT_CLIENTS)[number];
|
|
176
|
-
/**
|
|
177
|
-
* When caniemail last re-tested each feature. A feature's row is only as
|
|
178
|
-
* current as its test date, whatever the file's sync date says.
|
|
179
|
-
*/
|
|
180
|
-
declare const FEATURE_LAST_TESTED: Record<string, string>;
|
|
181
|
-
|
|
182
101
|
type SupportLevel = "supported" | "partial" | "unsupported" | "unknown";
|
|
183
102
|
type Framework = "jsx" | "mjml" | "maizzle";
|
|
184
103
|
type InputFormat = "html" | Framework;
|
|
185
104
|
interface EmailClient {
|
|
186
|
-
|
|
187
|
-
* Not a free string: the matrix answers for exactly these clients, so a
|
|
188
|
-
* client we ship without a column (or a column with no client) is a compile
|
|
189
|
-
* error rather than a silently empty section of every report.
|
|
190
|
-
*/
|
|
191
|
-
id: ClientId;
|
|
105
|
+
id: string;
|
|
192
106
|
name: string;
|
|
193
107
|
category: "webmail" | "desktop" | "mobile";
|
|
194
108
|
engine: string;
|
|
@@ -426,10 +340,31 @@ interface SizeIssue extends BaseIssue {
|
|
|
426
340
|
}
|
|
427
341
|
interface SizeReport {
|
|
428
342
|
htmlBytes: number;
|
|
343
|
+
/** Bytes of CSS inside `<style>` elements, summed across all of them. */
|
|
344
|
+
styleBytes: number;
|
|
429
345
|
humanSize: string;
|
|
430
346
|
clipped: boolean;
|
|
431
347
|
issues: SizeIssue[];
|
|
432
348
|
}
|
|
349
|
+
interface StyleSurvivalIssue extends BaseIssue {
|
|
350
|
+
/**
|
|
351
|
+
* The clients that discard the CSS. Required, not optional: the consuming
|
|
352
|
+
* app groups findings per client, and an issue that cannot name its clients
|
|
353
|
+
* does not surface at all.
|
|
354
|
+
*/
|
|
355
|
+
clients: string[];
|
|
356
|
+
detail?: string;
|
|
357
|
+
/**
|
|
358
|
+
* Where in the framework's source the offending CSS came from. Present only
|
|
359
|
+
* when the caller named a framework: the stylesheet that ships is assembled
|
|
360
|
+
* by the compiler, so "edit your <style> block" is the wrong instruction for
|
|
361
|
+
* someone whose source has no <style> block.
|
|
362
|
+
*/
|
|
363
|
+
frameworkNote?: string;
|
|
364
|
+
}
|
|
365
|
+
interface StyleSurvivalReport {
|
|
366
|
+
issues: StyleSurvivalIssue[];
|
|
367
|
+
}
|
|
433
368
|
interface OverflowIssue extends BaseIssue {
|
|
434
369
|
detail?: string;
|
|
435
370
|
}
|
|
@@ -495,4 +430,4 @@ interface DesignReport {
|
|
|
495
430
|
};
|
|
496
431
|
}
|
|
497
432
|
|
|
498
|
-
export { type
|
|
433
|
+
export { type AiProvider as A, type BaseIssue as B, type CSSWarning as C, type DiffResult as D, type EmailClient as E, type Framework as F, type LinkIssue as G, type OverflowIssue as H, type ImageReport as I, type Severity as J, type SizeIssue as K, type LinkReport as L, type SourceLocation as M, type SpamIssue as N, type OverflowReport as O, type PreviewResult as P, type TemplateIssue as Q, type TokenEstimate as R, type SupportLevel as S, type TransformResult as T, type TokenEstimateWithWarnings as U, type VmlReport as V, type VisualIssue as W, type VmlIssue as X, estimateAiFixTokens as Y, generateFixPrompt as Z, heuristicTokenCount as _, type CodeFix as a, type ExportPromptOptions as b, type AiFixResult as c, type StyleSurvivalReport as d, type SpamAnalysisOptions as e, type SpamReport as f, type AccessibilityReport as g, type AccessibilityIssue as h, type InboxPreview as i, type SizeReport as j, type TemplateReport as k, type VisualReport as l, type DesignReport as m, type DeliverabilityReport as n, type ClientTruncation as o, type DeliverabilityCheck as p, type DeliverabilityIssue as q, type DesignIssue as r, type EstimateOptions as s, type ExportScope as t, type FixType as u, type ImageInfo as v, type ImageIssue as w, type InboxPreviewIssue as x, type InputFormat as y, type LinkInfo as z };
|
|
@@ -98,97 +98,11 @@ declare function estimateAiFixTokens(options: EstimateOptions): Promise<TokenEst
|
|
|
98
98
|
*/
|
|
99
99
|
declare function heuristicTokenCount(text: string): number;
|
|
100
100
|
|
|
101
|
-
/**
|
|
102
|
-
* CSS/HTML feature support matrix, auto-generated from caniemail.com.
|
|
103
|
-
* Last synced: 2026-09-02
|
|
104
|
-
* caniemail last updated: 2026-08-10 15:16:24 +0000
|
|
105
|
-
*
|
|
106
|
-
* 298 features and 14 image formats across 21 email clients.
|
|
107
|
-
*
|
|
108
|
-
* Support levels:
|
|
109
|
-
* - "supported": fully supported
|
|
110
|
-
* - "partial": partially supported (with caveats)
|
|
111
|
-
* - "unsupported": not supported at all
|
|
112
|
-
* - "unknown": no data available
|
|
113
|
-
*
|
|
114
|
-
* Data sources:
|
|
115
|
-
* - Most clients: caniemail.com API (verified data)
|
|
116
|
-
* - hey-mail: caniemail.com (WebKit-based)
|
|
117
|
-
* - superhuman: Manual overrides (Chromium/Blink-based, best-effort estimates)
|
|
118
|
-
*
|
|
119
|
-
* A client we ship as one entry although caniemail tests it on several
|
|
120
|
-
* platforms (Proton Mail, AOL, Thunderbird) is graded on its worst
|
|
121
|
-
* platform. Gmail, Outlook, Yahoo and Apple Mail ship as separate clients
|
|
122
|
-
* per platform instead.
|
|
123
|
-
*
|
|
124
|
-
* DO NOT EDIT; regenerate with: bun run sync:caniemail
|
|
125
|
-
*/
|
|
126
|
-
/** The clients every row answers for, in report order. */
|
|
127
|
-
declare const SUPPORT_CLIENTS: readonly ["gmail-web", "gmail-android", "gmail-ios", "outlook-web", "outlook-windows", "outlook-windows-legacy", "outlook-ios", "outlook-android", "outlook-macos", "apple-mail-macos", "apple-mail-ios", "yahoo-mail", "yahoo-mail-android", "yahoo-mail-ios", "samsung-mail", "thunderbird", "hey-mail", "protonmail", "aol", "fastmail", "superhuman"];
|
|
128
|
-
declare const CSS_SUPPORT: Record<string, Record<ClientId, SupportLevel>>;
|
|
129
|
-
/**
|
|
130
|
-
* Caveat notes per (feature, client) from caniemail: the "why" behind a
|
|
131
|
-
* partial/buggy/unsupported rating. Sparse: only cells with a note appear.
|
|
132
|
-
*/
|
|
133
|
-
declare const CSS_SUPPORT_NOTES: Record<string, Record<string, string[]>>;
|
|
134
|
-
/**
|
|
135
|
-
* Image format support, keyed by format. Kept out of CSS_SUPPORT because an
|
|
136
|
-
* image format is a property of the `src`, not of a stylesheet: the image
|
|
137
|
-
* analyzer looks these up, the CSS analyzer never should.
|
|
138
|
-
*/
|
|
139
|
-
/** The image formats caniemail grades. */
|
|
140
|
-
declare const IMAGE_FORMATS: readonly ["apng", "avif", "base64", "bmp", "gif", "hdr", "heif", "ico", "jpg", "mp4", "png", "svg", "tiff", "webp"];
|
|
141
|
-
declare const IMAGE_SUPPORT: Record<string, Record<ClientId, SupportLevel>>;
|
|
142
|
-
/** Caveat notes per (image format, client), same shape as CSS_SUPPORT_NOTES. */
|
|
143
|
-
declare const IMAGE_SUPPORT_NOTES: Record<string, Record<string, string[]>>;
|
|
144
|
-
/**
|
|
145
|
-
* Features a client merely ignores when it "does not support" them: the
|
|
146
|
-
* email renders the same either way, so these report as info, not warnings.
|
|
147
|
-
*/
|
|
148
|
-
declare const GRACEFUL_FEATURES: ReadonlySet<string>;
|
|
149
|
-
/**
|
|
150
|
-
* Properties that require HTML structural changes (not just CSS swaps)
|
|
151
|
-
* to fix. These cannot be solved by replacing one CSS value with another.
|
|
152
|
-
*/
|
|
153
|
-
declare const STRUCTURAL_FIX_PROPERTIES: Set<string>;
|
|
154
|
-
/** HTML element features in the support matrix (for data-driven detection). */
|
|
155
|
-
declare const HTML_ELEMENT_FEATURES: readonly ["<abbr>", "<acronym>", "<address>", "<audio>", "<base>", "<bdi>", "<blockquote>", "<body>", "<button type=\"reset\">", "<button type=\"submit\">", "<code>", "<del>", "<dfn>", "<dialog>", "<div>", "<form>", "<h1>", "<hr>", "<img>", "<input type=\"checkbox\">", "<input type=\"hidden\">", "<input type=\"radio\">", "<input type=\"reset\">", "<input type=\"submit\">", "<input type=\"text\">", "<link>", "<marquee>", "<meter>", "<object>", "<p>", "<picture>", "<pre>", "<progress>", "<rp>", "<rt>", "<ruby>", "<select>", "<small>", "<span>", "<strike>", "<strong>", "<style>", "<svg>", "<table>", "<textarea>", "<ul>", "<video>", "<wbr>"];
|
|
156
|
-
/** HTML attribute features. Each key is also the cheerio selector that finds it. */
|
|
157
|
-
declare const HTML_ATTRIBUTE_FEATURES: readonly ["[align]", "[aria-describedby]", "[aria-hidden]", "[aria-label]", "[aria-labelledby]", "[aria-live]", "[background]", "[cellpadding]", "[cellspacing]", "[command]", "[dir]", "[height]", "[hidden]", "[lang]", "[loading]", "[popover]", "[required]", "[role]", "[srcset]", "[target]", "[valign]", "[width]"];
|
|
158
|
-
/** Document-level and link-shaped HTML features; each has a bespoke detector. */
|
|
159
|
-
declare const HTML_MISC_FEATURES: readonly ["amp4email", "anchor-links", "doctype", "html-comments", "html5-semantics", "image-maps", "mailto-links", "meta-color-scheme"];
|
|
160
|
-
/** CSS at-rule features, including the media features that qualify `@media`. */
|
|
161
|
-
declare const AT_RULE_FEATURES: readonly ["@font-face", "@import", "@keyframes", "@media", "@media device-pixel-ratio", "@media hover", "@media orientation", "@media prefers-color-scheme", "@media prefers-reduced-motion", "@supports"];
|
|
162
|
-
/** One property paired with one value, e.g. "display:flex". */
|
|
163
|
-
declare const COMPOUND_VALUE_FEATURES: readonly ["display:flex", "display:grid", "display:none"];
|
|
164
|
-
/** Pseudo-classes, pseudo-elements and combinators, e.g. ":hover", "::after". */
|
|
165
|
-
declare const SELECTOR_FEATURES: readonly ["::after", "::before", "::first-letter", "::first-line", "::marker", "::placeholder", ":adjacent-sibling", ":attribute-selector", ":chaining", ":checked", ":child-combinator", ":class-selector", ":descendant-combinator", ":first-child", ":first-of-type", ":focus", ":focus-visible", ":focus-within", ":general-sibling", ":grouping", ":has", ":hover", ":id-selector", ":lang", ":last-child", ":last-of-type", ":link", ":not", ":nth-child", ":nth-last-child", ":nth-of-type", ":only-child", ":only-of-type", ":target", ":type-selector", ":universal-selector", ":visited"];
|
|
166
|
-
/** CSS function features (e.g., "linear-gradient"). */
|
|
167
|
-
declare const CSS_FUNCTION_FEATURES: readonly ["calc", "clamp", "conic-gradient", "fit-content", "linear-gradient", "max", "min", "radial-gradient"];
|
|
168
|
-
/** Plain CSS property names: what an inline style or declaration can match. */
|
|
169
|
-
declare const CSS_PROPERTY_FEATURES: readonly ["!important", "accent-color", "align-items", "animation", "aspect-ratio", "backdrop-filter", "background", "background-blend-mode", "background-clip", "background-color", "background-image", "background-origin", "background-position", "background-repeat", "background-size", "bimi", "block-size", "border", "border-collapse", "border-image", "border-inline", "border-inline-individual", "border-inline-longhand", "border-radius", "border-radius-logical", "border-spacing", "bottom", "box-shadow", "box-sizing", "caption-side", "clear", "clip-path", "color", "color-scheme", "column-count", "columns", "css-comments", "cursor", "custom-properties", "direction", "display", "empty-cells", "filter", "flex-direction", "flex-wrap", "float", "font", "font-family", "font-kerning", "font-size", "font-size-adjust", "font-stretch", "font-weight", "gap", "grid-template-columns", "height", "hyphenate-character", "hyphenate-limit-chars", "hyphens", "inert", "inline-size", "inset", "justify-content", "left", "letter-spacing", "light-dark", "line-height", "list-style", "list-style-image", "list-style-position", "list-style-type", "margin", "margin-block-start-end", "margin-inline-block", "margin-inline-start-end", "mask-image", "max-block-size", "max-height", "max-inline-size", "max-width", "min-block-size", "min-height", "min-inline-size", "min-width", "mix-blend-mode", "modern-color", "nesting", "object-fit", "object-position", "opacity", "orphans", "outline", "outline-offset", "overflow", "overflow-wrap", "padding", "padding-block-start-end", "padding-inline-block", "padding-inline-start-end", "position", "pseudo-class-active", "pseudo-class-default", "pseudo-class-nth-last-of-type", "resize", "rgb", "rgba", "right", "scroll-snap", "shape-margin", "shape-outside", "system-ui", "tab-size", "table-layout", "text-align", "text-align-last", "text-decoration", "text-decoration-color", "text-decoration-line", "text-decoration-skip-ink", "text-decoration-style", "text-decoration-thickness", "text-emphasis", "text-emphasis-position", "text-indent", "text-justify", "text-orientation", "text-overflow", "text-shadow", "text-transform", "text-underline-offset", "text-underline-position", "text-wrap", "top", "transform", "transition", "unit-ch", "unit-cm", "unit-em", "unit-ex", "unit-in", "unit-initial", "unit-mm", "unit-pc", "unit-percent", "unit-pt", "unit-px", "unit-rem", "unit-vh", "unit-vmax", "unit-vmin", "unit-vw", "user-select", "vertical-align", "visibility", "white-space", "white-space-collapse", "widows", "width", "word-break", "word-spacing", "writing-mode", "z-index"];
|
|
170
|
-
/** Every feature key in CSS_SUPPORT, as a type. */
|
|
171
|
-
type FeatureKey = (typeof HTML_ELEMENT_FEATURES)[number] | (typeof HTML_ATTRIBUTE_FEATURES)[number] | (typeof HTML_MISC_FEATURES)[number] | (typeof AT_RULE_FEATURES)[number] | (typeof COMPOUND_VALUE_FEATURES)[number] | (typeof SELECTOR_FEATURES)[number] | (typeof CSS_FUNCTION_FEATURES)[number] | (typeof CSS_PROPERTY_FEATURES)[number];
|
|
172
|
-
/** An image format caniemail grades. */
|
|
173
|
-
type ImageFormat = (typeof IMAGE_FORMATS)[number];
|
|
174
|
-
/** A client the matrix answers for. */
|
|
175
|
-
type ClientId = (typeof SUPPORT_CLIENTS)[number];
|
|
176
|
-
/**
|
|
177
|
-
* When caniemail last re-tested each feature. A feature's row is only as
|
|
178
|
-
* current as its test date, whatever the file's sync date says.
|
|
179
|
-
*/
|
|
180
|
-
declare const FEATURE_LAST_TESTED: Record<string, string>;
|
|
181
|
-
|
|
182
101
|
type SupportLevel = "supported" | "partial" | "unsupported" | "unknown";
|
|
183
102
|
type Framework = "jsx" | "mjml" | "maizzle";
|
|
184
103
|
type InputFormat = "html" | Framework;
|
|
185
104
|
interface EmailClient {
|
|
186
|
-
|
|
187
|
-
* Not a free string: the matrix answers for exactly these clients, so a
|
|
188
|
-
* client we ship without a column (or a column with no client) is a compile
|
|
189
|
-
* error rather than a silently empty section of every report.
|
|
190
|
-
*/
|
|
191
|
-
id: ClientId;
|
|
105
|
+
id: string;
|
|
192
106
|
name: string;
|
|
193
107
|
category: "webmail" | "desktop" | "mobile";
|
|
194
108
|
engine: string;
|
|
@@ -426,10 +340,31 @@ interface SizeIssue extends BaseIssue {
|
|
|
426
340
|
}
|
|
427
341
|
interface SizeReport {
|
|
428
342
|
htmlBytes: number;
|
|
343
|
+
/** Bytes of CSS inside `<style>` elements, summed across all of them. */
|
|
344
|
+
styleBytes: number;
|
|
429
345
|
humanSize: string;
|
|
430
346
|
clipped: boolean;
|
|
431
347
|
issues: SizeIssue[];
|
|
432
348
|
}
|
|
349
|
+
interface StyleSurvivalIssue extends BaseIssue {
|
|
350
|
+
/**
|
|
351
|
+
* The clients that discard the CSS. Required, not optional: the consuming
|
|
352
|
+
* app groups findings per client, and an issue that cannot name its clients
|
|
353
|
+
* does not surface at all.
|
|
354
|
+
*/
|
|
355
|
+
clients: string[];
|
|
356
|
+
detail?: string;
|
|
357
|
+
/**
|
|
358
|
+
* Where in the framework's source the offending CSS came from. Present only
|
|
359
|
+
* when the caller named a framework: the stylesheet that ships is assembled
|
|
360
|
+
* by the compiler, so "edit your <style> block" is the wrong instruction for
|
|
361
|
+
* someone whose source has no <style> block.
|
|
362
|
+
*/
|
|
363
|
+
frameworkNote?: string;
|
|
364
|
+
}
|
|
365
|
+
interface StyleSurvivalReport {
|
|
366
|
+
issues: StyleSurvivalIssue[];
|
|
367
|
+
}
|
|
433
368
|
interface OverflowIssue extends BaseIssue {
|
|
434
369
|
detail?: string;
|
|
435
370
|
}
|
|
@@ -495,4 +430,4 @@ interface DesignReport {
|
|
|
495
430
|
};
|
|
496
431
|
}
|
|
497
432
|
|
|
498
|
-
export { type
|
|
433
|
+
export { type AiProvider as A, type BaseIssue as B, type CSSWarning as C, type DiffResult as D, type EmailClient as E, type Framework as F, type LinkIssue as G, type OverflowIssue as H, type ImageReport as I, type Severity as J, type SizeIssue as K, type LinkReport as L, type SourceLocation as M, type SpamIssue as N, type OverflowReport as O, type PreviewResult as P, type TemplateIssue as Q, type TokenEstimate as R, type SupportLevel as S, type TransformResult as T, type TokenEstimateWithWarnings as U, type VmlReport as V, type VisualIssue as W, type VmlIssue as X, estimateAiFixTokens as Y, generateFixPrompt as Z, heuristicTokenCount as _, type CodeFix as a, type ExportPromptOptions as b, type AiFixResult as c, type StyleSurvivalReport as d, type SpamAnalysisOptions as e, type SpamReport as f, type AccessibilityReport as g, type AccessibilityIssue as h, type InboxPreview as i, type SizeReport as j, type TemplateReport as k, type VisualReport as l, type DesignReport as m, type DeliverabilityReport as n, type ClientTruncation as o, type DeliverabilityCheck as p, type DeliverabilityIssue as q, type DesignIssue as r, type EstimateOptions as s, type ExportScope as t, type FixType as u, type ImageInfo as v, type ImageIssue as w, type InboxPreviewIssue as x, type InputFormat as y, type LinkInfo as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@emailens/engine",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.2",
|
|
4
4
|
"description": "Email compatibility engine for HTML, MJML, Maizzle and React Email: transforms CSS per email client, scores compatibility, simulates dark mode, suggests fixes, and runs spam, accessibility, link and image quality analysis.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/compile/maizzle.ts"],"sourcesContent":["import { CompileError } from \"./errors.js\";\r\n\r\n/** Maximum Maizzle source size: 512KB */\r\nconst MAX_SOURCE_SIZE = 512_000;\r\n\r\n/** Compilation timeout: 15 seconds */\r\nconst COMPILE_TIMEOUT_MS = 15_000;\r\n\r\n/**\r\n * PostHTML directives that perform file-system reads or network fetches.\r\n *\r\n * Maizzle's PostHTML pipeline resolves these at compile time: a template\r\n * like `<extends src=\"/etc/passwd\">` causes the server to read that path\r\n * and include the content in rendered output (server-side file read). We\r\n * reject any input containing these directives rather than stripping them,\r\n * because stripping is error-prone with nested or malformed markup.\r\n *\r\n * Affected plugins: posthtml-extend, posthtml-fetch, posthtml-components,\r\n * posthtml-include, posthtml-modules.\r\n */\r\nconst DANGEROUS_DIRECTIVE_RE =\r\n /<\\s*(?:extends|component|fetch|include|module|slot|fill|raw|block|yield)\\b/i;\r\n\r\n/**\r\n * Compile a Maizzle template string into an HTML email string.\r\n *\r\n * Pipeline:\r\n * 1. Validate input (size, basic structure check)\r\n * 2. Reject inputs containing PostHTML file-access directives\r\n * 3. Compile using @maizzle/framework\r\n *\r\n * Security:\r\n * - PostHTML file-system directives are rejected at validation time\r\n * to prevent server-side file reads and SSRF.\r\n * - Template expressions ({{ expr }}) are evaluated by posthtml-expressions\r\n * with empty `locals`, so unknown identifiers like `process` or `require`\r\n * return the literal string '{local}' rather than accessing Node.js globals.\r\n * - A hard timeout prevents pathological PostCSS/Tailwind inputs from\r\n * hanging indefinitely.\r\n *\r\n * Requires peer dependency: @maizzle/framework\r\n */\r\nexport async function compileMaizzle(source: string): Promise<string> {\r\n // ── 1. Validate ──────────────────────────────────────────────────────\r\n if (!source || !source.trim()) {\r\n throw new CompileError(\"Maizzle source must not be empty.\", \"maizzle\", \"validation\");\r\n }\r\n\r\n if (source.length > MAX_SOURCE_SIZE) {\r\n throw new CompileError(\r\n `Maizzle source exceeds ${MAX_SOURCE_SIZE / 1000}KB limit.`,\r\n \"maizzle\",\r\n \"validation\",\r\n );\r\n }\r\n\r\n // ── 2. Block file-system and network PostHTML directives ─────────────\r\n if (DANGEROUS_DIRECTIVE_RE.test(source)) {\r\n throw new CompileError(\r\n \"Maizzle templates may not use <extends>, <component>, <fetch>, <include>, \" +\r\n \"<module>, <slot>, <fill>, <raw>, <block>, or <yield> directives. These directives \" +\r\n \"access the server file system at compile time. Use inline HTML and Tailwind utility classes instead.\",\r\n \"maizzle\",\r\n \"validation\",\r\n );\r\n }\r\n\r\n // ── 3. Load peer dependency ──────────────────────────────────────────\r\n let maizzleRender: (\r\n input: string,\r\n options: Record<string, unknown>,\r\n ) => Promise<{ html: string }>;\r\n\r\n try {\r\n const maizzle = await import(\"@maizzle/framework\");\r\n maizzleRender = maizzle.render;\r\n } catch {\r\n throw new CompileError(\r\n 'Maizzle compilation requires \"@maizzle/framework\". Install it:\\n npm install @maizzle/framework',\r\n \"maizzle\",\r\n \"compile\",\r\n );\r\n }\r\n\r\n // ── 4. Compile with timeout ──────────────────────────────────────────\r\n const compilePromise = maizzleRender(source, {\r\n css: {\r\n inline: {\r\n removeInlinedSelectors: true,\r\n applyWidthAttributes: true,\r\n applyHeightAttributes: true,\r\n },\r\n shorthand: true,\r\n sixHex: true,\r\n },\r\n locals: {},\r\n });\r\n\r\n const timeoutPromise = new Promise<never>((_, reject) => {\r\n const t = setTimeout(() => {\r\n reject(\r\n new CompileError(\r\n `Maizzle compilation timed out after ${COMPILE_TIMEOUT_MS / 1000}s.`,\r\n \"maizzle\",\r\n \"compile\",\r\n ),\r\n );\r\n }, COMPILE_TIMEOUT_MS);\r\n if (typeof t.unref === \"function\") t.unref();\r\n });\r\n\r\n try {\r\n const { html } = await Promise.race([compilePromise, timeoutPromise]);\r\n\r\n if (!html) {\r\n throw new CompileError(\"Maizzle compilation produced empty output.\", \"maizzle\", \"compile\");\r\n }\r\n\r\n return html;\r\n } catch (err: unknown) {\r\n if (err instanceof CompileError) throw err;\r\n const message = err instanceof Error ? err.message : \"Unknown Maizzle compilation error\";\r\n throw new CompileError(`Maizzle compilation failed: ${message}`, \"maizzle\", \"compile\");\r\n }\r\n}\r\n"],"mappings":";;;;;AAGA,IAAM,kBAAkB;AAGxB,IAAM,qBAAqB;AAc3B,IAAM,yBACJ;AAqBF,eAAsB,eAAe,QAAiC;AAEpE,MAAI,CAAC,UAAU,CAAC,OAAO,KAAK,GAAG;AAC7B,UAAM,IAAI,aAAa,qCAAqC,WAAW,YAAY;AAAA,EACrF;AAEA,MAAI,OAAO,SAAS,iBAAiB;AACnC,UAAM,IAAI;AAAA,MACR,0BAA0B,kBAAkB,GAAI;AAAA,MAChD;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,MAAI,uBAAuB,KAAK,MAAM,GAAG;AACvC,UAAM,IAAI;AAAA,MACR;AAAA,MAGA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AAKJ,MAAI;AACF,UAAM,UAAU,MAAM,OAAO,oBAAoB;AACjD,oBAAgB,QAAQ;AAAA,EAC1B,SAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,QAAM,iBAAiB,cAAc,QAAQ;AAAA,IAC3C,KAAK;AAAA,MACH,QAAQ;AAAA,QACN,wBAAwB;AAAA,QACxB,sBAAsB;AAAA,QACtB,uBAAuB;AAAA,MACzB;AAAA,MACA,WAAW;AAAA,MACX,QAAQ;AAAA,IACV;AAAA,IACA,QAAQ,CAAC;AAAA,EACX,CAAC;AAED,QAAM,iBAAiB,IAAI,QAAe,CAAC,GAAG,WAAW;AACvD,UAAM,IAAI,WAAW,MAAM;AACzB;AAAA,QACE,IAAI;AAAA,UACF,uCAAuC,qBAAqB,GAAI;AAAA,UAChE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,GAAG,kBAAkB;AACrB,QAAI,OAAO,EAAE,UAAU,WAAY,GAAE,MAAM;AAAA,EAC7C,CAAC;AAED,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,MAAM,QAAQ,KAAK,CAAC,gBAAgB,cAAc,CAAC;AAEpE,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,aAAa,8CAA8C,WAAW,SAAS;AAAA,IAC3F;AAEA,WAAO;AAAA,EACT,SAAS,KAAc;AACrB,QAAI,eAAe,aAAc,OAAM;AACvC,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,UAAM,IAAI,aAAa,+BAA+B,OAAO,IAAI,WAAW,SAAS;AAAA,EACvF;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/compile/react-email.ts"],"sourcesContent":["import { CompileError } from \"./errors.js\";\r\n\r\n/** Maximum source code size: 256KB */\r\nconst MAX_SOURCE_SIZE = 256_000;\r\n\r\n/** Execution timeout: 5 seconds */\r\nconst EXECUTION_TIMEOUT_MS = 5_000;\r\n\r\n/**\r\n * Sandbox strategy for JSX execution.\r\n *\r\n * - `\"vm\"`: `node:vm` with hardened globals. Fast, zero-dependency,\r\n * but NOT a true security boundary (prototype-chain escapes are possible).\r\n * Suitable for CLI / local use where users run their own code.\r\n *\r\n * - `\"isolated-vm\"` (default): Separate V8 isolate via the `isolated-vm`\r\n * npm package. True heap isolation; escapes require a V8 engine bug.\r\n * Requires `isolated-vm` to be installed (native addon).\r\n *\r\n * - `\"quickjs\"`: Validates code structure in a QuickJS WASM sandbox, then\r\n * executes in `node:vm` for React rendering. Security is equivalent to\r\n * `node:vm`: the QuickJS phase validates import restrictions only.\r\n * No native addons needed, but only supports ES2020 and is slower.\r\n * For true isolation on servers, use `isolated-vm`.\r\n */\r\nexport type SandboxStrategy = \"vm\" | \"isolated-vm\" | \"quickjs\";\r\n\r\nexport interface CompileReactEmailOptions {\r\n /**\r\n * Sandbox strategy to use for executing user JSX code.\r\n * @default \"isolated-vm\"\r\n */\r\n sandbox?: SandboxStrategy;\r\n}\r\n\r\n/**\r\n * Compile a React Email JSX/TSX source string into an HTML email string.\r\n *\r\n * Pipeline:\r\n * 1. Validate input (size, basic checks)\r\n * 2. Transpile JSX/TSX → CommonJS JS using sucrase\r\n * 3. Execute inside a sandbox (configurable strategy)\r\n * 4. Render the exported component to a full HTML email string\r\n *\r\n * Requires peer dependencies: sucrase, react, @react-email/components,\r\n * @react-email/render. Additionally:\r\n * - sandbox \"isolated-vm\" requires `isolated-vm`\r\n * - sandbox \"quickjs\" requires `quickjs-emscripten`\r\n */\r\nexport async function compileReactEmail(\r\n source: string,\r\n options?: CompileReactEmailOptions,\r\n): Promise<string> {\r\n const strategy = options?.sandbox ?? \"isolated-vm\";\r\n\r\n // ── 1. Validate ──────────────────────────────────────────────────────\r\n if (!source || !source.trim()) {\r\n throw new CompileError(\"JSX source must not be empty.\", \"jsx\", \"validation\");\r\n }\r\n\r\n if (source.length > MAX_SOURCE_SIZE) {\r\n throw new CompileError(\r\n `JSX source exceeds ${MAX_SOURCE_SIZE / 1000}KB limit.`,\r\n \"jsx\",\r\n \"validation\",\r\n );\r\n }\r\n\r\n // ── 2. Load peer dependencies ────────────────────────────────────────\r\n let transform: typeof import(\"sucrase\").transform;\r\n let React: typeof import(\"react\");\r\n let ReactEmailComponents: typeof import(\"@react-email/components\");\r\n let render: typeof import(\"@react-email/render\").render;\r\n\r\n try {\r\n ({ transform } = await import(\"sucrase\"));\r\n } catch {\r\n throw new CompileError(\r\n 'JSX compilation requires \"sucrase\". Install it:\\n npm install sucrase',\r\n \"jsx\",\r\n \"transpile\",\r\n );\r\n }\r\n\r\n try {\r\n React = await import(\"react\");\r\n } catch {\r\n throw new CompileError(\r\n 'JSX compilation requires \"react\". Install it:\\n npm install react',\r\n \"jsx\",\r\n \"transpile\",\r\n );\r\n }\r\n\r\n try {\r\n ReactEmailComponents = await import(\"@react-email/components\");\r\n } catch {\r\n throw new CompileError(\r\n 'JSX compilation requires \"@react-email/components\". Install it:\\n npm install @react-email/components',\r\n \"jsx\",\r\n \"transpile\",\r\n );\r\n }\r\n\r\n try {\r\n ({ render } = await import(\"@react-email/render\"));\r\n } catch {\r\n throw new CompileError(\r\n 'JSX compilation requires \"@react-email/render\". Install it:\\n npm install @react-email/render',\r\n \"jsx\",\r\n \"transpile\",\r\n );\r\n }\r\n\r\n // ── 3. Transpile JSX/TSX → CommonJS ──────────────────────────────────\r\n let transpiledCode: string;\r\n try {\r\n const result = transform(source, {\r\n transforms: [\"typescript\", \"jsx\", \"imports\"],\r\n jsxRuntime: \"classic\",\r\n production: true,\r\n });\r\n transpiledCode = result.code;\r\n } catch (err: unknown) {\r\n const message = err instanceof Error ? err.message : \"Unknown transpilation error\";\r\n throw new CompileError(`JSX syntax error: ${message}`, \"jsx\", \"transpile\");\r\n }\r\n\r\n // ── 4. Execute in sandbox ────────────────────────────────────────────\r\n let moduleExports: Record<string, unknown>;\r\n\r\n switch (strategy) {\r\n case \"isolated-vm\":\r\n moduleExports = await executeInIsolatedVm(transpiledCode, React, ReactEmailComponents);\r\n break;\r\n case \"quickjs\":\r\n moduleExports = await executeInQuickJs(transpiledCode, React, ReactEmailComponents);\r\n break;\r\n case \"vm\":\r\n moduleExports = await executeInVm(transpiledCode, React, ReactEmailComponents);\r\n break;\r\n default:\r\n throw new CompileError(\r\n `Unknown sandbox strategy: \"${strategy}\". Use \"vm\", \"isolated-vm\", or \"quickjs\".`,\r\n \"jsx\",\r\n \"execution\",\r\n );\r\n }\r\n\r\n // ── 5. Extract component and render ──────────────────────────────────\r\n let Component: unknown = moduleExports.default ?? moduleExports;\r\n\r\n if (typeof Component !== \"function\" && typeof Component === \"object\" && Component !== null) {\r\n const values = Object.values(Component as Record<string, unknown>);\r\n const fn = values.find((v) => typeof v === \"function\");\r\n if (fn) Component = fn;\r\n }\r\n\r\n if (typeof Component !== \"function\") {\r\n throw new CompileError(\r\n 'The JSX source must export a React component function. ' +\r\n 'Use \"export default function Email() { ... }\" or ' +\r\n '\"export function Email() { ... }\".',\r\n \"jsx\",\r\n \"execution\",\r\n );\r\n }\r\n\r\n try {\r\n const element = React.createElement(Component as React.FC);\r\n const html = await render(element);\r\n return html;\r\n } catch (err: unknown) {\r\n const message = err instanceof Error ? err.message : \"Unknown rendering error\";\r\n throw new CompileError(`React rendering error: ${message}`, \"jsx\", \"render\");\r\n }\r\n}\r\n\r\n// ─── Sandbox: node:vm ──────────────────────────────────────────────────────\r\n\r\n/**\r\n * Execute transpiled code in a node:vm context with hardened globals.\r\n *\r\n * NOT a security boundary, see node:vm documentation. Suitable for CLI\r\n * use where the user runs their own code. For server use, prefer\r\n * \"isolated-vm\" or \"quickjs\".\r\n */\r\nasync function executeInVm(\r\n code: string,\r\n React: typeof import(\"react\"),\r\n ReactEmailComponents: typeof import(\"@react-email/components\"),\r\n): Promise<Record<string, unknown>> {\r\n const { createContext, Script } = await import(\"node:vm\");\r\n\r\n const ALLOWED_MODULES: Record<string, unknown> = {\r\n react: React,\r\n \"@react-email/components\": ReactEmailComponents,\r\n };\r\n\r\n const moduleExports: Record<string, unknown> = {};\r\n const moduleObj = { exports: moduleExports };\r\n\r\n const mockRequire = (moduleName: string): unknown => {\r\n if (moduleName in ALLOWED_MODULES) {\r\n return ALLOWED_MODULES[moduleName];\r\n }\r\n throw new Error(\r\n `Import of \"${moduleName}\" is not allowed. ` +\r\n `Only \"react\" and \"@react-email/components\" can be imported.`,\r\n );\r\n };\r\n\r\n const sandbox: Record<string, unknown> = {\r\n module: moduleObj,\r\n exports: moduleExports,\r\n require: mockRequire,\r\n React,\r\n Object, Array, String, Number, Boolean,\r\n Map, Set, WeakMap, WeakSet,\r\n JSON, Math, Date, RegExp,\r\n Error, TypeError, RangeError, ReferenceError, SyntaxError, URIError,\r\n Promise, Symbol,\r\n Proxy: undefined, Reflect: undefined,\r\n parseInt, parseFloat, isNaN, isFinite,\r\n encodeURIComponent, decodeURIComponent, encodeURI, decodeURI,\r\n undefined, NaN, Infinity,\r\n console: { log: () => {}, warn: () => {}, error: () => {}, info: () => {}, debug: () => {} },\r\n setTimeout: undefined, setInterval: undefined, setImmediate: undefined, queueMicrotask: undefined,\r\n process: undefined, globalThis: undefined, global: undefined, Buffer: undefined,\r\n __dirname: undefined, __filename: undefined,\r\n };\r\n\r\n const context = createContext(sandbox, {\r\n codeGeneration: { strings: false, wasm: false },\r\n });\r\n\r\n try {\r\n const script = new Script(code, { filename: \"user-email-component.tsx\" });\r\n script.runInContext(context, { timeout: EXECUTION_TIMEOUT_MS, displayErrors: true });\r\n } catch (err: unknown) {\r\n const message = err instanceof Error ? err.message : \"Unknown execution error\";\r\n if (message.includes(\"Script execution timed out\")) {\r\n throw new CompileError(\"JSX execution timed out (possible infinite loop).\", \"jsx\", \"execution\");\r\n }\r\n throw new CompileError(`JSX execution error: ${message}`, \"jsx\", \"execution\");\r\n }\r\n\r\n return moduleObj.exports as Record<string, unknown>;\r\n}\r\n\r\n// ─── Sandbox: isolated-vm ──────────────────────────────────────────────────\r\n\r\n/**\r\n * Validate code in a separate V8 isolate, then execute in `node:vm`.\r\n *\r\n * Two-phase approach:\r\n * 1. **Validate**: run the transpiled code in a true V8 isolate with stub\r\n * React/component implementations. This catches disallowed imports and\r\n * structural errors inside a genuine security boundary (separate heap,\r\n * 128 MB memory cap, timeout). Escape requires a V8 engine bug.\r\n * 2. **Execute**: run the validated code in `node:vm` with real React\r\n * objects for actual rendering.\r\n *\r\n * Why two phases: React's internal type system uses Symbols\r\n * (`Symbol(react.forward_ref)`, `Symbol(react.element)`, etc.) which cannot\r\n * be transferred across V8 isolate boundaries, the structured clone\r\n * algorithm does not support Symbols. Running React code directly inside\r\n * `isolated-vm` is not possible.\r\n */\r\nasync function executeInIsolatedVm(\r\n code: string,\r\n React: typeof import(\"react\"),\r\n ReactEmailComponents: typeof import(\"@react-email/components\"),\r\n): Promise<Record<string, unknown>> {\r\n let ivm: typeof import(\"isolated-vm\");\r\n try {\r\n const ivmMod = await import(\"isolated-vm\");\r\n ivm = (ivmMod as any).default ?? ivmMod;\r\n } catch {\r\n throw new CompileError(\r\n 'Sandbox strategy \"isolated-vm\" requires the \"isolated-vm\" package. Install it:\\n' +\r\n \" npm install isolated-vm\\n\" +\r\n 'Or use sandbox: \"vm\" for a lighter (but less secure) alternative.',\r\n \"jsx\",\r\n \"execution\",\r\n );\r\n }\r\n\r\n // ── Phase 1: Validate in a true V8 isolate ─────────────────────────────\r\n const isolate = new ivm.Isolate({ memoryLimit: 128 });\r\n try {\r\n const ivmContext = await isolate.createContext();\r\n\r\n // Stub implementations let the code parse and execute structurally\r\n // without needing real React objects (which contain non-cloneable Symbols).\r\n // Stub React: createElement returns a plain object, forwardRef passes\r\n // through, and any unknown property returns a no-op function. The Proxy\r\n // on the components module ensures that any named import (Html, Head,\r\n // Button, etc.) resolves to a dummy component function so the transpiled\r\n // code can execute structurally without real React objects.\r\n const validationCode = `\r\n (function() {\r\n var module = { exports: {} };\r\n var exports = module.exports;\r\n var noop = function() { return {}; };\r\n var React = new Proxy({\r\n createElement: noop,\r\n forwardRef: function(fn) { return fn; },\r\n Fragment: \"Fragment\",\r\n createContext: function() { return { Provider: noop, Consumer: noop }; },\r\n useState: function(v) { return [v, noop]; },\r\n useRef: function() { return { current: null }; },\r\n useEffect: noop,\r\n useMemo: function(fn) { return fn(); },\r\n useCallback: function(fn) { return fn; },\r\n Children: { map: noop, forEach: noop, toArray: function() { return []; } },\r\n }, { get: function(t, p) { return p in t ? t[p] : noop; } });\r\n var componentsProxy = new Proxy({}, {\r\n get: function() { return noop; }\r\n });\r\n function require(name) {\r\n if (name === \"react\") return React;\r\n if (name === \"@react-email/components\") return componentsProxy;\r\n throw new Error('Import of \"' + name + '\" is not allowed. Only \"react\" and \"@react-email/components\" can be imported.');\r\n }\r\n try {\r\n ${code}\r\n return JSON.stringify({ ok: true });\r\n } catch(e) {\r\n return JSON.stringify({ ok: false, error: e.message || \"Unknown error\" });\r\n }\r\n })()\r\n `;\r\n\r\n try {\r\n const result = await ivmContext.eval(validationCode, {\r\n timeout: EXECUTION_TIMEOUT_MS,\r\n });\r\n\r\n if (typeof result === \"string\") {\r\n const parsed = JSON.parse(result) as { ok: boolean; error?: string };\r\n if (!parsed.ok) {\r\n throw new CompileError(\r\n `JSX execution error: ${parsed.error ?? \"Unknown error\"}`,\r\n \"jsx\",\r\n \"execution\",\r\n );\r\n }\r\n }\r\n } catch (err: unknown) {\r\n if (err instanceof CompileError) throw err;\r\n const message = err instanceof Error ? err.message : \"Unknown execution error\";\r\n if (message.includes(\"timed out\") || message.includes(\"Timeout\")) {\r\n throw new CompileError(\"JSX execution timed out (possible infinite loop).\", \"jsx\", \"execution\");\r\n }\r\n throw new CompileError(`JSX execution error: ${message}`, \"jsx\", \"execution\");\r\n }\r\n } finally {\r\n isolate.dispose();\r\n }\r\n\r\n // ── Phase 2: Execute validated code in node:vm with real React ──────────\r\n return executeInVm(code, React, ReactEmailComponents);\r\n}\r\n\r\n// ─── Sandbox: QuickJS (WASM) ──────────────────────────────────────────────\r\n\r\n/**\r\n * Validate code structure in QuickJS WASM, then execute in `node:vm`.\r\n *\r\n * Two-phase approach:\r\n * 1. Validate that the code doesn't access disallowed modules by running it\r\n * in a QuickJS WASM sandbox with stub implementations.\r\n * 2. Execute in `node:vm` for actual React rendering (React objects can't\r\n * cross the WASM boundary).\r\n *\r\n * **Security note:** The actual execution happens in `node:vm`, so runtime\r\n * security is equivalent to the `\"vm\"` strategy. The QuickJS phase only\r\n * validates import restrictions. For true isolation on servers, use\r\n * `\"isolated-vm\"`.\r\n */\r\nasync function executeInQuickJs(\r\n code: string,\r\n React: typeof import(\"react\"),\r\n ReactEmailComponents: typeof import(\"@react-email/components\"),\r\n): Promise<Record<string, unknown>> {\r\n let getQuickJS: typeof import(\"quickjs-emscripten\").getQuickJS;\r\n try {\r\n ({ getQuickJS } = await import(\"quickjs-emscripten\"));\r\n } catch {\r\n throw new CompileError(\r\n 'Sandbox strategy \"quickjs\" requires the \"quickjs-emscripten\" package. Install it:\\n' +\r\n \" npm install quickjs-emscripten\\n\" +\r\n 'Or use sandbox: \"vm\" for a lighter alternative.',\r\n \"jsx\",\r\n \"execution\",\r\n );\r\n }\r\n\r\n const QuickJS = await getQuickJS();\r\n const vm = QuickJS.newContext();\r\n\r\n try {\r\n // Phase 1: Validate code safety in the WASM sandbox.\r\n // We provide stub implementations of React and the module system so\r\n // the code can execute without errors, but we only care that it\r\n // doesn't try to access anything dangerous.\r\n // QuickJS (ES2020) does not support Proxy, so we enumerate known\r\n // React Email component names as stub functions instead.\r\n const validationCode = `\r\n (function() {\r\n var module = { exports: {} };\r\n var exports = module.exports;\r\n var noop = function() { return {}; };\r\n var React = {\r\n createElement: noop,\r\n forwardRef: function(fn) { return fn; },\r\n Fragment: \"Fragment\",\r\n createContext: function() { return { Provider: noop, Consumer: noop }; },\r\n useState: function(v) { return [v, noop]; },\r\n useRef: function() { return { current: null }; },\r\n useEffect: noop,\r\n useMemo: function(fn) { return fn(); },\r\n useCallback: function(fn) { return fn; },\r\n Children: { map: noop, forEach: noop, toArray: function() { return []; } },\r\n };\r\n var components = {};\r\n var names = [\r\n \"Html\",\"Head\",\"Body\",\"Container\",\"Section\",\"Row\",\"Column\",\"Text\",\r\n \"Link\",\"Button\",\"Img\",\"Hr\",\"Preview\",\"Heading\",\"Font\",\"Style\",\r\n \"CodeBlock\",\"CodeInline\",\"Markdown\",\"Tailwind\",\"Responsive\",\r\n ];\r\n for (var i = 0; i < names.length; i++) components[names[i]] = noop;\r\n function require(name) {\r\n if (name === \"react\") return React;\r\n if (name === \"@react-email/components\") return components;\r\n throw new Error('Import of \"' + name + '\" is not allowed.');\r\n }\r\n try {\r\n ${code}\r\n return JSON.stringify({ ok: true });\r\n } catch(e) {\r\n return JSON.stringify({ ok: false, error: e.message || \"Unknown error\" });\r\n }\r\n })()\r\n `;\r\n\r\n const result = vm.evalCode(validationCode);\r\n if (result.error) {\r\n const errorVal = vm.dump(result.error);\r\n result.error.dispose();\r\n throw new CompileError(\r\n `JSX execution error: ${typeof errorVal === \"string\" ? errorVal : \"QuickJS execution failed\"}`,\r\n \"jsx\",\r\n \"execution\",\r\n );\r\n }\r\n\r\n const resultStr = vm.dump(result.value);\r\n result.value.dispose();\r\n\r\n if (typeof resultStr === \"string\") {\r\n const parsed = JSON.parse(resultStr) as { ok: boolean; error?: string };\r\n if (!parsed.ok) {\r\n throw new CompileError(\r\n `JSX execution error: ${parsed.error ?? \"Unknown error\"}`,\r\n \"jsx\",\r\n \"execution\",\r\n );\r\n }\r\n }\r\n\r\n // Phase 2: Code validated as safe; execute in node:vm for actual\r\n // React rendering (React objects can't cross the WASM boundary)\r\n return executeInVm(code, React, ReactEmailComponents);\r\n } finally {\r\n vm.dispose();\r\n }\r\n}\r\n"],"mappings":";;;;;AAGA,IAAM,kBAAkB;AAGxB,IAAM,uBAAuB;AA2C7B,eAAsB,kBACpB,QACA,SACiB;AApDnB;AAqDE,QAAM,YAAW,wCAAS,YAAT,YAAoB;AAGrC,MAAI,CAAC,UAAU,CAAC,OAAO,KAAK,GAAG;AAC7B,UAAM,IAAI,aAAa,iCAAiC,OAAO,YAAY;AAAA,EAC7E;AAEA,MAAI,OAAO,SAAS,iBAAiB;AACnC,UAAM,IAAI;AAAA,MACR,sBAAsB,kBAAkB,GAAI;AAAA,MAC5C;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI;AACF,KAAC,EAAE,UAAU,IAAI,MAAM,OAAO,SAAS;AAAA,EACzC,SAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,YAAQ,MAAM,OAAO,OAAO;AAAA,EAC9B,SAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,2BAAuB,MAAM,OAAO,yBAAyB;AAAA,EAC/D,SAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,KAAC,EAAE,OAAO,IAAI,MAAM,OAAO,qBAAqB;AAAA,EAClD,SAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AACJ,MAAI;AACF,UAAM,SAAS,UAAU,QAAQ;AAAA,MAC/B,YAAY,CAAC,cAAc,OAAO,SAAS;AAAA,MAC3C,YAAY;AAAA,MACZ,YAAY;AAAA,IACd,CAAC;AACD,qBAAiB,OAAO;AAAA,EAC1B,SAAS,KAAc;AACrB,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,UAAM,IAAI,aAAa,qBAAqB,OAAO,IAAI,OAAO,WAAW;AAAA,EAC3E;AAGA,MAAI;AAEJ,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,sBAAgB,MAAM,oBAAoB,gBAAgB,OAAO,oBAAoB;AACrF;AAAA,IACF,KAAK;AACH,sBAAgB,MAAM,iBAAiB,gBAAgB,OAAO,oBAAoB;AAClF;AAAA,IACF,KAAK;AACH,sBAAgB,MAAM,YAAY,gBAAgB,OAAO,oBAAoB;AAC7E;AAAA,IACF;AACE,YAAM,IAAI;AAAA,QACR,8BAA8B,QAAQ;AAAA,QACtC;AAAA,QACA;AAAA,MACF;AAAA,EACJ;AAGA,MAAI,aAAqB,mBAAc,YAAd,YAAyB;AAElD,MAAI,OAAO,cAAc,cAAc,OAAO,cAAc,YAAY,cAAc,MAAM;AAC1F,UAAM,SAAS,OAAO,OAAO,SAAoC;AACjE,UAAM,KAAK,OAAO,KAAK,CAAC,MAAM,OAAO,MAAM,UAAU;AACrD,QAAI,GAAI,aAAY;AAAA,EACtB;AAEA,MAAI,OAAO,cAAc,YAAY;AACnC,UAAM,IAAI;AAAA,MACR;AAAA,MAGA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,UAAM,UAAU,MAAM,cAAc,SAAqB;AACzD,UAAM,OAAO,MAAM,OAAO,OAAO;AACjC,WAAO;AAAA,EACT,SAAS,KAAc;AACrB,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,UAAM,IAAI,aAAa,0BAA0B,OAAO,IAAI,OAAO,QAAQ;AAAA,EAC7E;AACF;AAWA,eAAe,YACb,MACA,OACA,sBACkC;AAClC,QAAM,EAAE,eAAe,OAAO,IAAI,MAAM,OAAO,IAAS;AAExD,QAAM,kBAA2C;AAAA,IAC/C,OAAO;AAAA,IACP,2BAA2B;AAAA,EAC7B;AAEA,QAAM,gBAAyC,CAAC;AAChD,QAAM,YAAY,EAAE,SAAS,cAAc;AAE3C,QAAM,cAAc,CAAC,eAAgC;AACnD,QAAI,cAAc,iBAAiB;AACjC,aAAO,gBAAgB,UAAU;AAAA,IACnC;AACA,UAAM,IAAI;AAAA,MACR,cAAc,UAAU;AAAA,IAE1B;AAAA,EACF;AAEA,QAAM,UAAmC;AAAA,IACvC,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IAAQ;AAAA,IAAO;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAC/B;AAAA,IAAK;AAAA,IAAK;AAAA,IAAS;AAAA,IACnB;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAClB;AAAA,IAAO;AAAA,IAAW;AAAA,IAAY;AAAA,IAAgB;AAAA,IAAa;AAAA,IAC3D;AAAA,IAAS;AAAA,IACT,OAAO;AAAA,IAAW,SAAS;AAAA,IAC3B;AAAA,IAAU;AAAA,IAAY;AAAA,IAAO;AAAA,IAC7B;AAAA,IAAoB;AAAA,IAAoB;AAAA,IAAW;AAAA,IACnD;AAAA,IAAW;AAAA,IAAK;AAAA,IAChB,SAAS,EAAE,KAAK,MAAM;AAAA,IAAC,GAAG,MAAM,MAAM;AAAA,IAAC,GAAG,OAAO,MAAM;AAAA,IAAC,GAAG,MAAM,MAAM;AAAA,IAAC,GAAG,OAAO,MAAM;AAAA,IAAC,EAAE;AAAA,IAC3F,YAAY;AAAA,IAAW,aAAa;AAAA,IAAW,cAAc;AAAA,IAAW,gBAAgB;AAAA,IACxF,SAAS;AAAA,IAAW,YAAY;AAAA,IAAW,QAAQ;AAAA,IAAW,QAAQ;AAAA,IACtE,WAAW;AAAA,IAAW,YAAY;AAAA,EACpC;AAEA,QAAM,UAAU,cAAc,SAAS;AAAA,IACrC,gBAAgB,EAAE,SAAS,OAAO,MAAM,MAAM;AAAA,EAChD,CAAC;AAED,MAAI;AACF,UAAM,SAAS,IAAI,OAAO,MAAM,EAAE,UAAU,2BAA2B,CAAC;AACxE,WAAO,aAAa,SAAS,EAAE,SAAS,sBAAsB,eAAe,KAAK,CAAC;AAAA,EACrF,SAAS,KAAc;AACrB,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,QAAI,QAAQ,SAAS,4BAA4B,GAAG;AAClD,YAAM,IAAI,aAAa,qDAAqD,OAAO,WAAW;AAAA,IAChG;AACA,UAAM,IAAI,aAAa,wBAAwB,OAAO,IAAI,OAAO,WAAW;AAAA,EAC9E;AAEA,SAAO,UAAU;AACnB;AAqBA,eAAe,oBACb,MACA,OACA,sBACkC;AAjRpC;AAkRE,MAAI;AACJ,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,aAAa;AACzC,WAAO,YAAe,YAAf,YAA0B;AAAA,EACnC,SAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,MAGA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,QAAM,UAAU,IAAI,IAAI,QAAQ,EAAE,aAAa,IAAI,CAAC;AACpD,MAAI;AACF,UAAM,aAAa,MAAM,QAAQ,cAAc;AAS/C,UAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YA0Bf,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQZ,QAAI;AACF,YAAM,SAAS,MAAM,WAAW,KAAK,gBAAgB;AAAA,QACnD,SAAS;AAAA,MACX,CAAC;AAED,UAAI,OAAO,WAAW,UAAU;AAC9B,cAAM,SAAS,KAAK,MAAM,MAAM;AAChC,YAAI,CAAC,OAAO,IAAI;AACd,gBAAM,IAAI;AAAA,YACR,yBAAwB,YAAO,UAAP,YAAgB,eAAe;AAAA,YACvD;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,KAAc;AACrB,UAAI,eAAe,aAAc,OAAM;AACvC,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,UAAI,QAAQ,SAAS,WAAW,KAAK,QAAQ,SAAS,SAAS,GAAG;AAChE,cAAM,IAAI,aAAa,qDAAqD,OAAO,WAAW;AAAA,MAChG;AACA,YAAM,IAAI,aAAa,wBAAwB,OAAO,IAAI,OAAO,WAAW;AAAA,IAC9E;AAAA,EACF,UAAE;AACA,YAAQ,QAAQ;AAAA,EAClB;AAGA,SAAO,YAAY,MAAM,OAAO,oBAAoB;AACtD;AAkBA,eAAe,iBACb,MACA,OACA,sBACkC;AAjYpC;AAkYE,MAAI;AACJ,MAAI;AACF,KAAC,EAAE,WAAW,IAAI,MAAM,OAAO,oBAAoB;AAAA,EACrD,SAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,MAGA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,WAAW;AACjC,QAAM,KAAK,QAAQ,WAAW;AAE9B,MAAI;AAOF,UAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YA8Bf,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQZ,UAAM,SAAS,GAAG,SAAS,cAAc;AACzC,QAAI,OAAO,OAAO;AAChB,YAAM,WAAW,GAAG,KAAK,OAAO,KAAK;AACrC,aAAO,MAAM,QAAQ;AACrB,YAAM,IAAI;AAAA,QACR,wBAAwB,OAAO,aAAa,WAAW,WAAW,0BAA0B;AAAA,QAC5F;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAY,GAAG,KAAK,OAAO,KAAK;AACtC,WAAO,MAAM,QAAQ;AAErB,QAAI,OAAO,cAAc,UAAU;AACjC,YAAM,SAAS,KAAK,MAAM,SAAS;AACnC,UAAI,CAAC,OAAO,IAAI;AACd,cAAM,IAAI;AAAA,UACR,yBAAwB,YAAO,UAAP,YAAgB,eAAe;AAAA,UACvD;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAIA,WAAO,YAAY,MAAM,OAAO,oBAAoB;AAAA,EACtD,UAAE;AACA,OAAG,QAAQ;AAAA,EACb;AACF;","names":[]}
|
package/dist/maizzle-KKJF7XY7.js
DELETED
|
File without changes
|
|
File without changes
|