{"_id":"maillint","name":"maillint","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"maillint","version":"0.1.0","description":"Lint HTML email for client compatibility — locally, no render farm. Flags CSS/HTML that breaks in Outlook (Word engine), Gmail clipping at 102KB, missing image alt/dimensions and more, checked against a bundled caniemail-derived support matrix. Determinis","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"bin":{"maillint":"dist/cli.js"},"engines":{"node":">=18"},"scripts":{"build":"tsup","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","lint":"tsc --noEmit","example":"node dist/cli.js scan examples/newsletter.html","prepublishOnly":"npm run build"},"keywords":["email","html-email","email-linter","email-development","caniemail","outlook","gmail","mjml","transactional-email","newsletter","email-template","css","litmus","email-testing","cli"],"author":{"name":"didrod205","url":"https://github.com/didrod205"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/didrod205/maillint.git"},"bugs":{"url":"https://github.com/didrod205/maillint/issues"},"homepage":"https://github.com/didrod205/maillint#readme","dependencies":{"cac":"^6.7.14","picocolors":"^1.1.1"},"devDependencies":{"@types/node":"^22.10.0","tsup":"^8.3.5","typescript":"^5.7.2","vitest":"^2.1.8"},"gitHead":"03a8225ffd05e63855aebf8fb2c08a5cb18f6b28","_id":"maillint@0.1.0","_nodeVersion":"25.9.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-OLGafeD6lWsCSZFeb7GB4SWCV+svR/mNy3PBuZKpuTPa3VuHwCBoovt4eTEzJZTitInvVOUbL/Pk6hg3HxpSpA==","shasum":"17a6dbbffadab7735f4213eb9574c3590ce05e53","tarball":"https://registry.npmjs.org/maillint/-/maillint-0.1.0.tgz","fileCount":15,"unpackedSize":383986,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC9UKSnPiWVJEaUqfiFAbJMrIpxN/phmfgJgUCwOcXM3wIhAOXvCN8mnIBFHBX5JOzhMynr1yh7vqBBUhF6jLpNbgUf"}]},"_npmUser":{"name":"didrod2539","email":"ykc205@naver.com"},"directories":{},"maintainers":[{"name":"didrod2539","email":"ykc205@naver.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/maillint_0.1.0_1780553420766_0.3748545344250216"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-04T06:10:20.712Z","0.1.0":"2026-06-04T06:10:21.094Z","modified":"2026-06-04T06:10:21.321Z"},"maintainers":[{"name":"didrod2539","email":"ykc205@naver.com"}],"description":"Lint HTML email for client compatibility — locally, no render farm. Flags CSS/HTML that breaks in Outlook (Word engine), Gmail clipping at 102KB, missing image alt/dimensions and more, checked against a bundled caniemail-derived support matrix. Determinis","homepage":"https://github.com/didrod205/maillint#readme","keywords":["email","html-email","email-linter","email-development","caniemail","outlook","gmail","mjml","transactional-email","newsletter","email-template","css","litmus","email-testing","cli"],"repository":{"type":"git","url":"git+https://github.com/didrod205/maillint.git"},"author":{"name":"didrod205","url":"https://github.com/didrod205"},"bugs":{"url":"https://github.com/didrod205/maillint/issues"},"license":"MIT","readme":"<div align=\"center\">\n\n# 📬 maillint\n\n### Catch email rendering bugs before you hit send — Outlook breakage & Gmail clipping, linted locally.\n\n[![npm version](https://img.shields.io/npm/v/maillint.svg?color=success)](https://www.npmjs.com/package/maillint)\n[![bundle size](https://img.shields.io/bundlephobia/minzip/maillint?label=core%20gzip)](https://bundlephobia.com/package/maillint)\n[![CI](https://github.com/didrod205/maillint/actions/workflows/ci.yml/badge.svg)](https://github.com/didrod205/maillint/actions/workflows/ci.yml)\n[![types](https://img.shields.io/npm/types/maillint.svg)](https://www.npmjs.com/package/maillint)\n[![license](https://img.shields.io/npm/l/maillint.svg)](./LICENSE)\n\n</div>\n\nYou hand-code (or template) an HTML email, send a test to yourself, it looks fine —\nand then it ships **broken in Outlook** (which renders with Word's engine and\nignores `flex`, `position`, `background-image`, `border-radius`…) or **clipped in\nGmail** (which truncates anything past ~102 KB, hiding your CTA and unsubscribe\nlink). The only ways to know are a **paid render farm** (Litmus, Email on Acid) or\n**manually** cross-checking every CSS property on caniemail.com.\n\n**maillint checks your email HTML against a bundled, caniemail-derived support\nmatrix — locally, deterministically, in one command.** No render farm, no API key,\nno sending.\n\n```bash\nnpx maillint scan newsletter.html\n```\n\n```\nnewsletter.html  0/100 (F) · 1.3 KB\n  ✗ L9   display: flex            breaks in: Gmail, Outlook (Windows), Outlook.com\n  ✗ L11  CSS background-image     breaks in: Outlook (Windows, Word engine)\n  ✗ L13  border-radius            breaks in: Outlook (Windows, Word engine)\n  ✗ L44  <svg> graphics           breaks in: Gmail, Outlook, Yahoo!, Samsung…\n  ✗ L46  <form> interactivity     breaks in: Gmail, Outlook, Outlook.com, Yahoo!\n  ⚠ L35  Image without alt text   → add alt, or alt=\"\" for decorative\n```\n\n---\n\n## Why maillint?\n\n- 🎯 **Per-client truth, not guesses.** Each finding names the exact clients that\n  break and how to fix it, from a curated matrix modelled on **caniemail.com** —\n  the same data the pros check by hand, baked in.\n- 🔒 **Local & deterministic.** No render farm, no upload, no API key. Same input →\n  same output. Runs offline and in CI on every template change.\n- 📏 **Gmail clipping is just math.** maillint measures the real UTF-8 byte size and\n  warns *before* you cross the ~102 KB line that hides your call to action.\n- ♿ **a11y built in.** Missing image `alt`, width-less images (Outlook blows them\n  up), layout tables without `role=\"presentation\"`, missing charset/doctype/lang.\n- 🪶 **Zero-dependency core.** The library imports nothing at runtime; the CLI adds\n  only `cac` + `picocolors`.\n\nWhy not just ask an LLM \"will this render in Outlook\"? Client support is **exact,\nshifting data** — a chatbot hallucinates it, can't run in CI, and can't byte-count\nyour template on every commit. maillint is a lookup table, not a vibe.\n\n## Install\n\n```bash\n# run it now, no install\nnpx maillint scan email.html\n\n# or add it\nnpm install -g maillint      # global CLI\nnpm install -D maillint      # CI dependency\n```\n\nNode ≥ 18. Ships ESM + CJS + TypeScript types. Works on raw HTML, or the HTML your\nMJML/Handlebars/React-Email build emits.\n\n## Quick start\n\n```bash\nmaillint scan newsletter.html              # lint one file\ncat email.html | maillint scan             # or pipe it\nmaillint scan ./emails --min-score 80      # CI gate over a folder\nmaillint scan email.html --clients gmail,outlook-windows   # only the clients you target\nmaillint scan email.html --md report.md    # Markdown report for a PR\nmaillint init                              # write maillint.config.json\n```\n\nSee [`examples/sample-report.md`](./examples/sample-report.md) for a full report,\nand [`examples/clean.html`](./examples/clean.html) for an email that scores 100/100.\n\n## What it checks\n\n| Category | Examples |\n| -------- | -------- |\n| **Client compatibility** | `flex`/`grid`, `position`, `max-width`, `border-radius`, `box-shadow`, `background-image`, `transform`/`animation`, web fonts (`@font-face`), `@import`, `@media` (Outlook), `padding` on `<a>`, `<form>`/`<input>`/`<button>`, `<svg>`, `<video>` — each mapped to the clients that break |\n| **Gmail clipping** | real UTF-8 byte size vs Gmail's ~102 KB clip limit (error over, warning approaching) |\n| **Images** | missing `alt` (clients block images by default), missing explicit `width` (Outlook scaling) |\n| **Structure & a11y** | `<!DOCTYPE>`, `<meta charset>`, `<html lang>`, `<title>`, `role=\"presentation\"` on layout tables |\n\nEach finding is a weighted error / warning / info; files roll up to a 0–100 score\nand an A–F grade you can gate in CI.\n\n## Real scenarios\n\n**1. CI gate on your email templates.** A PR that adds a `display:flex` hero or a\nweb font fails the build before it reaches a real inbox:\n\n```yaml\n# .github/workflows/email.yml\n- run: npx maillint scan ./emails --min-score 85 --md email-report.md\n```\n\n**2. Lint your ESP/MJML output.** Point maillint at the compiled HTML from\nReact Email, MJML or your ESP to catch what the framework (or a hand-tweak) let\nthrough — clipping, a missing `alt`, an unsupported gradient.\n\n**3. Target only the clients you support.** A B2B product whose audience lives in\nOutlook? `--clients outlook-windows,outlook-com` focuses the report on what\nactually matters to your recipients.\n\n## Configuration\n\n`maillint init` writes `maillint.config.json`:\n\n```jsonc\n{\n  \"clients\": [\"apple-mail-ios\", \"gmail\", \"outlook-windows\", \"...\"],\n  \"ignore\": [],            // rule ids, e.g. [\"compat.border-radius\"]\n  \"partialSeverity\": \"info\",\n  \"clipBytes\": 102400,      // Gmail clipping threshold\n  \"clipWarnRatio\": 0.9,\n  \"minScore\": 0             // CI gate\n}\n```\n\n## Library API\n\n```ts\nimport { lintEmail, DEFAULT_CONFIG } from \"maillint\";\n\nconst { findings, bytes } = lintEmail(html, DEFAULT_CONFIG);\nfor (const f of findings) {\n  console.log(f.severity, f.rule, f.unsupported); // e.g. [\"gmail\",\"outlook-windows\"]\n}\n```\n\nAlso exported: `lintFile`, `buildReport`, `parseEmail`, the support matrix\n(`CSS_FEATURES`, `HTML_FEATURES`, `AT_RULE_FEATURES`), `CLIENTS`, and all types.\nThe core is dependency-free and browser-safe (great for a live playground).\n\n## Roadmap\n\n- 🤖 **Optional `--ai` layer (bring-your-own key)** to *suggest rewrites* for\n  flagged code (e.g. a VML fallback for a CSS background). The core stays 100%\n  offline and deterministic — AI is enhancement only.\n- More matrix coverage (dark-mode `prefers-color-scheme`, `mso-` props, AMP4email).\n- Inline `<!-- maillint-disable -->` comments and per-rule severity overrides.\n- Auto-inlining hints (which `<style>` rules to inline for stripping clients).\n- A web playground — paste HTML, see the report, nothing uploaded.\n\n## 💖 Sponsor\n\nmaillint is free and MIT-licensed, built and maintained in spare time. If it saved\nyou a broken send (or a render-farm subscription), please consider supporting it:\n\n- ⭐ **Star this repo** — the simplest free way to help others find it.\n- 🍋 **[Sponsor via Lemon Squeezy](https://elab-studio.lemonsqueezy.com/checkout/buy/5d059b89-51d0-456b-b33a-ed56994f7010)** — one-time or recurring.\n\n> The support matrix is modelled on the excellent community data at\n> [caniemail.com](https://www.caniemail.com). maillint bundles a curated snapshot;\n> it isn't affiliated with caniemail.\n\n## License\n\n[MIT](./LICENSE) © maillint contributors\n","readmeFilename":"README.md","_rev":"1-8394b3ea1970ab6bfe267861c2fe3be9"}