@emailens/engine 0.8.0 → 0.8.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.
Files changed (2) hide show
  1. package/README.md +55 -33
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,64 +1,82 @@
1
1
  # @emailens/engine
2
2
 
3
- Email compatibility engine that transforms CSS per email client, analyzes compatibility across **250+ CSS properties**, scores results, simulates dark mode, provides framework-aware fix snippets, checks DNS deliverability (SPF, DKIM, DMARC, MX, BIMI), and runs content hygiene, accessibility, link, image, inbox preview, size, and template variable analysis.
3
+ **Your email looks perfect in Apple Mail. Gmail strips half the CSS. Outlook renders it in Word.**
4
4
 
5
- Supports **12 email clients**: Gmail (Web, Android, iOS), Outlook (365, Windows), Apple Mail (macOS, iOS), Yahoo Mail, Samsung Mail, Thunderbird, HEY Mail, and Superhuman.
5
+ `@emailens/engine` analyzes your HTML against 250+ CSS properties across 12 email clients, scores compatibility, and shows you exactly what to fix before you hit send.
6
6
 
7
- ## Install
7
+ ## Quick Start
8
8
 
9
9
  ```bash
10
10
  npm install @emailens/engine
11
- # or
12
- bun add @emailens/engine
13
11
  ```
14
12
 
15
- Requires Node.js >= 18.
16
-
17
- ## Quick Start
18
-
19
13
  ```typescript
20
14
  import { auditEmail } from "@emailens/engine";
21
15
 
16
+ // Flexbox + gap + box-shadow — all Outlook killers
22
17
  const html = `<html lang="en">
23
- <head><title>Newsletter</title>
24
- <style>.card { border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }</style>
18
+ <head><title>Weekly Update</title>
19
+ <style>
20
+ .card { border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
21
+ </style>
25
22
  </head>
26
23
  <body>
27
24
  <div class="card" style="display: flex; gap: 16px;">
28
25
  <div>Column A</div>
29
26
  <div>Column B</div>
30
27
  </div>
31
- <a href="https://example.com/unsubscribe">Unsubscribe</a>
32
28
  </body>
33
29
  </html>`;
34
30
 
35
- // Run all checks in one call
36
31
  const report = auditEmail(html, { framework: "jsx" });
37
32
 
33
+ console.log(report.compatibility.scores["outlook-windows"]);
34
+ // { score: 30, errors: 3, warnings: 3, info: 1 }
35
+ // ↑ Outlook uses Word — flexbox, gap, box-shadow, border-radius all break
36
+
38
37
  console.log(report.compatibility.scores["gmail-web"]);
39
38
  // { score: 75, errors: 0, warnings: 5, info: 0 }
40
39
 
41
- console.log(report.spam);
42
- // { score: 100, level: "low", issues: [] }
43
-
44
- console.log(report.accessibility.score);
45
- // 88
40
+ console.log(report.spam.score); // 100 (clean)
41
+ console.log(report.accessibility.score); // 88
42
+ console.log(report.size.clipped); // false (under Gmail's 102KB limit)
43
+ ```
46
44
 
47
- console.log(report.links.totalLinks);
48
- // 1
45
+ Score too low? Fix it automatically:
49
46
 
50
- console.log(report.images.total);
51
- // 0
47
+ ```typescript
48
+ import { generateAiFix, AI_FIX_SYSTEM_PROMPT } from "@emailens/engine";
52
49
 
53
- console.log(report.inboxPreview.subject);
54
- // "Newsletter"
50
+ const { code } = await generateAiFix({
51
+ originalHtml: html,
52
+ warnings: report.compatibility.warnings,
53
+ scores: report.compatibility.scores,
54
+ scope: "outlook-windows",
55
+ format: "jsx",
56
+ provider: async (prompt) => {
57
+ // Any LLM — Claude, GPT, etc.
58
+ const msg = await anthropic.messages.create({
59
+ model: "claude-sonnet-4-6",
60
+ max_tokens: 8192,
61
+ system: AI_FIX_SYSTEM_PROMPT,
62
+ messages: [{ role: "user", content: prompt }],
63
+ });
64
+ return msg.content[0].type === "text" ? msg.content[0].text : "";
65
+ },
66
+ });
67
+ // code → JSX with <Table> layout, VML roundrects, inline fallbacks
68
+ ```
55
69
 
56
- console.log(report.size.clipped);
57
- // false
70
+ ## What It Catches
58
71
 
59
- console.log(report.templateVariables.unresolvedCount);
60
- // 0
61
- ```
72
+ - **CSS compatibility** — 250+ properties tested across 12 email clients, with fix snippets and AI-powered auto-fix
73
+ - **Spam scoring** — 45+ signals modeled after SpamAssassin, CAN-SPAM, and GDPR
74
+ - **Accessibility** — WCAG contrast ratios, alt text, semantic structure, heading hierarchy
75
+ - **Link validation** — broken hrefs, insecure HTTP, `javascript:` protocols, deceptive URLs
76
+ - **Image analysis** — missing dimensions, oversized data URIs, tracking pixels, WebP/SVG format
77
+ - **Inbox preview** — subject/preheader truncation per client, Gmail clipping detection
78
+ - **Domain authentication** — SPF, DKIM, DMARC, MX, and BIMI DNS record validation
79
+ - **Template variables** — unresolved merge tags across 6 template systems (Handlebars, ERB, Mailchimp, etc.)
62
80
 
63
81
  ## API Reference
64
82
 
@@ -185,9 +203,9 @@ Get only warnings that require HTML restructuring (`fixType: "structural"`).
185
203
 
186
204
  ### `analyzeSpam(html: string, options?: SpamAnalysisOptions): SpamReport`
187
205
 
188
- Analyzes an HTML email for content hygiene issues. Returns a 0–100 score (100 = clean) and an array of issues. Uses heuristic rules modeled after SpamAssassin, CAN-SPAM, and GDPR.
206
+ Analyzes an HTML email for spam scoring issues. Returns a 0–100 score (100 = clean) and an array of issues. Uses heuristic rules modeled after SpamAssassin, CAN-SPAM, and GDPR.
189
207
 
190
- > **Note:** Content hygiene heuristics — not a real spam filter. This checks for common anti-patterns that trigger spam filters but cannot predict actual inbox placement. For real spam testing, use the `checkSpamAssassin()` integration or a dedicated service.
208
+ > **Note:** Spam scoring heuristics — not a real spam filter. This checks for common anti-patterns that trigger spam filters but cannot predict actual inbox placement. For real spam testing, use the `checkSpamAssassin()` integration or a dedicated service.
191
209
 
192
210
  ```typescript
193
211
  import { analyzeSpam } from "@emailens/engine";
@@ -668,13 +686,17 @@ interface SpamAssassinResult {
668
686
  }
669
687
  ```
670
688
 
671
- ## Testing
689
+ ## Contributing
690
+
691
+ Contributions are welcome! Please [open an issue](https://github.com/nicholasgriffintn/emailens/issues) to discuss your idea before submitting a PR.
672
692
 
673
693
  ```bash
674
694
  bun test
675
695
  ```
676
696
 
677
- 574 tests covering analysis (250+ CSS properties), transformation, dark mode simulation, framework-aware fixes, AI fix generation, token estimation, content hygiene scoring, link validation, accessibility checking, image analysis, inbox preview extraction, size checking, template variable detection, DNS deliverability checking, session API, security hardening, integration pipelines, accuracy benchmarks, and battle tests.
697
+ 574 tests covering CSS analysis (250+ properties), transformation, dark mode simulation, framework-aware fixes, AI fix generation, token estimation, spam scoring, link validation, accessibility checking, image analysis, inbox preview extraction, size checking, template variable detection, DNS deliverability checking, session API, security hardening, integration pipelines, accuracy benchmarks, and battle tests.
698
+
699
+ **Project structure:** analysis modules live in `src/`, each with a corresponding test file in `tests/`. The engine parses HTML once and shares the DOM across all analyzers.
678
700
 
679
701
  ## License
680
702
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emailens/engine",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "Email compatibility engine — 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": {