@react-email/render 1.2.0 → 1.2.2
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/dist/browser/index.js +4 -2
- package/dist/browser/index.mjs +4 -2
- package/dist/edge/index.d.mts +40 -0
- package/dist/edge/index.d.ts +40 -0
- package/dist/edge/index.js +241 -0
- package/dist/edge/index.mjs +205 -0
- package/package.json +26 -6
package/dist/browser/index.js
CHANGED
|
@@ -159,8 +159,7 @@ function toPlainText(html2, options) {
|
|
|
159
159
|
}, options));
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
// src/
|
|
163
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
162
|
+
// src/shared/read-stream.browser.ts
|
|
164
163
|
var decoder = new TextDecoder("utf-8");
|
|
165
164
|
var readStream = (stream) => __async(void 0, null, function* () {
|
|
166
165
|
const chunks = [];
|
|
@@ -189,6 +188,9 @@ var readStream = (stream) => __async(void 0, null, function* () {
|
|
|
189
188
|
});
|
|
190
189
|
return decoder.decode(mergedChunks);
|
|
191
190
|
});
|
|
191
|
+
|
|
192
|
+
// src/browser/render.tsx
|
|
193
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
192
194
|
var render = (node, options) => __async(void 0, null, function* () {
|
|
193
195
|
const suspendedElement = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Suspense, { children: node });
|
|
194
196
|
const reactDOMServer = yield import("react-dom/server.browser").then(
|
package/dist/browser/index.mjs
CHANGED
|
@@ -124,8 +124,7 @@ function toPlainText(html2, options) {
|
|
|
124
124
|
}, options));
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
// src/
|
|
128
|
-
import { jsx } from "react/jsx-runtime";
|
|
127
|
+
// src/shared/read-stream.browser.ts
|
|
129
128
|
var decoder = new TextDecoder("utf-8");
|
|
130
129
|
var readStream = (stream) => __async(void 0, null, function* () {
|
|
131
130
|
const chunks = [];
|
|
@@ -154,6 +153,9 @@ var readStream = (stream) => __async(void 0, null, function* () {
|
|
|
154
153
|
});
|
|
155
154
|
return decoder.decode(mergedChunks);
|
|
156
155
|
});
|
|
156
|
+
|
|
157
|
+
// src/browser/render.tsx
|
|
158
|
+
import { jsx } from "react/jsx-runtime";
|
|
157
159
|
var render = (node, options) => __async(void 0, null, function* () {
|
|
158
160
|
const suspendedElement = /* @__PURE__ */ jsx(Suspense, { children: node });
|
|
159
161
|
const reactDOMServer = yield import("react-dom/server.browser").then(
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { HtmlToTextOptions, SelectorDefinition } from 'html-to-text';
|
|
2
|
+
import { Options as Options$1 } from 'prettier';
|
|
3
|
+
|
|
4
|
+
type Options = {
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated use {@link pretty} instead
|
|
7
|
+
*/
|
|
8
|
+
pretty?: boolean;
|
|
9
|
+
} & ({
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated use {@link toPlainText} instead
|
|
12
|
+
*/
|
|
13
|
+
plainText?: false;
|
|
14
|
+
} | {
|
|
15
|
+
/**
|
|
16
|
+
* @deprecated use {@link toPlainText} instead
|
|
17
|
+
*/
|
|
18
|
+
plainText?: true;
|
|
19
|
+
/**
|
|
20
|
+
* These are options you can pass down directly to the library we use for
|
|
21
|
+
* converting the rendered email's HTML into plain text.
|
|
22
|
+
*
|
|
23
|
+
* @see https://github.com/html-to-text/node-html-to-text
|
|
24
|
+
*/
|
|
25
|
+
htmlToTextOptions?: HtmlToTextOptions;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
declare const pretty: (str: string, options?: Options$1) => Promise<string>;
|
|
29
|
+
|
|
30
|
+
declare const plainTextSelectors: SelectorDefinition[];
|
|
31
|
+
declare function toPlainText(html: string, options?: HtmlToTextOptions): string;
|
|
32
|
+
|
|
33
|
+
declare const render: (element: React.ReactElement, options?: Options) => Promise<string>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated use {@link render}
|
|
37
|
+
*/
|
|
38
|
+
declare const renderAsync: (element: React.ReactElement, options?: Options) => Promise<string>;
|
|
39
|
+
|
|
40
|
+
export { type Options, plainTextSelectors, pretty, render, renderAsync, toPlainText };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { HtmlToTextOptions, SelectorDefinition } from 'html-to-text';
|
|
2
|
+
import { Options as Options$1 } from 'prettier';
|
|
3
|
+
|
|
4
|
+
type Options = {
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated use {@link pretty} instead
|
|
7
|
+
*/
|
|
8
|
+
pretty?: boolean;
|
|
9
|
+
} & ({
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated use {@link toPlainText} instead
|
|
12
|
+
*/
|
|
13
|
+
plainText?: false;
|
|
14
|
+
} | {
|
|
15
|
+
/**
|
|
16
|
+
* @deprecated use {@link toPlainText} instead
|
|
17
|
+
*/
|
|
18
|
+
plainText?: true;
|
|
19
|
+
/**
|
|
20
|
+
* These are options you can pass down directly to the library we use for
|
|
21
|
+
* converting the rendered email's HTML into plain text.
|
|
22
|
+
*
|
|
23
|
+
* @see https://github.com/html-to-text/node-html-to-text
|
|
24
|
+
*/
|
|
25
|
+
htmlToTextOptions?: HtmlToTextOptions;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
declare const pretty: (str: string, options?: Options$1) => Promise<string>;
|
|
29
|
+
|
|
30
|
+
declare const plainTextSelectors: SelectorDefinition[];
|
|
31
|
+
declare function toPlainText(html: string, options?: HtmlToTextOptions): string;
|
|
32
|
+
|
|
33
|
+
declare const render: (element: React.ReactElement, options?: Options) => Promise<string>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated use {@link render}
|
|
37
|
+
*/
|
|
38
|
+
declare const renderAsync: (element: React.ReactElement, options?: Options) => Promise<string>;
|
|
39
|
+
|
|
40
|
+
export { type Options, plainTextSelectors, pretty, render, renderAsync, toPlainText };
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __defProps = Object.defineProperties;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
9
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
10
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
12
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
13
|
+
var __spreadValues = (a, b) => {
|
|
14
|
+
for (var prop in b || (b = {}))
|
|
15
|
+
if (__hasOwnProp.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
if (__getOwnPropSymbols)
|
|
18
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
19
|
+
if (__propIsEnum.call(b, prop))
|
|
20
|
+
__defNormalProp(a, prop, b[prop]);
|
|
21
|
+
}
|
|
22
|
+
return a;
|
|
23
|
+
};
|
|
24
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
25
|
+
var __export = (target, all) => {
|
|
26
|
+
for (var name in all)
|
|
27
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
28
|
+
};
|
|
29
|
+
var __copyProps = (to, from, except, desc) => {
|
|
30
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
31
|
+
for (let key of __getOwnPropNames(from))
|
|
32
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
33
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
34
|
+
}
|
|
35
|
+
return to;
|
|
36
|
+
};
|
|
37
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
38
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
39
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
40
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
41
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
42
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
43
|
+
mod
|
|
44
|
+
));
|
|
45
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
46
|
+
var __async = (__this, __arguments, generator) => {
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
var fulfilled = (value) => {
|
|
49
|
+
try {
|
|
50
|
+
step(generator.next(value));
|
|
51
|
+
} catch (e) {
|
|
52
|
+
reject(e);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var rejected = (value) => {
|
|
56
|
+
try {
|
|
57
|
+
step(generator.throw(value));
|
|
58
|
+
} catch (e) {
|
|
59
|
+
reject(e);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
63
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// src/edge/index.ts
|
|
68
|
+
var index_exports = {};
|
|
69
|
+
__export(index_exports, {
|
|
70
|
+
plainTextSelectors: () => plainTextSelectors,
|
|
71
|
+
pretty: () => pretty,
|
|
72
|
+
render: () => render,
|
|
73
|
+
renderAsync: () => renderAsync,
|
|
74
|
+
toPlainText: () => toPlainText
|
|
75
|
+
});
|
|
76
|
+
module.exports = __toCommonJS(index_exports);
|
|
77
|
+
|
|
78
|
+
// src/edge/render.tsx
|
|
79
|
+
var import_react = require("react");
|
|
80
|
+
|
|
81
|
+
// src/shared/utils/pretty.ts
|
|
82
|
+
var html = __toESM(require("prettier/plugins/html"));
|
|
83
|
+
var import_standalone = require("prettier/standalone");
|
|
84
|
+
function recursivelyMapDoc(doc, callback) {
|
|
85
|
+
if (Array.isArray(doc)) {
|
|
86
|
+
return doc.map((innerDoc) => recursivelyMapDoc(innerDoc, callback));
|
|
87
|
+
}
|
|
88
|
+
if (typeof doc === "object") {
|
|
89
|
+
if (doc.type === "group") {
|
|
90
|
+
return __spreadProps(__spreadValues({}, doc), {
|
|
91
|
+
contents: recursivelyMapDoc(doc.contents, callback),
|
|
92
|
+
expandedStates: recursivelyMapDoc(
|
|
93
|
+
doc.expandedStates,
|
|
94
|
+
callback
|
|
95
|
+
)
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if ("contents" in doc) {
|
|
99
|
+
return __spreadProps(__spreadValues({}, doc), {
|
|
100
|
+
contents: recursivelyMapDoc(doc.contents, callback)
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if ("parts" in doc) {
|
|
104
|
+
return __spreadProps(__spreadValues({}, doc), {
|
|
105
|
+
parts: recursivelyMapDoc(doc.parts, callback)
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
if (doc.type === "if-break") {
|
|
109
|
+
return __spreadProps(__spreadValues({}, doc), {
|
|
110
|
+
breakContents: recursivelyMapDoc(doc.breakContents, callback),
|
|
111
|
+
flatContents: recursivelyMapDoc(doc.flatContents, callback)
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return callback(doc);
|
|
116
|
+
}
|
|
117
|
+
var modifiedHtml = __spreadValues({}, html);
|
|
118
|
+
if (modifiedHtml.printers) {
|
|
119
|
+
const previousPrint = modifiedHtml.printers.html.print;
|
|
120
|
+
modifiedHtml.printers.html.print = (path, options, print, args) => {
|
|
121
|
+
const node = path.getNode();
|
|
122
|
+
const rawPrintingResult = previousPrint(path, options, print, args);
|
|
123
|
+
if (node.type === "ieConditionalComment") {
|
|
124
|
+
const printingResult = recursivelyMapDoc(rawPrintingResult, (doc) => {
|
|
125
|
+
if (typeof doc === "object" && doc.type === "line") {
|
|
126
|
+
return doc.soft ? "" : " ";
|
|
127
|
+
}
|
|
128
|
+
return doc;
|
|
129
|
+
});
|
|
130
|
+
return printingResult;
|
|
131
|
+
}
|
|
132
|
+
return rawPrintingResult;
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
var defaults = {
|
|
136
|
+
endOfLine: "lf",
|
|
137
|
+
tabWidth: 2,
|
|
138
|
+
plugins: [modifiedHtml],
|
|
139
|
+
bracketSameLine: true,
|
|
140
|
+
parser: "html"
|
|
141
|
+
};
|
|
142
|
+
var pretty = (str, options = {}) => {
|
|
143
|
+
return (0, import_standalone.format)(str.replaceAll("\0", ""), __spreadValues(__spreadValues({}, defaults), options));
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// src/shared/utils/to-plain-text.ts
|
|
147
|
+
var import_html_to_text = require("html-to-text");
|
|
148
|
+
var plainTextSelectors = [
|
|
149
|
+
{ selector: "img", format: "skip" },
|
|
150
|
+
{ selector: "[data-skip-in-text=true]", format: "skip" },
|
|
151
|
+
{
|
|
152
|
+
selector: "a",
|
|
153
|
+
options: { linkBrackets: false }
|
|
154
|
+
}
|
|
155
|
+
];
|
|
156
|
+
function toPlainText(html2, options) {
|
|
157
|
+
return (0, import_html_to_text.convert)(html2, __spreadValues({
|
|
158
|
+
selectors: plainTextSelectors
|
|
159
|
+
}, options));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// src/shared/read-stream.browser.ts
|
|
163
|
+
var decoder = new TextDecoder("utf-8");
|
|
164
|
+
var readStream = (stream) => __async(void 0, null, function* () {
|
|
165
|
+
const chunks = [];
|
|
166
|
+
const writableStream = new WritableStream({
|
|
167
|
+
write(chunk) {
|
|
168
|
+
chunks.push(chunk);
|
|
169
|
+
},
|
|
170
|
+
abort(reason) {
|
|
171
|
+
throw new Error("Stream aborted", {
|
|
172
|
+
cause: {
|
|
173
|
+
reason
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
yield stream.pipeTo(writableStream);
|
|
179
|
+
let length = 0;
|
|
180
|
+
chunks.forEach((item) => {
|
|
181
|
+
length += item.length;
|
|
182
|
+
});
|
|
183
|
+
const mergedChunks = new Uint8Array(length);
|
|
184
|
+
let offset = 0;
|
|
185
|
+
chunks.forEach((item) => {
|
|
186
|
+
mergedChunks.set(item, offset);
|
|
187
|
+
offset += item.length;
|
|
188
|
+
});
|
|
189
|
+
return decoder.decode(mergedChunks);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// src/edge/import-react-dom.tsx
|
|
193
|
+
var importReactDom = () => {
|
|
194
|
+
return import("react-dom/server.edge").catch(
|
|
195
|
+
() => (
|
|
196
|
+
// This ensures that we still have compatibility with React 18,
|
|
197
|
+
// which doesn't have the `.edge` export.
|
|
198
|
+
import("react-dom/server")
|
|
199
|
+
)
|
|
200
|
+
);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// src/edge/render.tsx
|
|
204
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
205
|
+
var render = (element, options) => __async(void 0, null, function* () {
|
|
206
|
+
const suspendedElement = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Suspense, { children: element });
|
|
207
|
+
const reactDOMServer = yield importReactDom().then(
|
|
208
|
+
// This is because react-dom/server is CJS
|
|
209
|
+
(m) => m.default
|
|
210
|
+
);
|
|
211
|
+
const html2 = yield new Promise((resolve, reject) => {
|
|
212
|
+
reactDOMServer.renderToReadableStream(suspendedElement, {
|
|
213
|
+
onError(error) {
|
|
214
|
+
reject(error);
|
|
215
|
+
},
|
|
216
|
+
progressiveChunkSize: Number.POSITIVE_INFINITY
|
|
217
|
+
}).then(readStream).then(resolve).catch(reject);
|
|
218
|
+
});
|
|
219
|
+
if (options == null ? void 0 : options.plainText) {
|
|
220
|
+
return toPlainText(html2, options.htmlToTextOptions);
|
|
221
|
+
}
|
|
222
|
+
const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
|
|
223
|
+
const document = `${doctype}${html2.replace(/<!DOCTYPE.*?>/, "")}`;
|
|
224
|
+
if (options == null ? void 0 : options.pretty) {
|
|
225
|
+
return pretty(document);
|
|
226
|
+
}
|
|
227
|
+
return document;
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// src/edge/index.ts
|
|
231
|
+
var renderAsync = (element, options) => {
|
|
232
|
+
return render(element, options);
|
|
233
|
+
};
|
|
234
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
235
|
+
0 && (module.exports = {
|
|
236
|
+
plainTextSelectors,
|
|
237
|
+
pretty,
|
|
238
|
+
render,
|
|
239
|
+
renderAsync,
|
|
240
|
+
toPlainText
|
|
241
|
+
});
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __async = (__this, __arguments, generator) => {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
var fulfilled = (value) => {
|
|
23
|
+
try {
|
|
24
|
+
step(generator.next(value));
|
|
25
|
+
} catch (e) {
|
|
26
|
+
reject(e);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var rejected = (value) => {
|
|
30
|
+
try {
|
|
31
|
+
step(generator.throw(value));
|
|
32
|
+
} catch (e) {
|
|
33
|
+
reject(e);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
37
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// src/edge/render.tsx
|
|
42
|
+
import { Suspense } from "react";
|
|
43
|
+
|
|
44
|
+
// src/shared/utils/pretty.ts
|
|
45
|
+
import * as html from "prettier/plugins/html";
|
|
46
|
+
import { format } from "prettier/standalone";
|
|
47
|
+
function recursivelyMapDoc(doc, callback) {
|
|
48
|
+
if (Array.isArray(doc)) {
|
|
49
|
+
return doc.map((innerDoc) => recursivelyMapDoc(innerDoc, callback));
|
|
50
|
+
}
|
|
51
|
+
if (typeof doc === "object") {
|
|
52
|
+
if (doc.type === "group") {
|
|
53
|
+
return __spreadProps(__spreadValues({}, doc), {
|
|
54
|
+
contents: recursivelyMapDoc(doc.contents, callback),
|
|
55
|
+
expandedStates: recursivelyMapDoc(
|
|
56
|
+
doc.expandedStates,
|
|
57
|
+
callback
|
|
58
|
+
)
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if ("contents" in doc) {
|
|
62
|
+
return __spreadProps(__spreadValues({}, doc), {
|
|
63
|
+
contents: recursivelyMapDoc(doc.contents, callback)
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if ("parts" in doc) {
|
|
67
|
+
return __spreadProps(__spreadValues({}, doc), {
|
|
68
|
+
parts: recursivelyMapDoc(doc.parts, callback)
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (doc.type === "if-break") {
|
|
72
|
+
return __spreadProps(__spreadValues({}, doc), {
|
|
73
|
+
breakContents: recursivelyMapDoc(doc.breakContents, callback),
|
|
74
|
+
flatContents: recursivelyMapDoc(doc.flatContents, callback)
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return callback(doc);
|
|
79
|
+
}
|
|
80
|
+
var modifiedHtml = __spreadValues({}, html);
|
|
81
|
+
if (modifiedHtml.printers) {
|
|
82
|
+
const previousPrint = modifiedHtml.printers.html.print;
|
|
83
|
+
modifiedHtml.printers.html.print = (path, options, print, args) => {
|
|
84
|
+
const node = path.getNode();
|
|
85
|
+
const rawPrintingResult = previousPrint(path, options, print, args);
|
|
86
|
+
if (node.type === "ieConditionalComment") {
|
|
87
|
+
const printingResult = recursivelyMapDoc(rawPrintingResult, (doc) => {
|
|
88
|
+
if (typeof doc === "object" && doc.type === "line") {
|
|
89
|
+
return doc.soft ? "" : " ";
|
|
90
|
+
}
|
|
91
|
+
return doc;
|
|
92
|
+
});
|
|
93
|
+
return printingResult;
|
|
94
|
+
}
|
|
95
|
+
return rawPrintingResult;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
var defaults = {
|
|
99
|
+
endOfLine: "lf",
|
|
100
|
+
tabWidth: 2,
|
|
101
|
+
plugins: [modifiedHtml],
|
|
102
|
+
bracketSameLine: true,
|
|
103
|
+
parser: "html"
|
|
104
|
+
};
|
|
105
|
+
var pretty = (str, options = {}) => {
|
|
106
|
+
return format(str.replaceAll("\0", ""), __spreadValues(__spreadValues({}, defaults), options));
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// src/shared/utils/to-plain-text.ts
|
|
110
|
+
import {
|
|
111
|
+
convert
|
|
112
|
+
} from "html-to-text";
|
|
113
|
+
var plainTextSelectors = [
|
|
114
|
+
{ selector: "img", format: "skip" },
|
|
115
|
+
{ selector: "[data-skip-in-text=true]", format: "skip" },
|
|
116
|
+
{
|
|
117
|
+
selector: "a",
|
|
118
|
+
options: { linkBrackets: false }
|
|
119
|
+
}
|
|
120
|
+
];
|
|
121
|
+
function toPlainText(html2, options) {
|
|
122
|
+
return convert(html2, __spreadValues({
|
|
123
|
+
selectors: plainTextSelectors
|
|
124
|
+
}, options));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/shared/read-stream.browser.ts
|
|
128
|
+
var decoder = new TextDecoder("utf-8");
|
|
129
|
+
var readStream = (stream) => __async(void 0, null, function* () {
|
|
130
|
+
const chunks = [];
|
|
131
|
+
const writableStream = new WritableStream({
|
|
132
|
+
write(chunk) {
|
|
133
|
+
chunks.push(chunk);
|
|
134
|
+
},
|
|
135
|
+
abort(reason) {
|
|
136
|
+
throw new Error("Stream aborted", {
|
|
137
|
+
cause: {
|
|
138
|
+
reason
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
yield stream.pipeTo(writableStream);
|
|
144
|
+
let length = 0;
|
|
145
|
+
chunks.forEach((item) => {
|
|
146
|
+
length += item.length;
|
|
147
|
+
});
|
|
148
|
+
const mergedChunks = new Uint8Array(length);
|
|
149
|
+
let offset = 0;
|
|
150
|
+
chunks.forEach((item) => {
|
|
151
|
+
mergedChunks.set(item, offset);
|
|
152
|
+
offset += item.length;
|
|
153
|
+
});
|
|
154
|
+
return decoder.decode(mergedChunks);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// src/edge/import-react-dom.tsx
|
|
158
|
+
var importReactDom = () => {
|
|
159
|
+
return import("react-dom/server.edge").catch(
|
|
160
|
+
() => (
|
|
161
|
+
// This ensures that we still have compatibility with React 18,
|
|
162
|
+
// which doesn't have the `.edge` export.
|
|
163
|
+
import("react-dom/server")
|
|
164
|
+
)
|
|
165
|
+
);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// src/edge/render.tsx
|
|
169
|
+
import { jsx } from "react/jsx-runtime";
|
|
170
|
+
var render = (element, options) => __async(void 0, null, function* () {
|
|
171
|
+
const suspendedElement = /* @__PURE__ */ jsx(Suspense, { children: element });
|
|
172
|
+
const reactDOMServer = yield importReactDom().then(
|
|
173
|
+
// This is because react-dom/server is CJS
|
|
174
|
+
(m) => m.default
|
|
175
|
+
);
|
|
176
|
+
const html2 = yield new Promise((resolve, reject) => {
|
|
177
|
+
reactDOMServer.renderToReadableStream(suspendedElement, {
|
|
178
|
+
onError(error) {
|
|
179
|
+
reject(error);
|
|
180
|
+
},
|
|
181
|
+
progressiveChunkSize: Number.POSITIVE_INFINITY
|
|
182
|
+
}).then(readStream).then(resolve).catch(reject);
|
|
183
|
+
});
|
|
184
|
+
if (options == null ? void 0 : options.plainText) {
|
|
185
|
+
return toPlainText(html2, options.htmlToTextOptions);
|
|
186
|
+
}
|
|
187
|
+
const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
|
|
188
|
+
const document = `${doctype}${html2.replace(/<!DOCTYPE.*?>/, "")}`;
|
|
189
|
+
if (options == null ? void 0 : options.pretty) {
|
|
190
|
+
return pretty(document);
|
|
191
|
+
}
|
|
192
|
+
return document;
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// src/edge/index.ts
|
|
196
|
+
var renderAsync = (element, options) => {
|
|
197
|
+
return render(element, options);
|
|
198
|
+
};
|
|
199
|
+
export {
|
|
200
|
+
plainTextSelectors,
|
|
201
|
+
pretty,
|
|
202
|
+
render,
|
|
203
|
+
renderAsync,
|
|
204
|
+
toPlainText
|
|
205
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-email/render",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Transform React components into HTML email templates",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/browser/index.js",
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
],
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
|
-
"
|
|
14
|
+
"workerd": {
|
|
15
15
|
"import": {
|
|
16
|
-
"types": "./dist/
|
|
17
|
-
"default": "./dist/
|
|
16
|
+
"types": "./dist/edge/index.d.mts",
|
|
17
|
+
"default": "./dist/edge/index.mjs"
|
|
18
18
|
},
|
|
19
19
|
"require": {
|
|
20
|
-
"types": "./dist/
|
|
21
|
-
"default": "./dist/
|
|
20
|
+
"types": "./dist/edge/index.d.ts",
|
|
21
|
+
"default": "./dist/edge/index.js"
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"deno": {
|
|
@@ -41,6 +41,26 @@
|
|
|
41
41
|
"default": "./dist/browser/index.js"
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
|
+
"edge-light": {
|
|
45
|
+
"import": {
|
|
46
|
+
"types": "./dist/edge/index.d.mts",
|
|
47
|
+
"default": "./dist/edge/index.mjs"
|
|
48
|
+
},
|
|
49
|
+
"require": {
|
|
50
|
+
"types": "./dist/edge/index.d.ts",
|
|
51
|
+
"default": "./dist/edge/index.js"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"node": {
|
|
55
|
+
"import": {
|
|
56
|
+
"types": "./dist/node/index.d.mts",
|
|
57
|
+
"default": "./dist/node/index.mjs"
|
|
58
|
+
},
|
|
59
|
+
"require": {
|
|
60
|
+
"types": "./dist/node/index.d.ts",
|
|
61
|
+
"default": "./dist/node/index.js"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
44
64
|
"browser": {
|
|
45
65
|
"import": {
|
|
46
66
|
"types": "./dist/browser/index.d.mts",
|