@visulima/email 1.0.1 → 2.0.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/CHANGELOG.md +7 -0
- package/dist/middleware/index.d.ts +4 -3
- package/dist/render/cid.d.ts +17 -0
- package/dist/render/css-inline.d.ts +15 -0
- package/dist/render/css-inline.js +1 -0
- package/dist/render/dark-mode.d.ts +20 -0
- package/dist/render/preheader.d.ts +24 -0
- package/package.json +31 -19
- package/dist/packem_shared/inlineCss-BQ7d2Cyz.js +0 -1
- package/dist/packem_shared/postProcessHtml-DqKi2Ucg.js +0 -1
- package/dist/render/index.d.ts +0 -107
- package/dist/render/index.js +0 -1
- /package/dist/{packem_shared/extractCidReferences-BuoTREMp.js → render/cid.js} +0 -0
- /package/dist/{packem_shared/addDarkModeSupport-DZYxULjl.js → render/dark-mode.js} +0 -0
- /package/dist/{packem_shared/injectPreheader-CF9WHZ7J.js → render/preheader.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## @visulima/email [2.0.0](https://github.com/visulima/visulima/compare/%40visulima%2Femail%401.0.1...%40visulima%2Femail%402.0.0) (2026-07-15)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Dependencies
|
|
5
|
+
|
|
6
|
+
* **@visulima/fs:** upgraded to 5.0.2
|
|
7
|
+
|
|
1
8
|
## @visulima/email [1.0.1](https://github.com/visulima/visulima/compare/%40visulima%2Femail%401.0.0...%40visulima%2Femail%401.0.1) (2026-07-15)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -250,16 +250,17 @@ declare const RATE_LIMIT_PRESETS: {
|
|
|
250
250
|
declare const rateLimitMiddleware: (options: RateLimitMiddlewareOptions) => Middleware;
|
|
251
251
|
/**
|
|
252
252
|
* Wraps a transform that rewrites the message before it is sent — e.g. running the HTML through the
|
|
253
|
-
*
|
|
253
|
+
* render helpers (preheader, dark-mode, CID rewrite) and the opt-in CSS inliner.
|
|
254
254
|
* @param transform Maps the resolved {@link EmailOptions} to its rendered form.
|
|
255
255
|
* @returns A middleware that applies the transform ahead of the provider call.
|
|
256
256
|
* @example
|
|
257
257
|
* ```ts
|
|
258
|
-
* import {
|
|
258
|
+
* import { injectPreheader } from "@visulima/email/render/preheader";
|
|
259
|
+
* import { addDarkModeSupport } from "@visulima/email/render/dark-mode";
|
|
259
260
|
*
|
|
260
261
|
* mail.use(withRender(async (email) => ({
|
|
261
262
|
* ...email,
|
|
262
|
-
* html: email.html ?
|
|
263
|
+
* html: email.html ? addDarkModeSupport(injectPreheader(email.html, "Hi!")) : email.html,
|
|
263
264
|
* })));
|
|
264
265
|
* ```
|
|
265
266
|
*/
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rewrites `cid:` references in `src`/`href` attributes using a resolver.
|
|
3
|
+
*
|
|
4
|
+
* Useful for turning inline (Content-ID) image references into hosted URLs for previews/webmail, or
|
|
5
|
+
* for normalizing them. Returning `undefined` from the resolver leaves that reference unchanged.
|
|
6
|
+
* @param html The HTML email.
|
|
7
|
+
* @param resolver Maps a Content-ID to a replacement URL (or `undefined` to keep it).
|
|
8
|
+
* @returns The rewritten HTML.
|
|
9
|
+
*/
|
|
10
|
+
declare const rewriteCidLinks: (html: string, resolver: (cid: string) => string | undefined) => string;
|
|
11
|
+
/**
|
|
12
|
+
* Collects the Content-IDs referenced via `cid:` in `src`/`href` attributes.
|
|
13
|
+
* @param html The HTML email.
|
|
14
|
+
* @returns The referenced Content-IDs (de-duplicated, in first-seen order).
|
|
15
|
+
*/
|
|
16
|
+
declare const extractCidReferences: (html: string) => string[];
|
|
17
|
+
export { extractCidReferences, rewriteCidLinks };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inlines `<style>`/linked CSS into element `style` attributes for maximum email-client
|
|
3
|
+
* compatibility, via [juice](https://github.com/Automattic/juice).
|
|
4
|
+
*
|
|
5
|
+
* `juice` is an optional peer dependency, and this helper is published as its own subpath
|
|
6
|
+
* (`@visulima/email/render/css-inline`). Importing this module resolves `juice` eagerly, so install
|
|
7
|
+
* it (`pnpm add juice`) before importing — consumers who never inline CSS simply never import this
|
|
8
|
+
* entry, which keeps `juice` out of edge/worker bundles.
|
|
9
|
+
* @param html The HTML email.
|
|
10
|
+
* @param options Options forwarded to `juice` (e.g. `preserveImportant`, `removeStyleTags`).
|
|
11
|
+
* @returns The HTML with CSS inlined.
|
|
12
|
+
* @throws {EmailError} When inlining fails.
|
|
13
|
+
*/
|
|
14
|
+
declare const inlineCss: (html: string, options?: Record<string, unknown>) => string;
|
|
15
|
+
export { inlineCss as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import t from"juice";import n from"../packem_shared/EmailError-B-sEf3bp.js";const i=(r,o)=>{const a=t.default??t;try{return a(r,o)}catch(e){throw new n("render",`Failed to inline CSS: ${e.message}`,{cause:e})}};export{i as default};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for {@link addDarkModeSupport}.
|
|
3
|
+
*/
|
|
4
|
+
interface DarkModeOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Extra CSS to wrap in a `@media (prefers-color-scheme: dark)` block (the dark-mode overrides).
|
|
7
|
+
*/
|
|
8
|
+
styles?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Adds dark-mode hooks to an HTML email: the `color-scheme` / `supported-color-schemes` meta tags and,
|
|
12
|
+
* when provided, a `@media (prefers-color-scheme: dark)` style block.
|
|
13
|
+
*
|
|
14
|
+
* Injected into `<head>` (created after `<html>` if absent, otherwise prepended).
|
|
15
|
+
* @param html The HTML email.
|
|
16
|
+
* @param options Dark-mode options. See {@link DarkModeOptions}.
|
|
17
|
+
* @returns The HTML with dark-mode support added.
|
|
18
|
+
*/
|
|
19
|
+
declare const addDarkModeSupport: (html: string, options?: DarkModeOptions) => string;
|
|
20
|
+
export { DarkModeOptions, addDarkModeSupport };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for {@link injectPreheader}.
|
|
3
|
+
*/
|
|
4
|
+
interface PreheaderOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Append invisible padding characters so the preheader text isn't followed by leaked body content
|
|
7
|
+
* in the inbox preview.
|
|
8
|
+
* @default true
|
|
9
|
+
*/
|
|
10
|
+
spacer?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Injects a hidden preheader (inbox preview text) at the start of the HTML body.
|
|
14
|
+
*
|
|
15
|
+
* The preheader is wrapped in a `display:none` element with `mso-hide:all`, followed by zero-width
|
|
16
|
+
* padding so the preview shows only your text. Inserted right after `<body>` (or prepended if no
|
|
17
|
+
* body tag is present).
|
|
18
|
+
* @param html The HTML email.
|
|
19
|
+
* @param preheader The preview text.
|
|
20
|
+
* @param options Injection options. See {@link PreheaderOptions}.
|
|
21
|
+
* @returns The HTML with the preheader injected.
|
|
22
|
+
*/
|
|
23
|
+
declare const injectPreheader: (html: string, preheader: string, options?: PreheaderOptions) => string;
|
|
24
|
+
export { PreheaderOptions, injectPreheader };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@visulima/email",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A comprehensive email library with multi-provider support, crypto utilities, and template engines",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ahasend",
|
|
@@ -63,11 +63,6 @@
|
|
|
63
63
|
],
|
|
64
64
|
"homepage": "https://visulima.com/packages/email",
|
|
65
65
|
"bugs": "https://github.com/visulima/visulima/issues",
|
|
66
|
-
"license": "MIT",
|
|
67
|
-
"author": {
|
|
68
|
-
"name": "Daniel Bannert",
|
|
69
|
-
"email": "d.bannert@anolilab.de"
|
|
70
|
-
},
|
|
71
66
|
"repository": {
|
|
72
67
|
"type": "git",
|
|
73
68
|
"url": "git+https://github.com/visulima/visulima.git",
|
|
@@ -83,13 +78,13 @@
|
|
|
83
78
|
"url": "https://anolilab.com/support"
|
|
84
79
|
}
|
|
85
80
|
],
|
|
86
|
-
"
|
|
87
|
-
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
|
|
91
|
-
"type": "module",
|
|
81
|
+
"license": "MIT",
|
|
82
|
+
"author": {
|
|
83
|
+
"name": "Daniel Bannert",
|
|
84
|
+
"email": "d.bannert@anolilab.de"
|
|
85
|
+
},
|
|
92
86
|
"sideEffects": false,
|
|
87
|
+
"type": "module",
|
|
93
88
|
"exports": {
|
|
94
89
|
".": {
|
|
95
90
|
"types": "./dist/index.d.ts",
|
|
@@ -179,9 +174,21 @@
|
|
|
179
174
|
"types": "./dist/crypto/index.d.ts",
|
|
180
175
|
"default": "./dist/crypto/index.js"
|
|
181
176
|
},
|
|
182
|
-
"./render": {
|
|
183
|
-
"types": "./dist/render/
|
|
184
|
-
"default": "./dist/render/
|
|
177
|
+
"./render/cid": {
|
|
178
|
+
"types": "./dist/render/cid.d.ts",
|
|
179
|
+
"default": "./dist/render/cid.js"
|
|
180
|
+
},
|
|
181
|
+
"./render/css-inline": {
|
|
182
|
+
"types": "./dist/render/css-inline.d.ts",
|
|
183
|
+
"default": "./dist/render/css-inline.js"
|
|
184
|
+
},
|
|
185
|
+
"./render/dark-mode": {
|
|
186
|
+
"types": "./dist/render/dark-mode.d.ts",
|
|
187
|
+
"default": "./dist/render/dark-mode.js"
|
|
188
|
+
},
|
|
189
|
+
"./render/preheader": {
|
|
190
|
+
"types": "./dist/render/preheader.d.ts",
|
|
191
|
+
"default": "./dist/render/preheader.js"
|
|
185
192
|
},
|
|
186
193
|
"./webhooks": {
|
|
187
194
|
"types": "./dist/webhooks/index.d.ts",
|
|
@@ -353,10 +360,11 @@
|
|
|
353
360
|
},
|
|
354
361
|
"./package.json": "./package.json"
|
|
355
362
|
},
|
|
356
|
-
"
|
|
357
|
-
"
|
|
358
|
-
"
|
|
359
|
-
|
|
363
|
+
"files": [
|
|
364
|
+
"dist",
|
|
365
|
+
"README.md",
|
|
366
|
+
"CHANGELOG.md"
|
|
367
|
+
],
|
|
360
368
|
"dependencies": {
|
|
361
369
|
"html-to-text": "^10.0.0",
|
|
362
370
|
"ical-generator": "11.0.0",
|
|
@@ -421,5 +429,9 @@
|
|
|
421
429
|
},
|
|
422
430
|
"engines": {
|
|
423
431
|
"node": "^22.14.0 || >=24.10.0"
|
|
432
|
+
},
|
|
433
|
+
"publishConfig": {
|
|
434
|
+
"access": "public",
|
|
435
|
+
"provenance": true
|
|
424
436
|
}
|
|
425
437
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{createRequire as i}from"node:module";import r from"./EmailError-B-sEf3bp.js";const a=i(import.meta.url),n=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,c=o=>{if(typeof n<"u"&&n.versions&&n.versions.node){const[s,t]=n.versions.node.split(".").map(Number);if(s>22||s===22&&t>=3||s===20&&t>=16)return n.getBuiltinModule(o)}return a(o)},{createRequire:u}=c("node:module"),d=u(import.meta.url),p=(o,s)=>{let t;try{const e=d("juice");t=e.default??e}catch(e){throw e instanceof Error&&(e.code==="MODULE_NOT_FOUND"||e.message.includes("Cannot find module")||e.message.includes("Cannot find package"))?new r("render","juice is not installed. Please install it: pnpm add juice",{cause:e}):new r("render",`Failed to load juice: ${e.message}`,{cause:e})}try{return t(o,s)}catch(e){throw new r("render",`Failed to inline CSS: ${e.message}`,{cause:e})}};export{p as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{rewriteCidLinks as i}from"./extractCidReferences-BuoTREMp.js";import d from"./inlineCss-BQ7d2Cyz.js";import{addDarkModeSupport as t}from"./addDarkModeSupport-DZYxULjl.js";import{injectPreheader as s}from"./injectPreheader-CF9WHZ7J.js";const c=(e,r={})=>{let o=e;return r.inlineCss&&(o=d(o,typeof r.inlineCss=="object"?r.inlineCss:void 0)),r.preheader!==void 0&&(o=s(o,r.preheader,r.preheaderOptions)),r.darkMode&&(o=t(o,typeof r.darkMode=="object"?r.darkMode:void 0)),r.cidResolver&&(o=i(o,r.cidResolver)),o};export{c as postProcessHtml};
|
package/dist/render/index.d.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Rewrites `cid:` references in `src`/`href` attributes using a resolver.
|
|
3
|
-
*
|
|
4
|
-
* Useful for turning inline (Content-ID) image references into hosted URLs for previews/webmail, or
|
|
5
|
-
* for normalizing them. Returning `undefined` from the resolver leaves that reference unchanged.
|
|
6
|
-
* @param html The HTML email.
|
|
7
|
-
* @param resolver Maps a Content-ID to a replacement URL (or `undefined` to keep it).
|
|
8
|
-
* @returns The rewritten HTML.
|
|
9
|
-
*/
|
|
10
|
-
declare const rewriteCidLinks: (html: string, resolver: (cid: string) => string | undefined) => string;
|
|
11
|
-
/**
|
|
12
|
-
* Collects the Content-IDs referenced via `cid:` in `src`/`href` attributes.
|
|
13
|
-
* @param html The HTML email.
|
|
14
|
-
* @returns The referenced Content-IDs (de-duplicated, in first-seen order).
|
|
15
|
-
*/
|
|
16
|
-
declare const extractCidReferences: (html: string) => string[];
|
|
17
|
-
/**
|
|
18
|
-
* Inlines `<style>`/linked CSS into element `style` attributes for maximum email-client
|
|
19
|
-
* compatibility, via [juice](https://github.com/Automattic/juice).
|
|
20
|
-
*
|
|
21
|
-
* `juice` is an optional peer dependency — install it (`pnpm add juice`) to use this. It is loaded
|
|
22
|
-
* lazily (via `createRequire`) so importing the render entry point doesn't fail when `juice` is absent.
|
|
23
|
-
* @param html The HTML email.
|
|
24
|
-
* @param options Options forwarded to `juice` (e.g. `preserveImportant`, `removeStyleTags`).
|
|
25
|
-
* @returns The HTML with CSS inlined.
|
|
26
|
-
* @throws {EmailError} When `juice` is not installed or inlining fails.
|
|
27
|
-
*/
|
|
28
|
-
declare const inlineCss: (html: string, options?: Record<string, unknown>) => string;
|
|
29
|
-
/**
|
|
30
|
-
* Options for {@link addDarkModeSupport}.
|
|
31
|
-
*/
|
|
32
|
-
interface DarkModeOptions {
|
|
33
|
-
/**
|
|
34
|
-
* Extra CSS to wrap in a `@media (prefers-color-scheme: dark)` block (the dark-mode overrides).
|
|
35
|
-
*/
|
|
36
|
-
styles?: string;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Adds dark-mode hooks to an HTML email: the `color-scheme` / `supported-color-schemes` meta tags and,
|
|
40
|
-
* when provided, a `@media (prefers-color-scheme: dark)` style block.
|
|
41
|
-
*
|
|
42
|
-
* Injected into `<head>` (created after `<html>` if absent, otherwise prepended).
|
|
43
|
-
* @param html The HTML email.
|
|
44
|
-
* @param options Dark-mode options. See {@link DarkModeOptions}.
|
|
45
|
-
* @returns The HTML with dark-mode support added.
|
|
46
|
-
*/
|
|
47
|
-
declare const addDarkModeSupport: (html: string, options?: DarkModeOptions) => string;
|
|
48
|
-
/**
|
|
49
|
-
* Options for {@link injectPreheader}.
|
|
50
|
-
*/
|
|
51
|
-
interface PreheaderOptions {
|
|
52
|
-
/**
|
|
53
|
-
* Append invisible padding characters so the preheader text isn't followed by leaked body content
|
|
54
|
-
* in the inbox preview.
|
|
55
|
-
* @default true
|
|
56
|
-
*/
|
|
57
|
-
spacer?: boolean;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Injects a hidden preheader (inbox preview text) at the start of the HTML body.
|
|
61
|
-
*
|
|
62
|
-
* The preheader is wrapped in a `display:none` element with `mso-hide:all`, followed by zero-width
|
|
63
|
-
* padding so the preview shows only your text. Inserted right after `<body>` (or prepended if no
|
|
64
|
-
* body tag is present).
|
|
65
|
-
* @param html The HTML email.
|
|
66
|
-
* @param preheader The preview text.
|
|
67
|
-
* @param options Injection options. See {@link PreheaderOptions}.
|
|
68
|
-
* @returns The HTML with the preheader injected.
|
|
69
|
-
*/
|
|
70
|
-
declare const injectPreheader: (html: string, preheader: string, options?: PreheaderOptions) => string;
|
|
71
|
-
/**
|
|
72
|
-
* Options for {@link postProcessHtml}. Each step runs only when its option is set; the order is
|
|
73
|
-
* CSS-inline → preheader → dark-mode → CID rewrite.
|
|
74
|
-
*/
|
|
75
|
-
interface PostProcessOptions {
|
|
76
|
-
/**
|
|
77
|
-
* Rewrite `cid:` references using this resolver (see {@link rewriteCidLinks}).
|
|
78
|
-
*/
|
|
79
|
-
cidResolver?: (cid: string) => string | undefined;
|
|
80
|
-
/**
|
|
81
|
-
* Add dark-mode hooks. `true` adds the meta tags only; an object also injects dark CSS.
|
|
82
|
-
*/
|
|
83
|
-
darkMode?: DarkModeOptions | boolean;
|
|
84
|
-
/**
|
|
85
|
-
* Inline CSS via `juice`. `true` uses defaults; an object forwards options to `juice`.
|
|
86
|
-
*/
|
|
87
|
-
inlineCss?: Record<string, unknown> | boolean;
|
|
88
|
-
/**
|
|
89
|
-
* Inject hidden preview text at the top of the body.
|
|
90
|
-
*/
|
|
91
|
-
preheader?: string;
|
|
92
|
-
/**
|
|
93
|
-
* Options for the preheader injection.
|
|
94
|
-
*/
|
|
95
|
-
preheaderOptions?: PreheaderOptions;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Runs an HTML email through the selected post-processing steps.
|
|
99
|
-
*
|
|
100
|
-
* A convenience pipeline over {@link inlineCss}, {@link injectPreheader}, {@link addDarkModeSupport} and
|
|
101
|
-
* {@link rewriteCidLinks}. Only the steps whose options are provided run.
|
|
102
|
-
* @param html The HTML email.
|
|
103
|
-
* @param options Which steps to apply. See {@link PostProcessOptions}.
|
|
104
|
-
* @returns The processed HTML.
|
|
105
|
-
*/
|
|
106
|
-
declare const postProcessHtml: (html: string, options?: PostProcessOptions) => string;
|
|
107
|
-
export { type DarkModeOptions, type PostProcessOptions, type PreheaderOptions, addDarkModeSupport, extractCidReferences, injectPreheader, inlineCss, postProcessHtml, rewriteCidLinks };
|
package/dist/render/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{extractCidReferences as o,rewriteCidLinks as t}from"../packem_shared/extractCidReferences-BuoTREMp.js";import{default as s}from"../packem_shared/inlineCss-BQ7d2Cyz.js";import{addDarkModeSupport as f}from"../packem_shared/addDarkModeSupport-DZYxULjl.js";import{postProcessHtml as a}from"../packem_shared/postProcessHtml-DqKi2Ucg.js";import{injectPreheader as x}from"../packem_shared/injectPreheader-CF9WHZ7J.js";export{f as addDarkModeSupport,o as extractCidReferences,x as injectPreheader,s as inlineCss,a as postProcessHtml,t as rewriteCidLinks};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|