@emailens/engine 0.10.4 → 0.11.1
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 +1003 -179
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +116 -17
- package/dist/index.d.ts +116 -17
- package/dist/index.js +996 -179
- package/dist/index.js.map +1 -1
- package/dist/{react-email-DwBWB2kr.d.ts → react-email-BROBcC8u.d.ts} +5 -5
- package/dist/{react-email-QKHRTEJW.js → react-email-CVZZNVZ2.js} +2 -2
- package/dist/{react-email-DTzVpGgB.d.cts → react-email-DuZAgJtw.d.cts} +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-bvGDId6f.d.cts} +33 -9
- package/dist/{types-BLR3-Fzo.d.ts → types-bvGDId6f.d.ts} +33 -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 VmlReport, k as VisualReport, l as DesignReport, m as DeliverabilityReport } from './types-bvGDId6f.cjs';
|
|
2
|
+
export { B as BaseIssue, n as ClientTruncation, o as DeliverabilityCheck, p as DeliverabilityIssue, q as DesignIssue, r as EstimateOptions, s as ExportScope, t as FixType, u as ImageInfo, v as ImageIssue, w as InboxPreviewIssue, x as InputFormat, y as LinkIssue, z as OverflowIssue, P as PreviewResult, G as Severity, H as SizeIssue, J as SourceLocation, K as SpamIssue, M as TemplateIssue, N as TokenEstimate, Q as TokenEstimateWithWarnings, R as VisualIssue, U as VmlIssue, W as estimateAiFixTokens, X as generateFixPrompt, Y as heuristicTokenCount } from './types-bvGDId6f.cjs';
|
|
3
|
+
import * as cheerio from 'cheerio';
|
|
4
|
+
export { C as CompileError, a as CompileReactEmailOptions, S as SandboxStrategy } from './react-email-DuZAgJtw.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.
|
|
@@ -320,6 +372,24 @@ declare function checkTemplateVariables(html: string, options?: ParseOptions): T
|
|
|
320
372
|
*/
|
|
321
373
|
declare function checkOverflow(html: string, options?: ParseOptions): OverflowReport;
|
|
322
374
|
|
|
375
|
+
/**
|
|
376
|
+
* Check hand-written VML for the mistakes Outlook punishes.
|
|
377
|
+
*
|
|
378
|
+
* This is the one part of an email the DOM analyzers structurally cannot see:
|
|
379
|
+
* VML lives inside `<!--[if mso]>` conditional comments, so to every HTML
|
|
380
|
+
* parser it is a comment node, and to a headless-Chromium screenshot it does
|
|
381
|
+
* not exist at all. An email can therefore lint clean and preview perfectly
|
|
382
|
+
* while the branch Outlook actually renders is broken.
|
|
383
|
+
*
|
|
384
|
+
* ponytail: a tag-sequence checker, not a VML renderer. It validates structure
|
|
385
|
+
* and attribute values, which is where the reported breakages cluster. It does
|
|
386
|
+
* not resolve geometry, so it can say Outlook will misplace a nested shape but
|
|
387
|
+
* not where the shape lands.
|
|
388
|
+
*/
|
|
389
|
+
declare function checkVml(html: string, options?: {
|
|
390
|
+
positions?: boolean;
|
|
391
|
+
}): VmlReport;
|
|
392
|
+
|
|
323
393
|
/**
|
|
324
394
|
* Detect probable visual bugs in a stylized email: background images/gradients
|
|
325
395
|
* with no colour fallback, and font stacks with no web-safe fallback. Each
|
|
@@ -327,12 +397,18 @@ declare function checkOverflow(html: string, options?: ParseOptions): OverflowRe
|
|
|
327
397
|
*/
|
|
328
398
|
declare function checkVisual(html: string, options?: ParseOptions): VisualReport;
|
|
329
399
|
|
|
400
|
+
/**
|
|
401
|
+
* Report design drift in an HTML email: near-identical colours, and properties
|
|
402
|
+
* carrying more distinct values than a design system would.
|
|
403
|
+
*/
|
|
404
|
+
declare function checkDesignConsistency(html: string, options?: ParseOptions): DesignReport;
|
|
405
|
+
|
|
330
406
|
interface AuditOptions extends ParseOptions {
|
|
331
407
|
framework?: Framework;
|
|
332
408
|
/** Options for spam analysis */
|
|
333
409
|
spam?: SpamAnalysisOptions;
|
|
334
410
|
/** Skip specific checks */
|
|
335
|
-
skip?: Array<"spam" | "links" | "accessibility" | "images" | "compatibility" | "inboxPreview" | "size" | "templateVariables" | "overflow" | "visual">;
|
|
411
|
+
skip?: Array<"spam" | "links" | "accessibility" | "images" | "compatibility" | "inboxPreview" | "size" | "templateVariables" | "overflow" | "visual" | "darkContrast" | "mobileContrast" | "design" | "vml">;
|
|
336
412
|
}
|
|
337
413
|
interface AuditReport {
|
|
338
414
|
compatibility: {
|
|
@@ -353,6 +429,14 @@ interface AuditReport {
|
|
|
353
429
|
templateVariables: TemplateReport;
|
|
354
430
|
overflow: OverflowReport;
|
|
355
431
|
visual: VisualReport;
|
|
432
|
+
/** Structural faults in Outlook-only VML, which lives inside conditional comments. */
|
|
433
|
+
vml: VmlReport;
|
|
434
|
+
/** Contrast failures present only once a client inverts colours. */
|
|
435
|
+
darkContrast: AccessibilityIssue[];
|
|
436
|
+
/** Contrast failures present only below the email's mobile breakpoint. */
|
|
437
|
+
mobileContrast: AccessibilityIssue[];
|
|
438
|
+
/** Design drift: near-identical colours, and properties with no system left. */
|
|
439
|
+
design: DesignReport;
|
|
356
440
|
}
|
|
357
441
|
/**
|
|
358
442
|
* Run all email analysis checks in a single call.
|
|
@@ -453,7 +537,7 @@ interface EmailSession {
|
|
|
453
537
|
* Simulate dark mode for a specific client.
|
|
454
538
|
*
|
|
455
539
|
* Creates an isolated DOM copy per call (simulation mutates the DOM).
|
|
456
|
-
* Operates on the **original** HTML
|
|
540
|
+
* Operates on the **original** HTML, if you need dark mode on
|
|
457
541
|
* already-transformed HTML, use the standalone `simulateDarkMode()` instead.
|
|
458
542
|
*/
|
|
459
543
|
simulateDarkMode(clientId: string): {
|
|
@@ -466,7 +550,7 @@ interface EmailSession {
|
|
|
466
550
|
* DOM across all read-only analysis operations.
|
|
467
551
|
*
|
|
468
552
|
* Use this when you need to call multiple analysis functions on the
|
|
469
|
-
* same HTML
|
|
553
|
+
* same HTML: it eliminates redundant `cheerio.load()` calls.
|
|
470
554
|
*
|
|
471
555
|
* @example
|
|
472
556
|
* ```typescript
|
|
@@ -548,6 +632,21 @@ declare function wcagGrade(ratio: number): WcagGrade;
|
|
|
548
632
|
* Returns the flattened [r, g, b] as 0-255 values.
|
|
549
633
|
*/
|
|
550
634
|
declare function alphaBlend(fg: RGBA, bgR: number, bgG: number, bgB: number): [number, number, number];
|
|
635
|
+
/**
|
|
636
|
+
* Convert sRGB to OKLab.
|
|
637
|
+
*
|
|
638
|
+
* OKLab is built so that straight-line distance between two points matches how
|
|
639
|
+
* different the colours look, which sRGB emphatically does not: `#333` and
|
|
640
|
+
* `#343434` are far apart in RGB terms and identical to a reader.
|
|
641
|
+
*/
|
|
642
|
+
declare function rgbToOklab(rgba: RGBA): [number, number, number];
|
|
643
|
+
/**
|
|
644
|
+
* Perceptual distance between two colours, as OKLab delta-E.
|
|
645
|
+
*
|
|
646
|
+
* Roughly: under ~0.02 the two are the same colour to a reader, and around
|
|
647
|
+
* ~0.1 they are clearly different.
|
|
648
|
+
*/
|
|
649
|
+
declare function colorDistance(a: RGBA, b: RGBA): number;
|
|
551
650
|
|
|
552
651
|
/**
|
|
553
652
|
* Downlevel modern CSS in HTML emails to maximize email client compatibility.
|
|
@@ -575,4 +674,4 @@ declare function alphaBlend(fg: RGBA, bgR: number, bgG: number, bgB: number): [n
|
|
|
575
674
|
*/
|
|
576
675
|
declare function downlevelCSS(html: string): string;
|
|
577
676
|
|
|
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 };
|
|
677
|
+
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, VmlReport, type WcagGrade, alphaBlend, analyzeEmail, analyzeImages, analyzeSpam, auditEmail, caveatApplies, checkAccessibility, checkDarkModeContrast, checkDarkStylesContrastFromDom, checkDesignConsistency, checkMobileContrast, checkOverflow, checkSize, checkTemplateVariables, checkVisual, checkVml, 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 VmlReport, k as VisualReport, l as DesignReport, m as DeliverabilityReport } from './types-bvGDId6f.js';
|
|
2
|
+
export { B as BaseIssue, n as ClientTruncation, o as DeliverabilityCheck, p as DeliverabilityIssue, q as DesignIssue, r as EstimateOptions, s as ExportScope, t as FixType, u as ImageInfo, v as ImageIssue, w as InboxPreviewIssue, x as InputFormat, y as LinkIssue, z as OverflowIssue, P as PreviewResult, G as Severity, H as SizeIssue, J as SourceLocation, K as SpamIssue, M as TemplateIssue, N as TokenEstimate, Q as TokenEstimateWithWarnings, R as VisualIssue, U as VmlIssue, W as estimateAiFixTokens, X as generateFixPrompt, Y as heuristicTokenCount } from './types-bvGDId6f.js';
|
|
3
|
+
import * as cheerio from 'cheerio';
|
|
4
|
+
export { C as CompileError, a as CompileReactEmailOptions, S as SandboxStrategy } from './react-email-BROBcC8u.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.
|
|
@@ -320,6 +372,24 @@ declare function checkTemplateVariables(html: string, options?: ParseOptions): T
|
|
|
320
372
|
*/
|
|
321
373
|
declare function checkOverflow(html: string, options?: ParseOptions): OverflowReport;
|
|
322
374
|
|
|
375
|
+
/**
|
|
376
|
+
* Check hand-written VML for the mistakes Outlook punishes.
|
|
377
|
+
*
|
|
378
|
+
* This is the one part of an email the DOM analyzers structurally cannot see:
|
|
379
|
+
* VML lives inside `<!--[if mso]>` conditional comments, so to every HTML
|
|
380
|
+
* parser it is a comment node, and to a headless-Chromium screenshot it does
|
|
381
|
+
* not exist at all. An email can therefore lint clean and preview perfectly
|
|
382
|
+
* while the branch Outlook actually renders is broken.
|
|
383
|
+
*
|
|
384
|
+
* ponytail: a tag-sequence checker, not a VML renderer. It validates structure
|
|
385
|
+
* and attribute values, which is where the reported breakages cluster. It does
|
|
386
|
+
* not resolve geometry, so it can say Outlook will misplace a nested shape but
|
|
387
|
+
* not where the shape lands.
|
|
388
|
+
*/
|
|
389
|
+
declare function checkVml(html: string, options?: {
|
|
390
|
+
positions?: boolean;
|
|
391
|
+
}): VmlReport;
|
|
392
|
+
|
|
323
393
|
/**
|
|
324
394
|
* Detect probable visual bugs in a stylized email: background images/gradients
|
|
325
395
|
* with no colour fallback, and font stacks with no web-safe fallback. Each
|
|
@@ -327,12 +397,18 @@ declare function checkOverflow(html: string, options?: ParseOptions): OverflowRe
|
|
|
327
397
|
*/
|
|
328
398
|
declare function checkVisual(html: string, options?: ParseOptions): VisualReport;
|
|
329
399
|
|
|
400
|
+
/**
|
|
401
|
+
* Report design drift in an HTML email: near-identical colours, and properties
|
|
402
|
+
* carrying more distinct values than a design system would.
|
|
403
|
+
*/
|
|
404
|
+
declare function checkDesignConsistency(html: string, options?: ParseOptions): DesignReport;
|
|
405
|
+
|
|
330
406
|
interface AuditOptions extends ParseOptions {
|
|
331
407
|
framework?: Framework;
|
|
332
408
|
/** Options for spam analysis */
|
|
333
409
|
spam?: SpamAnalysisOptions;
|
|
334
410
|
/** Skip specific checks */
|
|
335
|
-
skip?: Array<"spam" | "links" | "accessibility" | "images" | "compatibility" | "inboxPreview" | "size" | "templateVariables" | "overflow" | "visual">;
|
|
411
|
+
skip?: Array<"spam" | "links" | "accessibility" | "images" | "compatibility" | "inboxPreview" | "size" | "templateVariables" | "overflow" | "visual" | "darkContrast" | "mobileContrast" | "design" | "vml">;
|
|
336
412
|
}
|
|
337
413
|
interface AuditReport {
|
|
338
414
|
compatibility: {
|
|
@@ -353,6 +429,14 @@ interface AuditReport {
|
|
|
353
429
|
templateVariables: TemplateReport;
|
|
354
430
|
overflow: OverflowReport;
|
|
355
431
|
visual: VisualReport;
|
|
432
|
+
/** Structural faults in Outlook-only VML, which lives inside conditional comments. */
|
|
433
|
+
vml: VmlReport;
|
|
434
|
+
/** Contrast failures present only once a client inverts colours. */
|
|
435
|
+
darkContrast: AccessibilityIssue[];
|
|
436
|
+
/** Contrast failures present only below the email's mobile breakpoint. */
|
|
437
|
+
mobileContrast: AccessibilityIssue[];
|
|
438
|
+
/** Design drift: near-identical colours, and properties with no system left. */
|
|
439
|
+
design: DesignReport;
|
|
356
440
|
}
|
|
357
441
|
/**
|
|
358
442
|
* Run all email analysis checks in a single call.
|
|
@@ -453,7 +537,7 @@ interface EmailSession {
|
|
|
453
537
|
* Simulate dark mode for a specific client.
|
|
454
538
|
*
|
|
455
539
|
* Creates an isolated DOM copy per call (simulation mutates the DOM).
|
|
456
|
-
* Operates on the **original** HTML
|
|
540
|
+
* Operates on the **original** HTML, if you need dark mode on
|
|
457
541
|
* already-transformed HTML, use the standalone `simulateDarkMode()` instead.
|
|
458
542
|
*/
|
|
459
543
|
simulateDarkMode(clientId: string): {
|
|
@@ -466,7 +550,7 @@ interface EmailSession {
|
|
|
466
550
|
* DOM across all read-only analysis operations.
|
|
467
551
|
*
|
|
468
552
|
* Use this when you need to call multiple analysis functions on the
|
|
469
|
-
* same HTML
|
|
553
|
+
* same HTML: it eliminates redundant `cheerio.load()` calls.
|
|
470
554
|
*
|
|
471
555
|
* @example
|
|
472
556
|
* ```typescript
|
|
@@ -548,6 +632,21 @@ declare function wcagGrade(ratio: number): WcagGrade;
|
|
|
548
632
|
* Returns the flattened [r, g, b] as 0-255 values.
|
|
549
633
|
*/
|
|
550
634
|
declare function alphaBlend(fg: RGBA, bgR: number, bgG: number, bgB: number): [number, number, number];
|
|
635
|
+
/**
|
|
636
|
+
* Convert sRGB to OKLab.
|
|
637
|
+
*
|
|
638
|
+
* OKLab is built so that straight-line distance between two points matches how
|
|
639
|
+
* different the colours look, which sRGB emphatically does not: `#333` and
|
|
640
|
+
* `#343434` are far apart in RGB terms and identical to a reader.
|
|
641
|
+
*/
|
|
642
|
+
declare function rgbToOklab(rgba: RGBA): [number, number, number];
|
|
643
|
+
/**
|
|
644
|
+
* Perceptual distance between two colours, as OKLab delta-E.
|
|
645
|
+
*
|
|
646
|
+
* Roughly: under ~0.02 the two are the same colour to a reader, and around
|
|
647
|
+
* ~0.1 they are clearly different.
|
|
648
|
+
*/
|
|
649
|
+
declare function colorDistance(a: RGBA, b: RGBA): number;
|
|
551
650
|
|
|
552
651
|
/**
|
|
553
652
|
* Downlevel modern CSS in HTML emails to maximize email client compatibility.
|
|
@@ -575,4 +674,4 @@ declare function alphaBlend(fg: RGBA, bgR: number, bgG: number, bgB: number): [n
|
|
|
575
674
|
*/
|
|
576
675
|
declare function downlevelCSS(html: string): string;
|
|
577
676
|
|
|
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 };
|
|
677
|
+
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, VmlReport, type WcagGrade, alphaBlend, analyzeEmail, analyzeImages, analyzeSpam, auditEmail, caveatApplies, checkAccessibility, checkDarkModeContrast, checkDarkStylesContrastFromDom, checkDesignConsistency, checkMobileContrast, checkOverflow, checkSize, checkTemplateVariables, checkVisual, checkVml, 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 };
|