@react-email/render 1.1.4 → 1.2.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.
@@ -7,8 +7,14 @@ type Options = {
7
7
  */
8
8
  pretty?: boolean;
9
9
  } & ({
10
+ /**
11
+ * @deprecated use {@link toPlainText} instead
12
+ */
10
13
  plainText?: false;
11
14
  } | {
15
+ /**
16
+ * @deprecated use {@link toPlainText} instead
17
+ */
12
18
  plainText?: true;
13
19
  /**
14
20
  * These are options you can pass down directly to the library we use for
@@ -19,10 +25,11 @@ type Options = {
19
25
  htmlToTextOptions?: HtmlToTextOptions;
20
26
  });
21
27
 
22
- declare const plainTextSelectors: SelectorDefinition[];
23
-
24
28
  declare const pretty: (str: string, options?: Options$1) => Promise<string>;
25
29
 
30
+ declare const plainTextSelectors: SelectorDefinition[];
31
+ declare function toPlainText(html: string, options?: HtmlToTextOptions): string;
32
+
26
33
  declare const render: (node: React.ReactNode, options?: Options) => Promise<string>;
27
34
 
28
35
  /**
@@ -30,4 +37,4 @@ declare const render: (node: React.ReactNode, options?: Options) => Promise<stri
30
37
  */
31
38
  declare const renderAsync: (element: React.ReactElement, options?: Options) => Promise<string>;
32
39
 
33
- export { type Options, plainTextSelectors, pretty, render, renderAsync };
40
+ export { type Options, plainTextSelectors, pretty, render, renderAsync, toPlainText };
@@ -7,8 +7,14 @@ type Options = {
7
7
  */
8
8
  pretty?: boolean;
9
9
  } & ({
10
+ /**
11
+ * @deprecated use {@link toPlainText} instead
12
+ */
10
13
  plainText?: false;
11
14
  } | {
15
+ /**
16
+ * @deprecated use {@link toPlainText} instead
17
+ */
12
18
  plainText?: true;
13
19
  /**
14
20
  * These are options you can pass down directly to the library we use for
@@ -19,10 +25,11 @@ type Options = {
19
25
  htmlToTextOptions?: HtmlToTextOptions;
20
26
  });
21
27
 
22
- declare const plainTextSelectors: SelectorDefinition[];
23
-
24
28
  declare const pretty: (str: string, options?: Options$1) => Promise<string>;
25
29
 
30
+ declare const plainTextSelectors: SelectorDefinition[];
31
+ declare function toPlainText(html: string, options?: HtmlToTextOptions): string;
32
+
26
33
  declare const render: (node: React.ReactNode, options?: Options) => Promise<string>;
27
34
 
28
35
  /**
@@ -30,4 +37,4 @@ declare const render: (node: React.ReactNode, options?: Options) => Promise<stri
30
37
  */
31
38
  declare const renderAsync: (element: React.ReactElement, options?: Options) => Promise<string>;
32
39
 
33
- export { type Options, plainTextSelectors, pretty, render, renderAsync };
40
+ export { type Options, plainTextSelectors, pretty, render, renderAsync, toPlainText };
@@ -70,24 +70,14 @@ __export(index_exports, {
70
70
  plainTextSelectors: () => plainTextSelectors,
71
71
  pretty: () => pretty,
72
72
  render: () => render,
73
- renderAsync: () => renderAsync
73
+ renderAsync: () => renderAsync,
74
+ toPlainText: () => toPlainText
74
75
  });
75
76
  module.exports = __toCommonJS(index_exports);
76
77
 
77
78
  // src/browser/render.tsx
78
- var import_html_to_text = require("html-to-text");
79
79
  var import_react = require("react");
80
80
 
81
- // src/shared/plain-text-selectors.ts
82
- var plainTextSelectors = [
83
- { selector: "img", format: "skip" },
84
- { selector: "[data-skip-in-text=true]", format: "skip" },
85
- {
86
- selector: "a",
87
- options: { linkBrackets: false }
88
- }
89
- ];
90
-
91
81
  // src/shared/utils/pretty.ts
92
82
  var html = __toESM(require("prettier/plugins/html"));
93
83
  var import_standalone = require("prettier/standalone");
@@ -153,8 +143,23 @@ var pretty = (str, options = {}) => {
153
143
  return (0, import_standalone.format)(str.replaceAll("\0", ""), __spreadValues(__spreadValues({}, defaults), options));
154
144
  };
155
145
 
156
- // src/browser/render.tsx
157
- var import_jsx_runtime = require("react/jsx-runtime");
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
158
163
  var decoder = new TextDecoder("utf-8");
159
164
  var readStream = (stream) => __async(void 0, null, function* () {
160
165
  const chunks = [];
@@ -183,6 +188,9 @@ var readStream = (stream) => __async(void 0, null, function* () {
183
188
  });
184
189
  return decoder.decode(mergedChunks);
185
190
  });
191
+
192
+ // src/browser/render.tsx
193
+ var import_jsx_runtime = require("react/jsx-runtime");
186
194
  var render = (node, options) => __async(void 0, null, function* () {
187
195
  const suspendedElement = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Suspense, { children: node });
188
196
  const reactDOMServer = yield import("react-dom/server.browser").then(
@@ -198,9 +206,7 @@ var render = (node, options) => __async(void 0, null, function* () {
198
206
  }).then(readStream).then(resolve).catch(reject);
199
207
  });
200
208
  if (options == null ? void 0 : options.plainText) {
201
- return (0, import_html_to_text.convert)(html2, __spreadValues({
202
- selectors: plainTextSelectors
203
- }, options.htmlToTextOptions));
209
+ return toPlainText(html2, options.htmlToTextOptions);
204
210
  }
205
211
  const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
206
212
  const document = `${doctype}${html2.replace(/<!DOCTYPE.*?>/, "")}`;
@@ -219,5 +225,6 @@ var renderAsync = (element, options) => {
219
225
  plainTextSelectors,
220
226
  pretty,
221
227
  render,
222
- renderAsync
228
+ renderAsync,
229
+ toPlainText
223
230
  });
@@ -39,19 +39,8 @@ var __async = (__this, __arguments, generator) => {
39
39
  };
40
40
 
41
41
  // src/browser/render.tsx
42
- import { convert } from "html-to-text";
43
42
  import { Suspense } from "react";
44
43
 
45
- // src/shared/plain-text-selectors.ts
46
- var plainTextSelectors = [
47
- { selector: "img", format: "skip" },
48
- { selector: "[data-skip-in-text=true]", format: "skip" },
49
- {
50
- selector: "a",
51
- options: { linkBrackets: false }
52
- }
53
- ];
54
-
55
44
  // src/shared/utils/pretty.ts
56
45
  import * as html from "prettier/plugins/html";
57
46
  import { format } from "prettier/standalone";
@@ -117,8 +106,25 @@ var pretty = (str, options = {}) => {
117
106
  return format(str.replaceAll("\0", ""), __spreadValues(__spreadValues({}, defaults), options));
118
107
  };
119
108
 
120
- // src/browser/render.tsx
121
- import { jsx } from "react/jsx-runtime";
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
122
128
  var decoder = new TextDecoder("utf-8");
123
129
  var readStream = (stream) => __async(void 0, null, function* () {
124
130
  const chunks = [];
@@ -147,6 +153,9 @@ var readStream = (stream) => __async(void 0, null, function* () {
147
153
  });
148
154
  return decoder.decode(mergedChunks);
149
155
  });
156
+
157
+ // src/browser/render.tsx
158
+ import { jsx } from "react/jsx-runtime";
150
159
  var render = (node, options) => __async(void 0, null, function* () {
151
160
  const suspendedElement = /* @__PURE__ */ jsx(Suspense, { children: node });
152
161
  const reactDOMServer = yield import("react-dom/server.browser").then(
@@ -162,9 +171,7 @@ var render = (node, options) => __async(void 0, null, function* () {
162
171
  }).then(readStream).then(resolve).catch(reject);
163
172
  });
164
173
  if (options == null ? void 0 : options.plainText) {
165
- return convert(html2, __spreadValues({
166
- selectors: plainTextSelectors
167
- }, options.htmlToTextOptions));
174
+ return toPlainText(html2, options.htmlToTextOptions);
168
175
  }
169
176
  const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
170
177
  const document = `${doctype}${html2.replace(/<!DOCTYPE.*?>/, "")}`;
@@ -182,5 +189,6 @@ export {
182
189
  plainTextSelectors,
183
190
  pretty,
184
191
  render,
185
- renderAsync
192
+ renderAsync,
193
+ toPlainText
186
194
  };
@@ -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,239 @@
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 = () => __async(void 0, null, function* () {
194
+ try {
195
+ return yield import("react-dom/server.edge");
196
+ } catch (_exception) {
197
+ return yield import("react-dom/server");
198
+ }
199
+ });
200
+
201
+ // src/edge/render.tsx
202
+ var import_jsx_runtime = require("react/jsx-runtime");
203
+ var render = (element, options) => __async(void 0, null, function* () {
204
+ const suspendedElement = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Suspense, { children: element });
205
+ const reactDOMServer = yield importReactDOM().then(
206
+ // This is beacuse react-dom/server is CJS
207
+ (m) => m.default
208
+ );
209
+ const html2 = yield new Promise((resolve, reject) => {
210
+ reactDOMServer.renderToReadableStream(suspendedElement, {
211
+ onError(error) {
212
+ reject(error);
213
+ },
214
+ progressiveChunkSize: Number.POSITIVE_INFINITY
215
+ }).then(readStream).then(resolve).catch(reject);
216
+ });
217
+ if (options == null ? void 0 : options.plainText) {
218
+ return toPlainText(html2, options.htmlToTextOptions);
219
+ }
220
+ const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
221
+ const document = `${doctype}${html2.replace(/<!DOCTYPE.*?>/, "")}`;
222
+ if (options == null ? void 0 : options.pretty) {
223
+ return pretty(document);
224
+ }
225
+ return document;
226
+ });
227
+
228
+ // src/edge/index.ts
229
+ var renderAsync = (element, options) => {
230
+ return render(element, options);
231
+ };
232
+ // Annotate the CommonJS export names for ESM import in node:
233
+ 0 && (module.exports = {
234
+ plainTextSelectors,
235
+ pretty,
236
+ render,
237
+ renderAsync,
238
+ toPlainText
239
+ });
@@ -0,0 +1,203 @@
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 = () => __async(void 0, null, function* () {
159
+ try {
160
+ return yield import("react-dom/server.edge");
161
+ } catch (_exception) {
162
+ return yield import("react-dom/server");
163
+ }
164
+ });
165
+
166
+ // src/edge/render.tsx
167
+ import { jsx } from "react/jsx-runtime";
168
+ var render = (element, options) => __async(void 0, null, function* () {
169
+ const suspendedElement = /* @__PURE__ */ jsx(Suspense, { children: element });
170
+ const reactDOMServer = yield importReactDOM().then(
171
+ // This is beacuse react-dom/server is CJS
172
+ (m) => m.default
173
+ );
174
+ const html2 = yield new Promise((resolve, reject) => {
175
+ reactDOMServer.renderToReadableStream(suspendedElement, {
176
+ onError(error) {
177
+ reject(error);
178
+ },
179
+ progressiveChunkSize: Number.POSITIVE_INFINITY
180
+ }).then(readStream).then(resolve).catch(reject);
181
+ });
182
+ if (options == null ? void 0 : options.plainText) {
183
+ return toPlainText(html2, options.htmlToTextOptions);
184
+ }
185
+ const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
186
+ const document = `${doctype}${html2.replace(/<!DOCTYPE.*?>/, "")}`;
187
+ if (options == null ? void 0 : options.pretty) {
188
+ return pretty(document);
189
+ }
190
+ return document;
191
+ });
192
+
193
+ // src/edge/index.ts
194
+ var renderAsync = (element, options) => {
195
+ return render(element, options);
196
+ };
197
+ export {
198
+ plainTextSelectors,
199
+ pretty,
200
+ render,
201
+ renderAsync,
202
+ toPlainText
203
+ };
@@ -7,8 +7,14 @@ type Options = {
7
7
  */
8
8
  pretty?: boolean;
9
9
  } & ({
10
+ /**
11
+ * @deprecated use {@link toPlainText} instead
12
+ */
10
13
  plainText?: false;
11
14
  } | {
15
+ /**
16
+ * @deprecated use {@link toPlainText} instead
17
+ */
12
18
  plainText?: true;
13
19
  /**
14
20
  * These are options you can pass down directly to the library we use for
@@ -19,10 +25,11 @@ type Options = {
19
25
  htmlToTextOptions?: HtmlToTextOptions;
20
26
  });
21
27
 
22
- declare const plainTextSelectors: SelectorDefinition[];
23
-
24
28
  declare const pretty: (str: string, options?: Options$1) => Promise<string>;
25
29
 
30
+ declare const plainTextSelectors: SelectorDefinition[];
31
+ declare function toPlainText(html: string, options?: HtmlToTextOptions): string;
32
+
26
33
  declare const render: (node: React.ReactNode, options?: Options) => Promise<string>;
27
34
 
28
35
  /**
@@ -30,4 +37,4 @@ declare const render: (node: React.ReactNode, options?: Options) => Promise<stri
30
37
  */
31
38
  declare const renderAsync: (element: React.ReactElement, options?: Options) => Promise<string>;
32
39
 
33
- export { type Options, plainTextSelectors, pretty, render, renderAsync };
40
+ export { type Options, plainTextSelectors, pretty, render, renderAsync, toPlainText };
@@ -7,8 +7,14 @@ type Options = {
7
7
  */
8
8
  pretty?: boolean;
9
9
  } & ({
10
+ /**
11
+ * @deprecated use {@link toPlainText} instead
12
+ */
10
13
  plainText?: false;
11
14
  } | {
15
+ /**
16
+ * @deprecated use {@link toPlainText} instead
17
+ */
12
18
  plainText?: true;
13
19
  /**
14
20
  * These are options you can pass down directly to the library we use for
@@ -19,10 +25,11 @@ type Options = {
19
25
  htmlToTextOptions?: HtmlToTextOptions;
20
26
  });
21
27
 
22
- declare const plainTextSelectors: SelectorDefinition[];
23
-
24
28
  declare const pretty: (str: string, options?: Options$1) => Promise<string>;
25
29
 
30
+ declare const plainTextSelectors: SelectorDefinition[];
31
+ declare function toPlainText(html: string, options?: HtmlToTextOptions): string;
32
+
26
33
  declare const render: (node: React.ReactNode, options?: Options) => Promise<string>;
27
34
 
28
35
  /**
@@ -30,4 +37,4 @@ declare const render: (node: React.ReactNode, options?: Options) => Promise<stri
30
37
  */
31
38
  declare const renderAsync: (element: React.ReactElement, options?: Options) => Promise<string>;
32
39
 
33
- export { type Options, plainTextSelectors, pretty, render, renderAsync };
40
+ export { type Options, plainTextSelectors, pretty, render, renderAsync, toPlainText };
@@ -70,24 +70,14 @@ __export(index_exports, {
70
70
  plainTextSelectors: () => plainTextSelectors,
71
71
  pretty: () => pretty,
72
72
  render: () => render,
73
- renderAsync: () => renderAsync
73
+ renderAsync: () => renderAsync,
74
+ toPlainText: () => toPlainText
74
75
  });
75
76
  module.exports = __toCommonJS(index_exports);
76
77
 
77
78
  // src/node/render.tsx
78
- var import_html_to_text = require("html-to-text");
79
79
  var import_react = require("react");
80
80
 
81
- // src/shared/plain-text-selectors.ts
82
- var plainTextSelectors = [
83
- { selector: "img", format: "skip" },
84
- { selector: "[data-skip-in-text=true]", format: "skip" },
85
- {
86
- selector: "a",
87
- options: { linkBrackets: false }
88
- }
89
- ];
90
-
91
81
  // src/shared/utils/pretty.ts
92
82
  var html = __toESM(require("prettier/plugins/html"));
93
83
  var import_standalone = require("prettier/standalone");
@@ -153,6 +143,22 @@ var pretty = (str, options = {}) => {
153
143
  return (0, import_standalone.format)(str.replaceAll("\0", ""), __spreadValues(__spreadValues({}, defaults), options));
154
144
  };
155
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
+
156
162
  // src/node/read-stream.ts
157
163
  var import_node_stream = require("stream");
158
164
  var decoder = new TextDecoder("utf-8");
@@ -215,9 +221,7 @@ var render = (node, options) => __async(void 0, null, function* () {
215
221
  });
216
222
  }
217
223
  if (options == null ? void 0 : options.plainText) {
218
- return (0, import_html_to_text.convert)(html2, __spreadValues({
219
- selectors: plainTextSelectors
220
- }, options.htmlToTextOptions));
224
+ return toPlainText(html2, options.htmlToTextOptions);
221
225
  }
222
226
  const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
223
227
  const document = `${doctype}${html2.replace(/<!DOCTYPE.*?>/, "")}`;
@@ -236,5 +240,6 @@ var renderAsync = (element, options) => {
236
240
  plainTextSelectors,
237
241
  pretty,
238
242
  render,
239
- renderAsync
243
+ renderAsync,
244
+ toPlainText
240
245
  });
@@ -39,19 +39,8 @@ var __async = (__this, __arguments, generator) => {
39
39
  };
40
40
 
41
41
  // src/node/render.tsx
42
- import { convert } from "html-to-text";
43
42
  import { Suspense } from "react";
44
43
 
45
- // src/shared/plain-text-selectors.ts
46
- var plainTextSelectors = [
47
- { selector: "img", format: "skip" },
48
- { selector: "[data-skip-in-text=true]", format: "skip" },
49
- {
50
- selector: "a",
51
- options: { linkBrackets: false }
52
- }
53
- ];
54
-
55
44
  // src/shared/utils/pretty.ts
56
45
  import * as html from "prettier/plugins/html";
57
46
  import { format } from "prettier/standalone";
@@ -117,6 +106,24 @@ var pretty = (str, options = {}) => {
117
106
  return format(str.replaceAll("\0", ""), __spreadValues(__spreadValues({}, defaults), options));
118
107
  };
119
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
+
120
127
  // src/node/read-stream.ts
121
128
  import { Writable } from "node:stream";
122
129
  var decoder = new TextDecoder("utf-8");
@@ -179,9 +186,7 @@ var render = (node, options) => __async(void 0, null, function* () {
179
186
  });
180
187
  }
181
188
  if (options == null ? void 0 : options.plainText) {
182
- return convert(html2, __spreadValues({
183
- selectors: plainTextSelectors
184
- }, options.htmlToTextOptions));
189
+ return toPlainText(html2, options.htmlToTextOptions);
185
190
  }
186
191
  const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
187
192
  const document = `${doctype}${html2.replace(/<!DOCTYPE.*?>/, "")}`;
@@ -199,5 +204,6 @@ export {
199
204
  plainTextSelectors,
200
205
  pretty,
201
206
  render,
202
- renderAsync
207
+ renderAsync,
208
+ toPlainText
203
209
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-email/render",
3
- "version": "1.1.4",
3
+ "version": "1.2.1",
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
- "node": {
14
+ "workerd": {
15
15
  "import": {
16
- "types": "./dist/node/index.d.mts",
17
- "default": "./dist/node/index.mjs"
16
+ "types": "./dist/edge/index.d.mts",
17
+ "default": "./dist/edge/index.mjs"
18
18
  },
19
19
  "require": {
20
- "types": "./dist/node/index.d.ts",
21
- "default": "./dist/node/index.js"
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",