@emailens/engine 0.10.4 → 0.11.0
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/README.md +25 -25
- package/dist/{chunk-HBKZMR7V.js → chunk-UFSYNSDP.js} +1 -1
- package/dist/chunk-UFSYNSDP.js.map +1 -0
- package/dist/compile/index.cjs.map +1 -1
- package/dist/compile/index.d.cts +2 -2
- package/dist/compile/index.d.ts +2 -2
- package/dist/compile/index.js +2 -2
- package/dist/index.cjs +802 -170
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +96 -17
- package/dist/index.d.ts +96 -17
- package/dist/index.js +796 -170
- package/dist/index.js.map +1 -1
- package/dist/{react-email-DwBWB2kr.d.ts → react-email-BWIfwG7U.d.cts} +5 -5
- package/dist/{react-email-QKHRTEJW.js → react-email-CVZZNVZ2.js} +2 -2
- package/dist/{react-email-DTzVpGgB.d.cts → react-email-D24HkW2Z.d.ts} +5 -5
- package/dist/server.cjs +10 -10
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +4 -4
- package/dist/server.d.ts +4 -4
- package/dist/server.js +10 -10
- package/dist/server.js.map +1 -1
- package/dist/{types-BLR3-Fzo.d.cts → types-BFhPXh3c.d.cts} +25 -9
- package/dist/{types-BLR3-Fzo.d.ts → types-BFhPXh3c.d.ts} +25 -9
- package/package.json +1 -1
- package/dist/chunk-HBKZMR7V.js.map +0 -1
- /package/dist/{react-email-QKHRTEJW.js.map → react-email-CVZZNVZ2.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { E as EmailClient, F as Framework, T as TransformResult, C as CSSWarning, a as CodeFix, D as DiffResult, b as ExportPromptOptions, A as AiProvider, c as AiFixResult, S as SupportLevel, d as SpamAnalysisOptions, e as SpamReport, L as LinkReport, f as AccessibilityReport, I as ImageReport,
|
|
2
|
-
export {
|
|
3
|
-
|
|
1
|
+
import { E as EmailClient, F as Framework, T as TransformResult, C as CSSWarning, a as CodeFix, D as DiffResult, b as ExportPromptOptions, A as AiProvider, c as AiFixResult, S as SupportLevel, d as SpamAnalysisOptions, e as SpamReport, L as LinkReport, f as AccessibilityReport, g as AccessibilityIssue, I as ImageReport, h as InboxPreview, i as SizeReport, j as TemplateReport, O as OverflowReport, V as VisualReport, k as DesignReport, l as DeliverabilityReport } from './types-BFhPXh3c.cjs';
|
|
2
|
+
export { B as BaseIssue, m as ClientTruncation, n as DeliverabilityCheck, o as DeliverabilityIssue, p as DesignIssue, q as EstimateOptions, r as ExportScope, s as FixType, t as ImageInfo, u as ImageIssue, v as InboxPreviewIssue, w as InputFormat, x as LinkIssue, y as OverflowIssue, P as PreviewResult, z as Severity, G as SizeIssue, H as SourceLocation, J as SpamIssue, K as TemplateIssue, M as TokenEstimate, N as TokenEstimateWithWarnings, Q as VisualIssue, R as estimateAiFixTokens, U as generateFixPrompt, W as heuristicTokenCount } from './types-BFhPXh3c.cjs';
|
|
3
|
+
import * as cheerio from 'cheerio';
|
|
4
|
+
export { C as CompileError, a as CompileReactEmailOptions, S as SandboxStrategy } from './react-email-BWIfwG7U.cjs';
|
|
4
5
|
|
|
5
6
|
declare const EMAIL_CLIENTS: EmailClient[];
|
|
6
7
|
declare function getClient(id: string): EmailClient | undefined;
|
|
@@ -13,7 +14,7 @@ interface ParseOptions {
|
|
|
13
14
|
/**
|
|
14
15
|
* Record source positions so issues carry a `loc`. Costs a little parse time
|
|
15
16
|
* (parse5 tracks a location record per node and per attribute), so it is
|
|
16
|
-
* opt-in for callers that need to point at the source
|
|
17
|
+
* opt-in for callers that need to point at the source: editors, CI
|
|
17
18
|
* annotations, agents.
|
|
18
19
|
*/
|
|
19
20
|
positions?: boolean;
|
|
@@ -24,7 +25,7 @@ interface ParseOptions {
|
|
|
24
25
|
* for all target email clients.
|
|
25
26
|
*
|
|
26
27
|
* The `framework` parameter controls which fix snippets are attached
|
|
27
|
-
* to warnings
|
|
28
|
+
* to warnings; it does NOT change which warnings fire. Analysis always
|
|
28
29
|
* runs on compiled HTML (what email clients actually receive). Fix
|
|
29
30
|
* snippets reference source-level constructs so users know how to
|
|
30
31
|
* modify their framework source code.
|
|
@@ -128,7 +129,7 @@ interface GenerateAiFixOptions extends ExportPromptOptions {
|
|
|
128
129
|
* to build a structured prompt, then delegates to an LLM for context-aware
|
|
129
130
|
* structural fixes that static snippets cannot handle.
|
|
130
131
|
*
|
|
131
|
-
* The engine stays provider-agnostic
|
|
132
|
+
* The engine stays provider-agnostic: consumers pass their own `AiProvider`
|
|
132
133
|
* callback (Anthropic SDK, Vercel AI SDK, OpenRouter, etc.).
|
|
133
134
|
*
|
|
134
135
|
* @example
|
|
@@ -166,10 +167,10 @@ declare function generateAiFix(options: GenerateAiFixOptions): Promise<AiFixResu
|
|
|
166
167
|
* System prompt for the AI fix provider. Consumers should pass this as
|
|
167
168
|
* the `system` parameter to their LLM call for best results.
|
|
168
169
|
*/
|
|
169
|
-
declare const AI_FIX_SYSTEM_PROMPT = "You are an expert email developer specializing in cross-client HTML email compatibility. You fix emails to render correctly across all email clients.\n\nRules:\n- Return ONLY the fixed code inside a single code fence. No explanations before or after.\n- Preserve all existing content, text, links, and visual design.\n- For structural issues (fixType: \"structural\"), you MUST restructure the HTML
|
|
170
|
+
declare const AI_FIX_SYSTEM_PROMPT = "You are an expert email developer specializing in cross-client HTML email compatibility. You fix emails to render correctly across all email clients.\n\nRules:\n- Return ONLY the fixed code inside a single code fence. No explanations before or after.\n- Preserve all existing content, text, links, and visual design.\n- For structural issues (fixType: \"structural\"), you MUST restructure the HTML; CSS-only changes will not work.\n- Common structural patterns:\n - word-break/overflow-wrap unsupported \u2192 wrap text in <table><tr><td> with constrained width\n - display:flex/grid \u2192 convert to <table> layout (match the original column count and proportions)\n - border-radius in Outlook \u2192 use VML <v:roundrect> with <!--[if mso]> conditionals\n - background-image in Outlook \u2192 use VML <v:rect> with <v:fill>\n - max-width in Outlook \u2192 wrap in <!--[if mso]><table width=\"N\"> conditional\n - position:absolute \u2192 use <table> cells for layout\n - <svg> \u2192 replace with <img> pointing to a hosted PNG\n- For CSS-only issues (fixType: \"css\"), swap properties or add fallbacks.\n- For \"Layout & Visual Issues\", apply the provided Fix directly: add the background-color fallback beneath a gradient/image, append a web-safe font to the stack, and constrain fixed widths wider than the frame to width:100% with max-width.\n- Apply ALL fixes from the issues list: do not skip any.\n- Use the framework syntax specified (JSX/MJML/Maizzle/HTML).\n- For JSX: use camelCase style props, React Email components, and proper TypeScript types.\n- For MJML: use mj-* elements and attributes.\n- For Maizzle: use Tailwind CSS classes.";
|
|
170
171
|
|
|
171
172
|
/**
|
|
172
|
-
* CSS/HTML feature support matrix
|
|
173
|
+
* CSS/HTML feature support matrix, auto-generated from caniemail.com.
|
|
173
174
|
* Last synced: 2026-07-28
|
|
174
175
|
* caniemail last updated: 2026-07-20 09:56:37 +0000
|
|
175
176
|
*
|
|
@@ -186,11 +187,11 @@ declare const AI_FIX_SYSTEM_PROMPT = "You are an expert email developer speciali
|
|
|
186
187
|
* - hey-mail: caniemail.com (WebKit-based)
|
|
187
188
|
* - superhuman: Manual overrides (Chromium/Blink-based, best-effort estimates)
|
|
188
189
|
*
|
|
189
|
-
* DO NOT EDIT
|
|
190
|
+
* DO NOT EDIT; regenerate with: bun run sync:caniemail
|
|
190
191
|
*/
|
|
191
192
|
declare const CSS_SUPPORT: Record<string, Record<string, SupportLevel>>;
|
|
192
193
|
/**
|
|
193
|
-
* Caveat notes per (feature, client) from caniemail
|
|
194
|
+
* Caveat notes per (feature, client) from caniemail: the "why" behind a
|
|
194
195
|
* partial/buggy/unsupported rating. Sparse: only cells with a note appear.
|
|
195
196
|
*/
|
|
196
197
|
declare const CSS_SUPPORT_NOTES: Record<string, Record<string, string[]>>;
|
|
@@ -212,10 +213,10 @@ declare const CSS_FUNCTION_FEATURES: readonly ["calc", "clamp", "conic-gradient"
|
|
|
212
213
|
* caniemail's page for each feature, for a diagnostic's `codeDescription`.
|
|
213
214
|
*
|
|
214
215
|
* 250 of 255 features. The rest have no caniemail entry of
|
|
215
|
-
* their own and get no link, which is the honest outcome
|
|
216
|
+
* their own and get no link, which is the honest outcome: a link to a 404
|
|
216
217
|
* is worse than none.
|
|
217
218
|
*
|
|
218
|
-
* DO NOT EDIT
|
|
219
|
+
* DO NOT EDIT; regenerate with: bun run sync:feature-urls
|
|
219
220
|
*/
|
|
220
221
|
declare const FEATURE_URLS: Record<string, string>;
|
|
221
222
|
/** Where to read about a rule, when there is somewhere. */
|
|
@@ -239,7 +240,7 @@ declare const VALUE_CAVEAT_PROPS: ReadonlySet<string>;
|
|
|
239
240
|
* applies if either does.
|
|
240
241
|
*
|
|
241
242
|
* Returns true (report it) for a property that isn't value-gated, and for one
|
|
242
|
-
* where we never saw a value
|
|
243
|
+
* where we never saw a value: an at-rule, a pseudo-class, a detected CSS
|
|
243
244
|
* function.
|
|
244
245
|
*/
|
|
245
246
|
declare function caveatApplies(prop: string, values: readonly string[] | undefined, notes: string[] | undefined): boolean;
|
|
@@ -267,6 +268,20 @@ declare function analyzeSpam(html: string, options?: SpamAnalysisOptions): SpamR
|
|
|
267
268
|
*/
|
|
268
269
|
declare function validateLinks(html: string, options?: ParseOptions): LinkReport;
|
|
269
270
|
|
|
271
|
+
/**
|
|
272
|
+
* The render a cascade is being resolved for.
|
|
273
|
+
*
|
|
274
|
+
* An email has more than one correct answer: the same CSS produces a different
|
|
275
|
+
* palette on a phone and in dark mode, and a contrast bug can live in only one
|
|
276
|
+
* of them. Resolving against an explicit context is what lets the same
|
|
277
|
+
* machinery grade all three.
|
|
278
|
+
*/
|
|
279
|
+
interface RenderContext {
|
|
280
|
+
/** Viewport width in px, for width media queries. */
|
|
281
|
+
width: number;
|
|
282
|
+
/** Whether `prefers-color-scheme: dark` matches. */
|
|
283
|
+
dark: boolean;
|
|
284
|
+
}
|
|
270
285
|
/**
|
|
271
286
|
* Audit an HTML email for accessibility issues.
|
|
272
287
|
*
|
|
@@ -275,6 +290,43 @@ declare function validateLinks(html: string, options?: ParseOptions): LinkReport
|
|
|
275
290
|
* color contrast. Returns a 0–100 score and detailed issues.
|
|
276
291
|
*/
|
|
277
292
|
declare function checkAccessibility(html: string, options?: ParseOptions): AccessibilityReport;
|
|
293
|
+
/**
|
|
294
|
+
* Contrast failures inside the email's own `@media (prefers-color-scheme: dark)`
|
|
295
|
+
* styles.
|
|
296
|
+
*
|
|
297
|
+
* This is the other half of dark mode, and the half the author actually
|
|
298
|
+
* controls: Apple Mail, Superhuman, Thunderbird and friends do not invert
|
|
299
|
+
* anything, they just apply the dark block as written. A dark background
|
|
300
|
+
* paired with body text that was never re-coloured is invisible there, and no
|
|
301
|
+
* amount of inversion analysis finds it; the bug is in the CSS, not in what
|
|
302
|
+
* the client does to it.
|
|
303
|
+
*
|
|
304
|
+
* Free to run: same DOM, resolved against a dark render, so positions stay
|
|
305
|
+
* valid. Emails with no dark block resolve identically to the light pass and
|
|
306
|
+
* report nothing.
|
|
307
|
+
*/
|
|
308
|
+
declare function checkDarkStylesContrastFromDom($: cheerio.CheerioAPI, lightIssues?: AccessibilityIssue[]): AccessibilityIssue[];
|
|
309
|
+
/**
|
|
310
|
+
* Contrast failures that only appear at mobile width. See
|
|
311
|
+
* {@link checkMobileContrastFromDom}.
|
|
312
|
+
*/
|
|
313
|
+
declare function checkMobileContrast(html: string, options?: ParseOptions): AccessibilityIssue[];
|
|
314
|
+
/**
|
|
315
|
+
* Contrast failures an email has *only* in dark mode.
|
|
316
|
+
*
|
|
317
|
+
* Clients that invert colours do it selectively, so a palette that passes in
|
|
318
|
+
* light mode can collapse to unreadable once inverted, mid-tone text left
|
|
319
|
+
* alone on a background repainted near-black. This runs the ordinary contrast
|
|
320
|
+
* check over the simulated dark render and reports what is new there.
|
|
321
|
+
*
|
|
322
|
+
* Pass `lightIssues` when the light-mode report is already in hand (the audit
|
|
323
|
+
* has it) to skip re-running the light pass.
|
|
324
|
+
*
|
|
325
|
+
* ponytail: deduped by the element description, so two genuinely identical
|
|
326
|
+
* elements collapse into one report. Track them individually only if the
|
|
327
|
+
* per-element count turns out to matter.
|
|
328
|
+
*/
|
|
329
|
+
declare function checkDarkModeContrast(html: string, lightIssues?: AccessibilityIssue[]): AccessibilityIssue[];
|
|
278
330
|
|
|
279
331
|
/**
|
|
280
332
|
* Analyze images in an HTML email for best practices.
|
|
@@ -327,12 +379,18 @@ declare function checkOverflow(html: string, options?: ParseOptions): OverflowRe
|
|
|
327
379
|
*/
|
|
328
380
|
declare function checkVisual(html: string, options?: ParseOptions): VisualReport;
|
|
329
381
|
|
|
382
|
+
/**
|
|
383
|
+
* Report design drift in an HTML email: near-identical colours, and properties
|
|
384
|
+
* carrying more distinct values than a design system would.
|
|
385
|
+
*/
|
|
386
|
+
declare function checkDesignConsistency(html: string, options?: ParseOptions): DesignReport;
|
|
387
|
+
|
|
330
388
|
interface AuditOptions extends ParseOptions {
|
|
331
389
|
framework?: Framework;
|
|
332
390
|
/** Options for spam analysis */
|
|
333
391
|
spam?: SpamAnalysisOptions;
|
|
334
392
|
/** Skip specific checks */
|
|
335
|
-
skip?: Array<"spam" | "links" | "accessibility" | "images" | "compatibility" | "inboxPreview" | "size" | "templateVariables" | "overflow" | "visual">;
|
|
393
|
+
skip?: Array<"spam" | "links" | "accessibility" | "images" | "compatibility" | "inboxPreview" | "size" | "templateVariables" | "overflow" | "visual" | "darkContrast" | "mobileContrast" | "design">;
|
|
336
394
|
}
|
|
337
395
|
interface AuditReport {
|
|
338
396
|
compatibility: {
|
|
@@ -353,6 +411,12 @@ interface AuditReport {
|
|
|
353
411
|
templateVariables: TemplateReport;
|
|
354
412
|
overflow: OverflowReport;
|
|
355
413
|
visual: VisualReport;
|
|
414
|
+
/** Contrast failures present only once a client inverts colours. */
|
|
415
|
+
darkContrast: AccessibilityIssue[];
|
|
416
|
+
/** Contrast failures present only below the email's mobile breakpoint. */
|
|
417
|
+
mobileContrast: AccessibilityIssue[];
|
|
418
|
+
/** Design drift: near-identical colours, and properties with no system left. */
|
|
419
|
+
design: DesignReport;
|
|
356
420
|
}
|
|
357
421
|
/**
|
|
358
422
|
* Run all email analysis checks in a single call.
|
|
@@ -453,7 +517,7 @@ interface EmailSession {
|
|
|
453
517
|
* Simulate dark mode for a specific client.
|
|
454
518
|
*
|
|
455
519
|
* Creates an isolated DOM copy per call (simulation mutates the DOM).
|
|
456
|
-
* Operates on the **original** HTML
|
|
520
|
+
* Operates on the **original** HTML, if you need dark mode on
|
|
457
521
|
* already-transformed HTML, use the standalone `simulateDarkMode()` instead.
|
|
458
522
|
*/
|
|
459
523
|
simulateDarkMode(clientId: string): {
|
|
@@ -466,7 +530,7 @@ interface EmailSession {
|
|
|
466
530
|
* DOM across all read-only analysis operations.
|
|
467
531
|
*
|
|
468
532
|
* Use this when you need to call multiple analysis functions on the
|
|
469
|
-
* same HTML
|
|
533
|
+
* same HTML: it eliminates redundant `cheerio.load()` calls.
|
|
470
534
|
*
|
|
471
535
|
* @example
|
|
472
536
|
* ```typescript
|
|
@@ -548,6 +612,21 @@ declare function wcagGrade(ratio: number): WcagGrade;
|
|
|
548
612
|
* Returns the flattened [r, g, b] as 0-255 values.
|
|
549
613
|
*/
|
|
550
614
|
declare function alphaBlend(fg: RGBA, bgR: number, bgG: number, bgB: number): [number, number, number];
|
|
615
|
+
/**
|
|
616
|
+
* Convert sRGB to OKLab.
|
|
617
|
+
*
|
|
618
|
+
* OKLab is built so that straight-line distance between two points matches how
|
|
619
|
+
* different the colours look, which sRGB emphatically does not: `#333` and
|
|
620
|
+
* `#343434` are far apart in RGB terms and identical to a reader.
|
|
621
|
+
*/
|
|
622
|
+
declare function rgbToOklab(rgba: RGBA): [number, number, number];
|
|
623
|
+
/**
|
|
624
|
+
* Perceptual distance between two colours, as OKLab delta-E.
|
|
625
|
+
*
|
|
626
|
+
* Roughly: under ~0.02 the two are the same colour to a reader, and around
|
|
627
|
+
* ~0.1 they are clearly different.
|
|
628
|
+
*/
|
|
629
|
+
declare function colorDistance(a: RGBA, b: RGBA): number;
|
|
551
630
|
|
|
552
631
|
/**
|
|
553
632
|
* Downlevel modern CSS in HTML emails to maximize email client compatibility.
|
|
@@ -575,4 +654,4 @@ declare function alphaBlend(fg: RGBA, bgR: number, bgG: number, bgB: number): [n
|
|
|
575
654
|
*/
|
|
576
655
|
declare function downlevelCSS(html: string): string;
|
|
577
656
|
|
|
578
|
-
export { AI_FIX_SYSTEM_PROMPT, AT_RULE_FEATURES, AccessibilityReport, AiFixResult, AiProvider, type AuditOptions, type AuditReport, COMPOUND_VALUE_FEATURES, CSSWarning, CSS_FUNCTION_FEATURES, CSS_SUPPORT, CSS_SUPPORT_NOTES, CodeFix, type CreateSessionOptions, DeliverabilityReport, DiffResult, EMAIL_CLIENTS, EMPTY_DELIVERABILITY, EmailClient, type EmailSession, ExportPromptOptions, FEATURE_URLS, Framework, GENERIC_LINK_TEXT, type GenerateAiFixOptions, HTML_ELEMENT_FEATURES, ImageReport, InboxPreview, LinkReport, MAX_HTML_SIZE, MAX_WARNING_LOCATIONS, OverflowReport, type ParseOptions, type RGBA, STRUCTURAL_FIX_PROPERTIES, SizeReport, SpamAnalysisOptions, SpamReport, SupportLevel, TemplateReport, TransformResult, VALUE_CAVEAT_PROPS, VisualReport, type WcagGrade, alphaBlend, analyzeEmail, analyzeImages, analyzeSpam, auditEmail, caveatApplies, checkAccessibility, checkOverflow, checkSize, checkTemplateVariables, checkVisual, contrastRatio, createSession, diffResults, downlevelCSS, errorWarnings, extractInboxPreview, featureUrl, formatRgb, generateAiFix, generateCompatibilityScore, getClient, getCodeFix, getSuggestion, parseColor, relativeLuminance, simulateDarkMode, structuralWarnings, toPlainText, transformForAllClients, transformForClient, validateLinks, warningsForClient, wcagGrade };
|
|
657
|
+
export { AI_FIX_SYSTEM_PROMPT, AT_RULE_FEATURES, AccessibilityIssue, AccessibilityReport, AiFixResult, AiProvider, type AuditOptions, type AuditReport, COMPOUND_VALUE_FEATURES, CSSWarning, CSS_FUNCTION_FEATURES, CSS_SUPPORT, CSS_SUPPORT_NOTES, CodeFix, type CreateSessionOptions, DeliverabilityReport, DesignReport, DiffResult, EMAIL_CLIENTS, EMPTY_DELIVERABILITY, EmailClient, type EmailSession, ExportPromptOptions, FEATURE_URLS, Framework, GENERIC_LINK_TEXT, type GenerateAiFixOptions, HTML_ELEMENT_FEATURES, ImageReport, InboxPreview, LinkReport, MAX_HTML_SIZE, MAX_WARNING_LOCATIONS, OverflowReport, type ParseOptions, type RGBA, type RenderContext, STRUCTURAL_FIX_PROPERTIES, SizeReport, SpamAnalysisOptions, SpamReport, SupportLevel, TemplateReport, TransformResult, VALUE_CAVEAT_PROPS, VisualReport, type WcagGrade, alphaBlend, analyzeEmail, analyzeImages, analyzeSpam, auditEmail, caveatApplies, checkAccessibility, checkDarkModeContrast, checkDarkStylesContrastFromDom, checkDesignConsistency, checkMobileContrast, checkOverflow, checkSize, checkTemplateVariables, checkVisual, colorDistance, contrastRatio, createSession, diffResults, downlevelCSS, errorWarnings, extractInboxPreview, featureUrl, formatRgb, generateAiFix, generateCompatibilityScore, getClient, getCodeFix, getSuggestion, parseColor, relativeLuminance, rgbToOklab, simulateDarkMode, structuralWarnings, toPlainText, transformForAllClients, transformForClient, validateLinks, warningsForClient, wcagGrade };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { E as EmailClient, F as Framework, T as TransformResult, C as CSSWarning, a as CodeFix, D as DiffResult, b as ExportPromptOptions, A as AiProvider, c as AiFixResult, S as SupportLevel, d as SpamAnalysisOptions, e as SpamReport, L as LinkReport, f as AccessibilityReport, I as ImageReport,
|
|
2
|
-
export {
|
|
3
|
-
|
|
1
|
+
import { E as EmailClient, F as Framework, T as TransformResult, C as CSSWarning, a as CodeFix, D as DiffResult, b as ExportPromptOptions, A as AiProvider, c as AiFixResult, S as SupportLevel, d as SpamAnalysisOptions, e as SpamReport, L as LinkReport, f as AccessibilityReport, g as AccessibilityIssue, I as ImageReport, h as InboxPreview, i as SizeReport, j as TemplateReport, O as OverflowReport, V as VisualReport, k as DesignReport, l as DeliverabilityReport } from './types-BFhPXh3c.js';
|
|
2
|
+
export { B as BaseIssue, m as ClientTruncation, n as DeliverabilityCheck, o as DeliverabilityIssue, p as DesignIssue, q as EstimateOptions, r as ExportScope, s as FixType, t as ImageInfo, u as ImageIssue, v as InboxPreviewIssue, w as InputFormat, x as LinkIssue, y as OverflowIssue, P as PreviewResult, z as Severity, G as SizeIssue, H as SourceLocation, J as SpamIssue, K as TemplateIssue, M as TokenEstimate, N as TokenEstimateWithWarnings, Q as VisualIssue, R as estimateAiFixTokens, U as generateFixPrompt, W as heuristicTokenCount } from './types-BFhPXh3c.js';
|
|
3
|
+
import * as cheerio from 'cheerio';
|
|
4
|
+
export { C as CompileError, a as CompileReactEmailOptions, S as SandboxStrategy } from './react-email-D24HkW2Z.js';
|
|
4
5
|
|
|
5
6
|
declare const EMAIL_CLIENTS: EmailClient[];
|
|
6
7
|
declare function getClient(id: string): EmailClient | undefined;
|
|
@@ -13,7 +14,7 @@ interface ParseOptions {
|
|
|
13
14
|
/**
|
|
14
15
|
* Record source positions so issues carry a `loc`. Costs a little parse time
|
|
15
16
|
* (parse5 tracks a location record per node and per attribute), so it is
|
|
16
|
-
* opt-in for callers that need to point at the source
|
|
17
|
+
* opt-in for callers that need to point at the source: editors, CI
|
|
17
18
|
* annotations, agents.
|
|
18
19
|
*/
|
|
19
20
|
positions?: boolean;
|
|
@@ -24,7 +25,7 @@ interface ParseOptions {
|
|
|
24
25
|
* for all target email clients.
|
|
25
26
|
*
|
|
26
27
|
* The `framework` parameter controls which fix snippets are attached
|
|
27
|
-
* to warnings
|
|
28
|
+
* to warnings; it does NOT change which warnings fire. Analysis always
|
|
28
29
|
* runs on compiled HTML (what email clients actually receive). Fix
|
|
29
30
|
* snippets reference source-level constructs so users know how to
|
|
30
31
|
* modify their framework source code.
|
|
@@ -128,7 +129,7 @@ interface GenerateAiFixOptions extends ExportPromptOptions {
|
|
|
128
129
|
* to build a structured prompt, then delegates to an LLM for context-aware
|
|
129
130
|
* structural fixes that static snippets cannot handle.
|
|
130
131
|
*
|
|
131
|
-
* The engine stays provider-agnostic
|
|
132
|
+
* The engine stays provider-agnostic: consumers pass their own `AiProvider`
|
|
132
133
|
* callback (Anthropic SDK, Vercel AI SDK, OpenRouter, etc.).
|
|
133
134
|
*
|
|
134
135
|
* @example
|
|
@@ -166,10 +167,10 @@ declare function generateAiFix(options: GenerateAiFixOptions): Promise<AiFixResu
|
|
|
166
167
|
* System prompt for the AI fix provider. Consumers should pass this as
|
|
167
168
|
* the `system` parameter to their LLM call for best results.
|
|
168
169
|
*/
|
|
169
|
-
declare const AI_FIX_SYSTEM_PROMPT = "You are an expert email developer specializing in cross-client HTML email compatibility. You fix emails to render correctly across all email clients.\n\nRules:\n- Return ONLY the fixed code inside a single code fence. No explanations before or after.\n- Preserve all existing content, text, links, and visual design.\n- For structural issues (fixType: \"structural\"), you MUST restructure the HTML
|
|
170
|
+
declare const AI_FIX_SYSTEM_PROMPT = "You are an expert email developer specializing in cross-client HTML email compatibility. You fix emails to render correctly across all email clients.\n\nRules:\n- Return ONLY the fixed code inside a single code fence. No explanations before or after.\n- Preserve all existing content, text, links, and visual design.\n- For structural issues (fixType: \"structural\"), you MUST restructure the HTML; CSS-only changes will not work.\n- Common structural patterns:\n - word-break/overflow-wrap unsupported \u2192 wrap text in <table><tr><td> with constrained width\n - display:flex/grid \u2192 convert to <table> layout (match the original column count and proportions)\n - border-radius in Outlook \u2192 use VML <v:roundrect> with <!--[if mso]> conditionals\n - background-image in Outlook \u2192 use VML <v:rect> with <v:fill>\n - max-width in Outlook \u2192 wrap in <!--[if mso]><table width=\"N\"> conditional\n - position:absolute \u2192 use <table> cells for layout\n - <svg> \u2192 replace with <img> pointing to a hosted PNG\n- For CSS-only issues (fixType: \"css\"), swap properties or add fallbacks.\n- For \"Layout & Visual Issues\", apply the provided Fix directly: add the background-color fallback beneath a gradient/image, append a web-safe font to the stack, and constrain fixed widths wider than the frame to width:100% with max-width.\n- Apply ALL fixes from the issues list: do not skip any.\n- Use the framework syntax specified (JSX/MJML/Maizzle/HTML).\n- For JSX: use camelCase style props, React Email components, and proper TypeScript types.\n- For MJML: use mj-* elements and attributes.\n- For Maizzle: use Tailwind CSS classes.";
|
|
170
171
|
|
|
171
172
|
/**
|
|
172
|
-
* CSS/HTML feature support matrix
|
|
173
|
+
* CSS/HTML feature support matrix, auto-generated from caniemail.com.
|
|
173
174
|
* Last synced: 2026-07-28
|
|
174
175
|
* caniemail last updated: 2026-07-20 09:56:37 +0000
|
|
175
176
|
*
|
|
@@ -186,11 +187,11 @@ declare const AI_FIX_SYSTEM_PROMPT = "You are an expert email developer speciali
|
|
|
186
187
|
* - hey-mail: caniemail.com (WebKit-based)
|
|
187
188
|
* - superhuman: Manual overrides (Chromium/Blink-based, best-effort estimates)
|
|
188
189
|
*
|
|
189
|
-
* DO NOT EDIT
|
|
190
|
+
* DO NOT EDIT; regenerate with: bun run sync:caniemail
|
|
190
191
|
*/
|
|
191
192
|
declare const CSS_SUPPORT: Record<string, Record<string, SupportLevel>>;
|
|
192
193
|
/**
|
|
193
|
-
* Caveat notes per (feature, client) from caniemail
|
|
194
|
+
* Caveat notes per (feature, client) from caniemail: the "why" behind a
|
|
194
195
|
* partial/buggy/unsupported rating. Sparse: only cells with a note appear.
|
|
195
196
|
*/
|
|
196
197
|
declare const CSS_SUPPORT_NOTES: Record<string, Record<string, string[]>>;
|
|
@@ -212,10 +213,10 @@ declare const CSS_FUNCTION_FEATURES: readonly ["calc", "clamp", "conic-gradient"
|
|
|
212
213
|
* caniemail's page for each feature, for a diagnostic's `codeDescription`.
|
|
213
214
|
*
|
|
214
215
|
* 250 of 255 features. The rest have no caniemail entry of
|
|
215
|
-
* their own and get no link, which is the honest outcome
|
|
216
|
+
* their own and get no link, which is the honest outcome: a link to a 404
|
|
216
217
|
* is worse than none.
|
|
217
218
|
*
|
|
218
|
-
* DO NOT EDIT
|
|
219
|
+
* DO NOT EDIT; regenerate with: bun run sync:feature-urls
|
|
219
220
|
*/
|
|
220
221
|
declare const FEATURE_URLS: Record<string, string>;
|
|
221
222
|
/** Where to read about a rule, when there is somewhere. */
|
|
@@ -239,7 +240,7 @@ declare const VALUE_CAVEAT_PROPS: ReadonlySet<string>;
|
|
|
239
240
|
* applies if either does.
|
|
240
241
|
*
|
|
241
242
|
* Returns true (report it) for a property that isn't value-gated, and for one
|
|
242
|
-
* where we never saw a value
|
|
243
|
+
* where we never saw a value: an at-rule, a pseudo-class, a detected CSS
|
|
243
244
|
* function.
|
|
244
245
|
*/
|
|
245
246
|
declare function caveatApplies(prop: string, values: readonly string[] | undefined, notes: string[] | undefined): boolean;
|
|
@@ -267,6 +268,20 @@ declare function analyzeSpam(html: string, options?: SpamAnalysisOptions): SpamR
|
|
|
267
268
|
*/
|
|
268
269
|
declare function validateLinks(html: string, options?: ParseOptions): LinkReport;
|
|
269
270
|
|
|
271
|
+
/**
|
|
272
|
+
* The render a cascade is being resolved for.
|
|
273
|
+
*
|
|
274
|
+
* An email has more than one correct answer: the same CSS produces a different
|
|
275
|
+
* palette on a phone and in dark mode, and a contrast bug can live in only one
|
|
276
|
+
* of them. Resolving against an explicit context is what lets the same
|
|
277
|
+
* machinery grade all three.
|
|
278
|
+
*/
|
|
279
|
+
interface RenderContext {
|
|
280
|
+
/** Viewport width in px, for width media queries. */
|
|
281
|
+
width: number;
|
|
282
|
+
/** Whether `prefers-color-scheme: dark` matches. */
|
|
283
|
+
dark: boolean;
|
|
284
|
+
}
|
|
270
285
|
/**
|
|
271
286
|
* Audit an HTML email for accessibility issues.
|
|
272
287
|
*
|
|
@@ -275,6 +290,43 @@ declare function validateLinks(html: string, options?: ParseOptions): LinkReport
|
|
|
275
290
|
* color contrast. Returns a 0–100 score and detailed issues.
|
|
276
291
|
*/
|
|
277
292
|
declare function checkAccessibility(html: string, options?: ParseOptions): AccessibilityReport;
|
|
293
|
+
/**
|
|
294
|
+
* Contrast failures inside the email's own `@media (prefers-color-scheme: dark)`
|
|
295
|
+
* styles.
|
|
296
|
+
*
|
|
297
|
+
* This is the other half of dark mode, and the half the author actually
|
|
298
|
+
* controls: Apple Mail, Superhuman, Thunderbird and friends do not invert
|
|
299
|
+
* anything, they just apply the dark block as written. A dark background
|
|
300
|
+
* paired with body text that was never re-coloured is invisible there, and no
|
|
301
|
+
* amount of inversion analysis finds it; the bug is in the CSS, not in what
|
|
302
|
+
* the client does to it.
|
|
303
|
+
*
|
|
304
|
+
* Free to run: same DOM, resolved against a dark render, so positions stay
|
|
305
|
+
* valid. Emails with no dark block resolve identically to the light pass and
|
|
306
|
+
* report nothing.
|
|
307
|
+
*/
|
|
308
|
+
declare function checkDarkStylesContrastFromDom($: cheerio.CheerioAPI, lightIssues?: AccessibilityIssue[]): AccessibilityIssue[];
|
|
309
|
+
/**
|
|
310
|
+
* Contrast failures that only appear at mobile width. See
|
|
311
|
+
* {@link checkMobileContrastFromDom}.
|
|
312
|
+
*/
|
|
313
|
+
declare function checkMobileContrast(html: string, options?: ParseOptions): AccessibilityIssue[];
|
|
314
|
+
/**
|
|
315
|
+
* Contrast failures an email has *only* in dark mode.
|
|
316
|
+
*
|
|
317
|
+
* Clients that invert colours do it selectively, so a palette that passes in
|
|
318
|
+
* light mode can collapse to unreadable once inverted, mid-tone text left
|
|
319
|
+
* alone on a background repainted near-black. This runs the ordinary contrast
|
|
320
|
+
* check over the simulated dark render and reports what is new there.
|
|
321
|
+
*
|
|
322
|
+
* Pass `lightIssues` when the light-mode report is already in hand (the audit
|
|
323
|
+
* has it) to skip re-running the light pass.
|
|
324
|
+
*
|
|
325
|
+
* ponytail: deduped by the element description, so two genuinely identical
|
|
326
|
+
* elements collapse into one report. Track them individually only if the
|
|
327
|
+
* per-element count turns out to matter.
|
|
328
|
+
*/
|
|
329
|
+
declare function checkDarkModeContrast(html: string, lightIssues?: AccessibilityIssue[]): AccessibilityIssue[];
|
|
278
330
|
|
|
279
331
|
/**
|
|
280
332
|
* Analyze images in an HTML email for best practices.
|
|
@@ -327,12 +379,18 @@ declare function checkOverflow(html: string, options?: ParseOptions): OverflowRe
|
|
|
327
379
|
*/
|
|
328
380
|
declare function checkVisual(html: string, options?: ParseOptions): VisualReport;
|
|
329
381
|
|
|
382
|
+
/**
|
|
383
|
+
* Report design drift in an HTML email: near-identical colours, and properties
|
|
384
|
+
* carrying more distinct values than a design system would.
|
|
385
|
+
*/
|
|
386
|
+
declare function checkDesignConsistency(html: string, options?: ParseOptions): DesignReport;
|
|
387
|
+
|
|
330
388
|
interface AuditOptions extends ParseOptions {
|
|
331
389
|
framework?: Framework;
|
|
332
390
|
/** Options for spam analysis */
|
|
333
391
|
spam?: SpamAnalysisOptions;
|
|
334
392
|
/** Skip specific checks */
|
|
335
|
-
skip?: Array<"spam" | "links" | "accessibility" | "images" | "compatibility" | "inboxPreview" | "size" | "templateVariables" | "overflow" | "visual">;
|
|
393
|
+
skip?: Array<"spam" | "links" | "accessibility" | "images" | "compatibility" | "inboxPreview" | "size" | "templateVariables" | "overflow" | "visual" | "darkContrast" | "mobileContrast" | "design">;
|
|
336
394
|
}
|
|
337
395
|
interface AuditReport {
|
|
338
396
|
compatibility: {
|
|
@@ -353,6 +411,12 @@ interface AuditReport {
|
|
|
353
411
|
templateVariables: TemplateReport;
|
|
354
412
|
overflow: OverflowReport;
|
|
355
413
|
visual: VisualReport;
|
|
414
|
+
/** Contrast failures present only once a client inverts colours. */
|
|
415
|
+
darkContrast: AccessibilityIssue[];
|
|
416
|
+
/** Contrast failures present only below the email's mobile breakpoint. */
|
|
417
|
+
mobileContrast: AccessibilityIssue[];
|
|
418
|
+
/** Design drift: near-identical colours, and properties with no system left. */
|
|
419
|
+
design: DesignReport;
|
|
356
420
|
}
|
|
357
421
|
/**
|
|
358
422
|
* Run all email analysis checks in a single call.
|
|
@@ -453,7 +517,7 @@ interface EmailSession {
|
|
|
453
517
|
* Simulate dark mode for a specific client.
|
|
454
518
|
*
|
|
455
519
|
* Creates an isolated DOM copy per call (simulation mutates the DOM).
|
|
456
|
-
* Operates on the **original** HTML
|
|
520
|
+
* Operates on the **original** HTML, if you need dark mode on
|
|
457
521
|
* already-transformed HTML, use the standalone `simulateDarkMode()` instead.
|
|
458
522
|
*/
|
|
459
523
|
simulateDarkMode(clientId: string): {
|
|
@@ -466,7 +530,7 @@ interface EmailSession {
|
|
|
466
530
|
* DOM across all read-only analysis operations.
|
|
467
531
|
*
|
|
468
532
|
* Use this when you need to call multiple analysis functions on the
|
|
469
|
-
* same HTML
|
|
533
|
+
* same HTML: it eliminates redundant `cheerio.load()` calls.
|
|
470
534
|
*
|
|
471
535
|
* @example
|
|
472
536
|
* ```typescript
|
|
@@ -548,6 +612,21 @@ declare function wcagGrade(ratio: number): WcagGrade;
|
|
|
548
612
|
* Returns the flattened [r, g, b] as 0-255 values.
|
|
549
613
|
*/
|
|
550
614
|
declare function alphaBlend(fg: RGBA, bgR: number, bgG: number, bgB: number): [number, number, number];
|
|
615
|
+
/**
|
|
616
|
+
* Convert sRGB to OKLab.
|
|
617
|
+
*
|
|
618
|
+
* OKLab is built so that straight-line distance between two points matches how
|
|
619
|
+
* different the colours look, which sRGB emphatically does not: `#333` and
|
|
620
|
+
* `#343434` are far apart in RGB terms and identical to a reader.
|
|
621
|
+
*/
|
|
622
|
+
declare function rgbToOklab(rgba: RGBA): [number, number, number];
|
|
623
|
+
/**
|
|
624
|
+
* Perceptual distance between two colours, as OKLab delta-E.
|
|
625
|
+
*
|
|
626
|
+
* Roughly: under ~0.02 the two are the same colour to a reader, and around
|
|
627
|
+
* ~0.1 they are clearly different.
|
|
628
|
+
*/
|
|
629
|
+
declare function colorDistance(a: RGBA, b: RGBA): number;
|
|
551
630
|
|
|
552
631
|
/**
|
|
553
632
|
* Downlevel modern CSS in HTML emails to maximize email client compatibility.
|
|
@@ -575,4 +654,4 @@ declare function alphaBlend(fg: RGBA, bgR: number, bgG: number, bgB: number): [n
|
|
|
575
654
|
*/
|
|
576
655
|
declare function downlevelCSS(html: string): string;
|
|
577
656
|
|
|
578
|
-
export { AI_FIX_SYSTEM_PROMPT, AT_RULE_FEATURES, AccessibilityReport, AiFixResult, AiProvider, type AuditOptions, type AuditReport, COMPOUND_VALUE_FEATURES, CSSWarning, CSS_FUNCTION_FEATURES, CSS_SUPPORT, CSS_SUPPORT_NOTES, CodeFix, type CreateSessionOptions, DeliverabilityReport, DiffResult, EMAIL_CLIENTS, EMPTY_DELIVERABILITY, EmailClient, type EmailSession, ExportPromptOptions, FEATURE_URLS, Framework, GENERIC_LINK_TEXT, type GenerateAiFixOptions, HTML_ELEMENT_FEATURES, ImageReport, InboxPreview, LinkReport, MAX_HTML_SIZE, MAX_WARNING_LOCATIONS, OverflowReport, type ParseOptions, type RGBA, STRUCTURAL_FIX_PROPERTIES, SizeReport, SpamAnalysisOptions, SpamReport, SupportLevel, TemplateReport, TransformResult, VALUE_CAVEAT_PROPS, VisualReport, type WcagGrade, alphaBlend, analyzeEmail, analyzeImages, analyzeSpam, auditEmail, caveatApplies, checkAccessibility, checkOverflow, checkSize, checkTemplateVariables, checkVisual, contrastRatio, createSession, diffResults, downlevelCSS, errorWarnings, extractInboxPreview, featureUrl, formatRgb, generateAiFix, generateCompatibilityScore, getClient, getCodeFix, getSuggestion, parseColor, relativeLuminance, simulateDarkMode, structuralWarnings, toPlainText, transformForAllClients, transformForClient, validateLinks, warningsForClient, wcagGrade };
|
|
657
|
+
export { AI_FIX_SYSTEM_PROMPT, AT_RULE_FEATURES, AccessibilityIssue, AccessibilityReport, AiFixResult, AiProvider, type AuditOptions, type AuditReport, COMPOUND_VALUE_FEATURES, CSSWarning, CSS_FUNCTION_FEATURES, CSS_SUPPORT, CSS_SUPPORT_NOTES, CodeFix, type CreateSessionOptions, DeliverabilityReport, DesignReport, DiffResult, EMAIL_CLIENTS, EMPTY_DELIVERABILITY, EmailClient, type EmailSession, ExportPromptOptions, FEATURE_URLS, Framework, GENERIC_LINK_TEXT, type GenerateAiFixOptions, HTML_ELEMENT_FEATURES, ImageReport, InboxPreview, LinkReport, MAX_HTML_SIZE, MAX_WARNING_LOCATIONS, OverflowReport, type ParseOptions, type RGBA, type RenderContext, STRUCTURAL_FIX_PROPERTIES, SizeReport, SpamAnalysisOptions, SpamReport, SupportLevel, TemplateReport, TransformResult, VALUE_CAVEAT_PROPS, VisualReport, type WcagGrade, alphaBlend, analyzeEmail, analyzeImages, analyzeSpam, auditEmail, caveatApplies, checkAccessibility, checkDarkModeContrast, checkDarkStylesContrastFromDom, checkDesignConsistency, checkMobileContrast, checkOverflow, checkSize, checkTemplateVariables, checkVisual, colorDistance, contrastRatio, createSession, diffResults, downlevelCSS, errorWarnings, extractInboxPreview, featureUrl, formatRgb, generateAiFix, generateCompatibilityScore, getClient, getCodeFix, getSuggestion, parseColor, relativeLuminance, rgbToOklab, simulateDarkMode, structuralWarnings, toPlainText, transformForAllClients, transformForClient, validateLinks, warningsForClient, wcagGrade };
|