@react-email/render 0.0.10 → 0.0.11

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/index.d.mts CHANGED
@@ -1,12 +1,24 @@
1
- interface Options {
1
+ import { HtmlToTextOptions, SelectorDefinition } from 'html-to-text';
2
+
3
+ type Options = {
2
4
  pretty?: boolean;
3
- plainText?: boolean;
4
- }
5
+ } & ({
6
+ plainText?: false;
7
+ } | {
8
+ plainText?: true;
9
+ /**
10
+ * These are options you can pass down directly to the library we use for
11
+ * converting the rendered email's HTML into plain text.
12
+ *
13
+ * @see https://github.com/html-to-text/node-html-to-text
14
+ */
15
+ htmlToTextOptions?: HtmlToTextOptions;
16
+ });
17
+
5
18
  declare const render: (component: React.ReactElement, options?: Options) => string;
6
19
 
7
- declare const renderAsync: (component: React.ReactElement, options?: {
8
- pretty?: boolean;
9
- plainText?: boolean;
10
- }) => Promise<string>;
20
+ declare const renderAsync: (component: React.ReactElement, options?: Options) => Promise<string>;
21
+
22
+ declare const plainTextSelectors: SelectorDefinition[];
11
23
 
12
- export { Options, render, renderAsync };
24
+ export { Options, plainTextSelectors, render, renderAsync };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,24 @@
1
- interface Options {
1
+ import { HtmlToTextOptions, SelectorDefinition } from 'html-to-text';
2
+
3
+ type Options = {
2
4
  pretty?: boolean;
3
- plainText?: boolean;
4
- }
5
+ } & ({
6
+ plainText?: false;
7
+ } | {
8
+ plainText?: true;
9
+ /**
10
+ * These are options you can pass down directly to the library we use for
11
+ * converting the rendered email's HTML into plain text.
12
+ *
13
+ * @see https://github.com/html-to-text/node-html-to-text
14
+ */
15
+ htmlToTextOptions?: HtmlToTextOptions;
16
+ });
17
+
5
18
  declare const render: (component: React.ReactElement, options?: Options) => string;
6
19
 
7
- declare const renderAsync: (component: React.ReactElement, options?: {
8
- pretty?: boolean;
9
- plainText?: boolean;
10
- }) => Promise<string>;
20
+ declare const renderAsync: (component: React.ReactElement, options?: Options) => Promise<string>;
21
+
22
+ declare const plainTextSelectors: SelectorDefinition[];
11
23
 
12
- export { Options, render, renderAsync };
24
+ export { Options, plainTextSelectors, render, renderAsync };
package/dist/index.js CHANGED
@@ -3,8 +3,27 @@ var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
7
  var __getProtoOf = Object.getPrototypeOf;
7
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
10
+ var __knownSymbol = (name, symbol) => {
11
+ if (symbol = Symbol[name])
12
+ return symbol;
13
+ throw Error("Symbol." + name + " is not defined");
14
+ };
15
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
16
+ var __spreadValues = (a, b) => {
17
+ for (var prop in b || (b = {}))
18
+ if (__hasOwnProp.call(b, prop))
19
+ __defNormalProp(a, prop, b[prop]);
20
+ if (__getOwnPropSymbols)
21
+ for (var prop of __getOwnPropSymbols(b)) {
22
+ if (__propIsEnum.call(b, prop))
23
+ __defNormalProp(a, prop, b[prop]);
24
+ }
25
+ return a;
26
+ };
8
27
  var __export = (target, all) => {
9
28
  for (var name in all)
10
29
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -46,10 +65,12 @@ var __async = (__this, __arguments, generator) => {
46
65
  step((generator = generator.apply(__this, __arguments)).next());
47
66
  });
48
67
  };
68
+ var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
49
69
 
50
70
  // src/index.ts
51
71
  var src_exports = {};
52
72
  __export(src_exports, {
73
+ plainTextSelectors: () => plainTextSelectors,
53
74
  render: () => render,
54
75
  renderAsync: () => renderAsync
55
76
  });
@@ -58,7 +79,31 @@ module.exports = __toCommonJS(src_exports);
58
79
  // src/render.ts
59
80
  var ReactDomServer = __toESM(require("react-dom/server"));
60
81
  var import_html_to_text = require("html-to-text");
61
- var import_pretty = __toESM(require("pretty"));
82
+
83
+ // src/utils/pretty.ts
84
+ var import_js_beautify = require("js-beautify");
85
+ var defaults = {
86
+ unformatted: ["code", "pre", "em", "strong", "span"],
87
+ indent_inner_html: true,
88
+ indent_char: " ",
89
+ indent_size: 2,
90
+ sep: "\n"
91
+ };
92
+ var pretty = (str, options = {}) => {
93
+ return (0, import_js_beautify.html)(str, __spreadValues(__spreadValues({}, defaults), options));
94
+ };
95
+
96
+ // src/plain-text-selectors.ts
97
+ var plainTextSelectors = [
98
+ { selector: "img", format: "skip" },
99
+ { selector: "#__react-email-preview", format: "skip" },
100
+ {
101
+ selector: "a",
102
+ options: { linkBrackets: false }
103
+ }
104
+ ];
105
+
106
+ // src/render.ts
62
107
  var render = (component, options) => {
63
108
  if (options == null ? void 0 : options.plainText) {
64
109
  return renderAsPlainText(component, options);
@@ -67,56 +112,70 @@ var render = (component, options) => {
67
112
  const markup = ReactDomServer.renderToStaticMarkup(component);
68
113
  const document = `${doctype}${markup}`;
69
114
  if (options && options.pretty) {
70
- return (0, import_pretty.default)(document);
115
+ return pretty(document);
71
116
  }
72
117
  return document;
73
118
  };
74
- var renderAsPlainText = (component, _options) => {
75
- return (0, import_html_to_text.convert)(ReactDomServer.renderToStaticMarkup(component), {
76
- selectors: [
77
- { selector: "img", format: "skip" },
78
- { selector: "#__react-email-preview", format: "skip" }
79
- ]
80
- });
119
+ var renderAsPlainText = (component, options) => {
120
+ return (0, import_html_to_text.convert)(ReactDomServer.renderToStaticMarkup(component), __spreadValues({
121
+ selectors: plainTextSelectors
122
+ }, (options == null ? void 0 : options.plainText) === true ? options.htmlToTextOptions : {}));
81
123
  };
82
124
 
83
125
  // src/render-async.ts
84
126
  var import_html_to_text2 = require("html-to-text");
85
- var import_pretty2 = __toESM(require("pretty"));
127
+ var decoder = new TextDecoder("utf-8");
86
128
  var readStream = (readableStream) => __async(void 0, null, function* () {
87
- const reader = readableStream.getReader();
88
- const chunks = [];
89
- while (true) {
90
- const { value, done } = yield reader.read();
91
- if (done) {
92
- break;
129
+ let result = "";
130
+ if ("allReady" in readableStream) {
131
+ const reader = readableStream.getReader();
132
+ while (true) {
133
+ const { value, done } = yield reader.read();
134
+ if (done) {
135
+ break;
136
+ }
137
+ result += decoder.decode(value);
138
+ }
139
+ } else {
140
+ try {
141
+ for (var iter = __forAwait(readableStream), more, temp, error; more = !(temp = yield iter.next()).done; more = false) {
142
+ const chunk = temp.value;
143
+ result += decoder.decode(Buffer.from(chunk));
144
+ }
145
+ } catch (temp) {
146
+ error = [temp];
147
+ } finally {
148
+ try {
149
+ more && (temp = iter.return) && (yield temp.call(iter));
150
+ } finally {
151
+ if (error)
152
+ throw error[0];
153
+ }
93
154
  }
94
- chunks.push(value);
95
155
  }
96
- return chunks.map((chunk) => new TextDecoder("utf-8").decode(chunk)).join("");
156
+ return result;
97
157
  });
98
158
  var renderAsync = (component, options) => __async(void 0, null, function* () {
159
+ var _a;
99
160
  const reactDOMServer = (yield import("react-dom/server")).default;
100
- const renderToStream = reactDOMServer.renderToReadableStream || reactDOMServer.renderToString || reactDOMServer.renderToPipeableStream;
161
+ const renderToStream = (_a = reactDOMServer.renderToReadableStream) != null ? _a : reactDOMServer.renderToStaticNodeStream;
101
162
  const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
102
- const readableStream = yield renderToStream(component);
103
- const html = typeof readableStream === "string" ? readableStream : yield readStream(readableStream);
163
+ const htmlOrReadableStream = yield renderToStream(component);
164
+ const html2 = typeof htmlOrReadableStream === "string" ? htmlOrReadableStream : yield readStream(htmlOrReadableStream);
104
165
  if (options == null ? void 0 : options.plainText) {
105
- return (0, import_html_to_text2.convert)(html, {
106
- selectors: [
107
- { selector: "img", format: "skip" },
108
- { selector: "#__react-email-preview", format: "skip" }
109
- ]
110
- });
166
+ return (0, import_html_to_text2.convert)(html2, __spreadValues({
167
+ selectors: plainTextSelectors
168
+ }, options.htmlToTextOptions));
111
169
  }
112
- const document = `${doctype}${html}`;
170
+ const document = `${doctype}${html2}`;
113
171
  if (options == null ? void 0 : options.pretty) {
114
- return (0, import_pretty2.default)(document);
172
+ return pretty(document);
115
173
  }
116
174
  return document;
117
175
  });
118
176
  // Annotate the CommonJS export names for ESM import in node:
119
177
  0 && (module.exports = {
178
+ plainTextSelectors,
120
179
  render,
121
180
  renderAsync
122
181
  });
package/dist/index.mjs CHANGED
@@ -1,3 +1,24 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
5
+ var __knownSymbol = (name, symbol) => {
6
+ if (symbol = Symbol[name])
7
+ return symbol;
8
+ throw Error("Symbol." + name + " is not defined");
9
+ };
10
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
+ var __spreadValues = (a, b) => {
12
+ for (var prop in b || (b = {}))
13
+ if (__hasOwnProp.call(b, prop))
14
+ __defNormalProp(a, prop, b[prop]);
15
+ if (__getOwnPropSymbols)
16
+ for (var prop of __getOwnPropSymbols(b)) {
17
+ if (__propIsEnum.call(b, prop))
18
+ __defNormalProp(a, prop, b[prop]);
19
+ }
20
+ return a;
21
+ };
1
22
  var __async = (__this, __arguments, generator) => {
2
23
  return new Promise((resolve, reject) => {
3
24
  var fulfilled = (value) => {
@@ -18,11 +39,36 @@ var __async = (__this, __arguments, generator) => {
18
39
  step((generator = generator.apply(__this, __arguments)).next());
19
40
  });
20
41
  };
42
+ var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
21
43
 
22
44
  // src/render.ts
23
45
  import * as ReactDomServer from "react-dom/server";
24
46
  import { convert } from "html-to-text";
25
- import pretty from "pretty";
47
+
48
+ // src/utils/pretty.ts
49
+ import { html } from "js-beautify";
50
+ var defaults = {
51
+ unformatted: ["code", "pre", "em", "strong", "span"],
52
+ indent_inner_html: true,
53
+ indent_char: " ",
54
+ indent_size: 2,
55
+ sep: "\n"
56
+ };
57
+ var pretty = (str, options = {}) => {
58
+ return html(str, __spreadValues(__spreadValues({}, defaults), options));
59
+ };
60
+
61
+ // src/plain-text-selectors.ts
62
+ var plainTextSelectors = [
63
+ { selector: "img", format: "skip" },
64
+ { selector: "#__react-email-preview", format: "skip" },
65
+ {
66
+ selector: "a",
67
+ options: { linkBrackets: false }
68
+ }
69
+ ];
70
+
71
+ // src/render.ts
26
72
  var render = (component, options) => {
27
73
  if (options == null ? void 0 : options.plainText) {
28
74
  return renderAsPlainText(component, options);
@@ -35,51 +81,65 @@ var render = (component, options) => {
35
81
  }
36
82
  return document;
37
83
  };
38
- var renderAsPlainText = (component, _options) => {
39
- return convert(ReactDomServer.renderToStaticMarkup(component), {
40
- selectors: [
41
- { selector: "img", format: "skip" },
42
- { selector: "#__react-email-preview", format: "skip" }
43
- ]
44
- });
84
+ var renderAsPlainText = (component, options) => {
85
+ return convert(ReactDomServer.renderToStaticMarkup(component), __spreadValues({
86
+ selectors: plainTextSelectors
87
+ }, (options == null ? void 0 : options.plainText) === true ? options.htmlToTextOptions : {}));
45
88
  };
46
89
 
47
90
  // src/render-async.ts
48
91
  import { convert as convert2 } from "html-to-text";
49
- import pretty2 from "pretty";
92
+ var decoder = new TextDecoder("utf-8");
50
93
  var readStream = (readableStream) => __async(void 0, null, function* () {
51
- const reader = readableStream.getReader();
52
- const chunks = [];
53
- while (true) {
54
- const { value, done } = yield reader.read();
55
- if (done) {
56
- break;
94
+ let result = "";
95
+ if ("allReady" in readableStream) {
96
+ const reader = readableStream.getReader();
97
+ while (true) {
98
+ const { value, done } = yield reader.read();
99
+ if (done) {
100
+ break;
101
+ }
102
+ result += decoder.decode(value);
103
+ }
104
+ } else {
105
+ try {
106
+ for (var iter = __forAwait(readableStream), more, temp, error; more = !(temp = yield iter.next()).done; more = false) {
107
+ const chunk = temp.value;
108
+ result += decoder.decode(Buffer.from(chunk));
109
+ }
110
+ } catch (temp) {
111
+ error = [temp];
112
+ } finally {
113
+ try {
114
+ more && (temp = iter.return) && (yield temp.call(iter));
115
+ } finally {
116
+ if (error)
117
+ throw error[0];
118
+ }
57
119
  }
58
- chunks.push(value);
59
120
  }
60
- return chunks.map((chunk) => new TextDecoder("utf-8").decode(chunk)).join("");
121
+ return result;
61
122
  });
62
123
  var renderAsync = (component, options) => __async(void 0, null, function* () {
124
+ var _a;
63
125
  const reactDOMServer = (yield import("react-dom/server")).default;
64
- const renderToStream = reactDOMServer.renderToReadableStream || reactDOMServer.renderToString || reactDOMServer.renderToPipeableStream;
126
+ const renderToStream = (_a = reactDOMServer.renderToReadableStream) != null ? _a : reactDOMServer.renderToStaticNodeStream;
65
127
  const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
66
- const readableStream = yield renderToStream(component);
67
- const html = typeof readableStream === "string" ? readableStream : yield readStream(readableStream);
128
+ const htmlOrReadableStream = yield renderToStream(component);
129
+ const html2 = typeof htmlOrReadableStream === "string" ? htmlOrReadableStream : yield readStream(htmlOrReadableStream);
68
130
  if (options == null ? void 0 : options.plainText) {
69
- return convert2(html, {
70
- selectors: [
71
- { selector: "img", format: "skip" },
72
- { selector: "#__react-email-preview", format: "skip" }
73
- ]
74
- });
131
+ return convert2(html2, __spreadValues({
132
+ selectors: plainTextSelectors
133
+ }, options.htmlToTextOptions));
75
134
  }
76
- const document = `${doctype}${html}`;
135
+ const document = `${doctype}${html2}`;
77
136
  if (options == null ? void 0 : options.pretty) {
78
- return pretty2(document);
137
+ return pretty(document);
79
138
  }
80
139
  return document;
81
140
  });
82
141
  export {
142
+ plainTextSelectors,
83
143
  render,
84
144
  renderAsync
85
145
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-email/render",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
4
4
  "description": "Transform React components into HTML email templates",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -24,7 +24,7 @@
24
24
  "license": "MIT",
25
25
  "repository": {
26
26
  "type": "git",
27
- "url": "https://github.com/resendlabs/react-email.git",
27
+ "url": "https://github.com/resend/react-email.git",
28
28
  "directory": "packages/render"
29
29
  },
30
30
  "keywords": [
@@ -36,15 +36,18 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "html-to-text": "9.0.5",
39
- "pretty": "2.0.0",
39
+ "js-beautify": "^1.14.11",
40
40
  "react": "18.2.0",
41
41
  "react-dom": "18.2.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@babel/preset-react": "7.22.5",
45
+ "@edge-runtime/vm": "3.1.7",
45
46
  "@types/html-to-text": "9.0.1",
46
- "@types/pretty": "2.0.1",
47
+ "@types/js-beautify": "1.14.3",
48
+ "jsdom": "23.0.1",
47
49
  "typescript": "5.1.6",
50
+ "vitest": "0.34.6",
48
51
  "eslint-config-custom": "0.0.0",
49
52
  "tsconfig": "0.0.0"
50
53
  },
package/readme.md CHANGED
@@ -6,7 +6,7 @@
6
6
  <div align="center">
7
7
  <a href="https://react.email">Website</a>
8
8
  <span> · </span>
9
- <a href="https://github.com/resendlabs/react-email">GitHub</a>
9
+ <a href="https://github.com/resend/react-email">GitHub</a>
10
10
  <span> · </span>
11
11
  <a href="https://react.email/discord">Discord</a>
12
12
  </div>