@postalsys/email-text-tools 2.5.0 → 2.6.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/CHANGELOG.md +14 -0
- package/README.md +2 -0
- package/dist/cjs/index.d.ts +3 -1
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/lib/inline-style.d.ts +2 -0
- package/dist/cjs/lib/inline-style.js +42 -0
- package/dist/cjs/lib/mime-html.js +2 -35
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.js +3 -2
- package/dist/esm/lib/inline-style.d.ts +2 -0
- package/dist/esm/lib/inline-style.js +39 -0
- package/dist/esm/lib/mime-html.js +1 -34
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.6.1](https://github.com/postalsys/email-text-tools/compare/v2.6.0...v2.6.1) (2026-10-22)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* update dependencies ([e185bb4](https://github.com/postalsys/email-text-tools/commit/e185bb45fef135b8e996889c29e03fbb458b8fd0))
|
|
9
|
+
|
|
10
|
+
## [2.6.0](https://github.com/postalsys/email-text-tools/compare/v2.5.0...v2.6.0) (2026-10-21)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* export INLINE_STYLE_BLOCK from the package entry ([36b8c30](https://github.com/postalsys/email-text-tools/commit/36b8c305b3841202ae6d7407e80e0c6189d556a6))
|
|
16
|
+
|
|
3
17
|
## [2.5.0](https://github.com/postalsys/email-text-tools/compare/v2.4.26...v2.5.0) (2026-10-19)
|
|
4
18
|
|
|
5
19
|
|
package/README.md
CHANGED
|
@@ -12,6 +12,8 @@ const { mimeHtml, textToHtml } = require('@postalsys/email-text-tools');
|
|
|
12
12
|
|
|
13
13
|
`require()` loads `mimeHtml` (and with it jsdom) only on first access; an ES module import loads it up front.
|
|
14
14
|
|
|
15
|
+
`INLINE_STYLE_BLOCK` is the `<style>` block `mimeHtml()` prepends to a message that only has a text body (font and the colours of nested quotes), for a caller that converts text with `textToHtml()` itself and wants the same styling. Reading it does not load jsdom.
|
|
16
|
+
|
|
15
17
|
## mimeHtml sanitizer policy
|
|
16
18
|
|
|
17
19
|
`mimeHtml()` sanitizes with DOMPurify and additionally removes:
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -3,16 +3,18 @@ import htmlToText from './lib/html-to-text.js';
|
|
|
3
3
|
import inlineHtml from './lib/inline-html.js';
|
|
4
4
|
import inlineText from './lib/inline-text.js';
|
|
5
5
|
import mimeHtml from './lib/mime-html.js';
|
|
6
|
+
import { INLINE_STYLE_BLOCK } from './lib/inline-style.js';
|
|
6
7
|
export type { FormatDateOptions } from './lib/format-date.js';
|
|
7
8
|
export type { InlineAction, MessageAddress, QuotedMessage } from './lib/inline-html.js';
|
|
8
9
|
export type { MimeHtmlAsyncOptions, MimeHtmlMessage } from './lib/mime-html.js';
|
|
9
10
|
export type { WorkerPoolOptions, WorkerPoolStats } from './lib/worker-pool.js';
|
|
10
|
-
export { textToHtml, htmlToText, inlineHtml, inlineText, mimeHtml };
|
|
11
|
+
export { textToHtml, htmlToText, inlineHtml, inlineText, mimeHtml, INLINE_STYLE_BLOCK };
|
|
11
12
|
declare const textTools: {
|
|
12
13
|
textToHtml: typeof textToHtml;
|
|
13
14
|
htmlToText: typeof htmlToText;
|
|
14
15
|
inlineHtml: typeof inlineHtml;
|
|
15
16
|
inlineText: typeof inlineText;
|
|
16
17
|
mimeHtml: typeof mimeHtml;
|
|
18
|
+
INLINE_STYLE_BLOCK: string;
|
|
17
19
|
};
|
|
18
20
|
export default textTools;
|
package/dist/cjs/index.js
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
// require() returns the same object as before the TypeScript build: the five helpers as plain
|
|
6
6
|
// enumerable properties, mimeHtml through a getter. mimeHtml loads jsdom, which costs tens of
|
|
7
7
|
// megabytes of heap, so it is only loaded on first access and callers that only need the other
|
|
8
|
-
// helpers never pay for it.
|
|
8
|
+
// helpers never pay for it. INLINE_STYLE_BLOCK was added after them and comes from a leaf module,
|
|
9
|
+
// so reading it does not load jsdom either.
|
|
9
10
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
11
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
12
|
};
|
|
@@ -14,6 +15,7 @@ const text_to_html_js_1 = __importDefault(require("./lib/text-to-html.js"));
|
|
|
14
15
|
const html_to_text_js_1 = __importDefault(require("./lib/html-to-text.js"));
|
|
15
16
|
const inline_html_js_1 = __importDefault(require("./lib/inline-html.js"));
|
|
16
17
|
const inline_text_js_1 = __importDefault(require("./lib/inline-text.js"));
|
|
18
|
+
const inline_style_js_1 = require("./lib/inline-style.js");
|
|
17
19
|
const textTools = { textToHtml: text_to_html_js_1.default, htmlToText: html_to_text_js_1.default, inlineHtml: inline_html_js_1.default, inlineText: inline_text_js_1.default };
|
|
18
20
|
Object.defineProperty(textTools, 'mimeHtml', {
|
|
19
21
|
enumerable: true,
|
|
@@ -22,6 +24,7 @@ Object.defineProperty(textTools, 'mimeHtml', {
|
|
|
22
24
|
return require('./lib/mime-html.js');
|
|
23
25
|
}
|
|
24
26
|
});
|
|
27
|
+
textTools.INLINE_STYLE_BLOCK = inline_style_js_1.INLINE_STYLE_BLOCK;
|
|
25
28
|
// What TypeScript and Babel generated `import textTools from '...'` code reads, as the
|
|
26
29
|
// declarations promise a default export
|
|
27
30
|
Object.defineProperty(textTools, 'default', { value: textTools, enumerable: false, writable: true, configurable: true });
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/** Base styles mimeHtml() applies to a message that only has a plain text body */
|
|
2
|
+
export declare const INLINE_STYLE_BLOCK = "<style>\n\nbody, td, th, p {\n font-family: sans-serif;\n font-size: 12px;\n}\n\nblockquote {\n border-left-width: 2px;\n border-left-style: solid;\n \n border-left-color: darkblue;\n color: darkblue;\n\n margin: 1rem 0;\n padding-left: 1rem;\n}\n\nblockquote blockquote{\n border-left-color: royalblue;\n color: royalblue;\n}\n\nblockquote blockquote blockquote{\n border-left-color: dodgerblue;\n color: dodgerblue;\n}\n\nblockquote blockquote blockquote blockquote{\n border-left-color: darkblue;\n color: darkblue;\n}\n\n</style>";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// The default <style> block mimeHtml() prepends when a message has only a text body, so quoted
|
|
3
|
+
// text converted by textToHtml() gets its quote colouring. A leaf module, so the package entry can
|
|
4
|
+
// export it without loading jsdom. Named export only: lib/ modules with a default export are
|
|
5
|
+
// rewritten to return it from require().
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.INLINE_STYLE_BLOCK = void 0;
|
|
8
|
+
/** Base styles mimeHtml() applies to a message that only has a plain text body */
|
|
9
|
+
exports.INLINE_STYLE_BLOCK = `<style>
|
|
10
|
+
|
|
11
|
+
body, td, th, p {
|
|
12
|
+
font-family: sans-serif;
|
|
13
|
+
font-size: 12px;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
blockquote {
|
|
17
|
+
border-left-width: 2px;
|
|
18
|
+
border-left-style: solid;
|
|
19
|
+
|
|
20
|
+
border-left-color: darkblue;
|
|
21
|
+
color: darkblue;
|
|
22
|
+
|
|
23
|
+
margin: 1rem 0;
|
|
24
|
+
padding-left: 1rem;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
blockquote blockquote{
|
|
28
|
+
border-left-color: royalblue;
|
|
29
|
+
color: royalblue;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
blockquote blockquote blockquote{
|
|
33
|
+
border-left-color: dodgerblue;
|
|
34
|
+
color: dodgerblue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
blockquote blockquote blockquote blockquote{
|
|
38
|
+
border-left-color: darkblue;
|
|
39
|
+
color: darkblue;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
</style>`;
|
|
@@ -11,6 +11,7 @@ const he_1 = __importDefault(require("he"));
|
|
|
11
11
|
const node_worker_threads_1 = require("node:worker_threads");
|
|
12
12
|
const worker_pool_js_1 = __importDefault(require("./worker-pool.js"));
|
|
13
13
|
const html_guard_js_1 = require("./html-guard.js");
|
|
14
|
+
const inline_style_js_1 = require("./inline-style.js");
|
|
14
15
|
const commonjs_cjs_1 = require("./commonjs.cjs");
|
|
15
16
|
const text_to_html_js_1 = __importDefault(require("./text-to-html.js"));
|
|
16
17
|
const FORBID_TAGS = [
|
|
@@ -161,40 +162,6 @@ async function juiceWithTimeout(html, options = {}) {
|
|
|
161
162
|
worker.postMessage(html);
|
|
162
163
|
});
|
|
163
164
|
}
|
|
164
|
-
const INLINE_STYLE_BLOCK = `<style>
|
|
165
|
-
|
|
166
|
-
body, td, th, p {
|
|
167
|
-
font-family: sans-serif;
|
|
168
|
-
font-size: 12px;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
blockquote {
|
|
172
|
-
border-left-width: 2px;
|
|
173
|
-
border-left-style: solid;
|
|
174
|
-
|
|
175
|
-
border-left-color: darkblue;
|
|
176
|
-
color: darkblue;
|
|
177
|
-
|
|
178
|
-
margin: 1rem 0;
|
|
179
|
-
padding-left: 1rem;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
blockquote blockquote{
|
|
183
|
-
border-left-color: royalblue;
|
|
184
|
-
color: royalblue;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
blockquote blockquote blockquote{
|
|
188
|
-
border-left-color: dodgerblue;
|
|
189
|
-
color: dodgerblue;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
blockquote blockquote blockquote blockquote{
|
|
193
|
-
border-left-color: darkblue;
|
|
194
|
-
color: darkblue;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
</style>`;
|
|
198
165
|
// Only this much <style> text is kept per message, the rest is dropped. juice and the selector
|
|
199
166
|
// filter below scale with it, and no legitimate email needs more.
|
|
200
167
|
const MAX_STYLE_TEXT = 256 * 1024;
|
|
@@ -313,7 +280,7 @@ function prepareHtml(message) {
|
|
|
313
280
|
if (!source && message.text) {
|
|
314
281
|
source = (0, text_to_html_js_1.default)(message.text) || '';
|
|
315
282
|
if (source) {
|
|
316
|
-
source = INLINE_STYLE_BLOCK + source;
|
|
283
|
+
source = inline_style_js_1.INLINE_STYLE_BLOCK + source;
|
|
317
284
|
}
|
|
318
285
|
}
|
|
319
286
|
const html = (source || '').toString().replace(/^"data:[^"]+"/g, '');
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -3,16 +3,18 @@ import htmlToText from './lib/html-to-text.js';
|
|
|
3
3
|
import inlineHtml from './lib/inline-html.js';
|
|
4
4
|
import inlineText from './lib/inline-text.js';
|
|
5
5
|
import mimeHtml from './lib/mime-html.js';
|
|
6
|
+
import { INLINE_STYLE_BLOCK } from './lib/inline-style.js';
|
|
6
7
|
export type { FormatDateOptions } from './lib/format-date.js';
|
|
7
8
|
export type { InlineAction, MessageAddress, QuotedMessage } from './lib/inline-html.js';
|
|
8
9
|
export type { MimeHtmlAsyncOptions, MimeHtmlMessage } from './lib/mime-html.js';
|
|
9
10
|
export type { WorkerPoolOptions, WorkerPoolStats } from './lib/worker-pool.js';
|
|
10
|
-
export { textToHtml, htmlToText, inlineHtml, inlineText, mimeHtml };
|
|
11
|
+
export { textToHtml, htmlToText, inlineHtml, inlineText, mimeHtml, INLINE_STYLE_BLOCK };
|
|
11
12
|
declare const textTools: {
|
|
12
13
|
textToHtml: typeof textToHtml;
|
|
13
14
|
htmlToText: typeof htmlToText;
|
|
14
15
|
inlineHtml: typeof inlineHtml;
|
|
15
16
|
inlineText: typeof inlineText;
|
|
16
17
|
mimeHtml: typeof mimeHtml;
|
|
18
|
+
INLINE_STYLE_BLOCK: string;
|
|
17
19
|
};
|
|
18
20
|
export default textTools;
|
package/dist/esm/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import htmlToText from './lib/html-to-text.js';
|
|
|
7
7
|
import inlineHtml from './lib/inline-html.js';
|
|
8
8
|
import inlineText from './lib/inline-text.js';
|
|
9
9
|
import mimeHtml from './lib/mime-html.js';
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
import { INLINE_STYLE_BLOCK } from './lib/inline-style.js';
|
|
11
|
+
export { textToHtml, htmlToText, inlineHtml, inlineText, mimeHtml, INLINE_STYLE_BLOCK };
|
|
12
|
+
const textTools = { textToHtml, htmlToText, inlineHtml, inlineText, mimeHtml, INLINE_STYLE_BLOCK };
|
|
12
13
|
export default textTools;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/** Base styles mimeHtml() applies to a message that only has a plain text body */
|
|
2
|
+
export declare const INLINE_STYLE_BLOCK = "<style>\n\nbody, td, th, p {\n font-family: sans-serif;\n font-size: 12px;\n}\n\nblockquote {\n border-left-width: 2px;\n border-left-style: solid;\n \n border-left-color: darkblue;\n color: darkblue;\n\n margin: 1rem 0;\n padding-left: 1rem;\n}\n\nblockquote blockquote{\n border-left-color: royalblue;\n color: royalblue;\n}\n\nblockquote blockquote blockquote{\n border-left-color: dodgerblue;\n color: dodgerblue;\n}\n\nblockquote blockquote blockquote blockquote{\n border-left-color: darkblue;\n color: darkblue;\n}\n\n</style>";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// The default <style> block mimeHtml() prepends when a message has only a text body, so quoted
|
|
2
|
+
// text converted by textToHtml() gets its quote colouring. A leaf module, so the package entry can
|
|
3
|
+
// export it without loading jsdom. Named export only: lib/ modules with a default export are
|
|
4
|
+
// rewritten to return it from require().
|
|
5
|
+
/** Base styles mimeHtml() applies to a message that only has a plain text body */
|
|
6
|
+
export const INLINE_STYLE_BLOCK = `<style>
|
|
7
|
+
|
|
8
|
+
body, td, th, p {
|
|
9
|
+
font-family: sans-serif;
|
|
10
|
+
font-size: 12px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
blockquote {
|
|
14
|
+
border-left-width: 2px;
|
|
15
|
+
border-left-style: solid;
|
|
16
|
+
|
|
17
|
+
border-left-color: darkblue;
|
|
18
|
+
color: darkblue;
|
|
19
|
+
|
|
20
|
+
margin: 1rem 0;
|
|
21
|
+
padding-left: 1rem;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
blockquote blockquote{
|
|
25
|
+
border-left-color: royalblue;
|
|
26
|
+
color: royalblue;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
blockquote blockquote blockquote{
|
|
30
|
+
border-left-color: dodgerblue;
|
|
31
|
+
color: dodgerblue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
blockquote blockquote blockquote blockquote{
|
|
35
|
+
border-left-color: darkblue;
|
|
36
|
+
color: darkblue;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
</style>`;
|
|
@@ -6,6 +6,7 @@ import he from 'he';
|
|
|
6
6
|
import { Worker } from 'node:worker_threads';
|
|
7
7
|
import WorkerPool from './worker-pool.js';
|
|
8
8
|
import { MAX_NESTING_DEPTH, exceedsNestingDepth, fallbackText } from './html-guard.js';
|
|
9
|
+
import { INLINE_STYLE_BLOCK } from './inline-style.js';
|
|
9
10
|
import { JUICE_WORKER_PATH } from './commonjs.cjs';
|
|
10
11
|
import textToHtml from './text-to-html.js';
|
|
11
12
|
const FORBID_TAGS = [
|
|
@@ -156,40 +157,6 @@ async function juiceWithTimeout(html, options = {}) {
|
|
|
156
157
|
worker.postMessage(html);
|
|
157
158
|
});
|
|
158
159
|
}
|
|
159
|
-
const INLINE_STYLE_BLOCK = `<style>
|
|
160
|
-
|
|
161
|
-
body, td, th, p {
|
|
162
|
-
font-family: sans-serif;
|
|
163
|
-
font-size: 12px;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
blockquote {
|
|
167
|
-
border-left-width: 2px;
|
|
168
|
-
border-left-style: solid;
|
|
169
|
-
|
|
170
|
-
border-left-color: darkblue;
|
|
171
|
-
color: darkblue;
|
|
172
|
-
|
|
173
|
-
margin: 1rem 0;
|
|
174
|
-
padding-left: 1rem;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
blockquote blockquote{
|
|
178
|
-
border-left-color: royalblue;
|
|
179
|
-
color: royalblue;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
blockquote blockquote blockquote{
|
|
183
|
-
border-left-color: dodgerblue;
|
|
184
|
-
color: dodgerblue;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
blockquote blockquote blockquote blockquote{
|
|
188
|
-
border-left-color: darkblue;
|
|
189
|
-
color: darkblue;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
</style>`;
|
|
193
160
|
// Only this much <style> text is kept per message, the rest is dropped. juice and the selector
|
|
194
161
|
// filter below scale with it, and no legitimate email needs more.
|
|
195
162
|
const MAX_STYLE_TEXT = 256 * 1024;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postalsys/email-text-tools",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"description": "Email text tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -90,10 +90,10 @@
|
|
|
90
90
|
"globals": "17.13.0",
|
|
91
91
|
"prettier": "3.9.10",
|
|
92
92
|
"typescript": "6.0.3",
|
|
93
|
-
"typescript-eslint": "8.
|
|
93
|
+
"typescript-eslint": "8.72.0"
|
|
94
94
|
},
|
|
95
95
|
"dependencies": {
|
|
96
|
-
"@postalsys/email-content": "0.1.
|
|
96
|
+
"@postalsys/email-content": "0.1.18",
|
|
97
97
|
"dompurify": "3.4.17",
|
|
98
98
|
"he": "1.2.0",
|
|
99
99
|
"html-to-text": "10.0.1",
|