Skip to content

Commit da3e719

Browse files
committed
feat(render): Use prettier's standalone API instead of js-beautify (#1777)
1 parent 5bc7044 commit da3e719

File tree

5 files changed

+197
-50
lines changed

5 files changed

+197
-50
lines changed

.changeset/large-taxis-smoke.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@react-email/render": patch
3+
---
4+
5+
Use prettier's stadalone API instead of js-beautify

packages/react-email/src/cli/commands/testing/__snapshots__/export.spec.ts.snap

+161-24
Original file line numberDiff line numberDiff line change
@@ -3,63 +3,200 @@
33
exports[`email export 1`] = `
44
"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
55
<html dir="ltr" lang="en">
6-
76
<head>
87
<link rel="preload" as="image" href="/static/vercel-logo.png" />
98
<link rel="preload" as="image" href="/static/vercel-arrow.png" />
109
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
11-
<meta name="x-apple-disable-message-reformatting" /><!--$-->
10+
<meta name="x-apple-disable-message-reformatting" />
11+
<!--$-->
1212
</head>
13-
<div style="display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0">Join undefined on Vercel<div> ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏</div>
13+
<div
14+
style="display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0"
15+
>
16+
Join undefined on Vercel
17+
<div>
18+
 ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏
19+
</div>
1420
</div>
15-
16-
<body style="background-color:rgb(255,255,255);margin-top:auto;margin-bottom:auto;margin-left:auto;margin-right:auto;font-family:ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;padding-left:0.5rem;padding-right:0.5rem">
17-
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="border-width:1px;border-style:solid;border-color:rgb(234,234,234);border-radius:0.25rem;margin-top:40px;margin-bottom:40px;margin-left:auto;margin-right:auto;padding:20px;max-width:465px">
21+
<body
22+
style='background-color:rgb(255,255,255);margin-top:auto;margin-bottom:auto;margin-left:auto;margin-right:auto;font-family:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";padding-left:0.5rem;padding-right:0.5rem'
23+
>
24+
<table
25+
align="center"
26+
width="100%"
27+
border="0"
28+
cellpadding="0"
29+
cellspacing="0"
30+
role="presentation"
31+
style="border-width:1px;border-style:solid;border-color:rgb(234,234,234);border-radius:0.25rem;margin-top:40px;margin-bottom:40px;margin-left:auto;margin-right:auto;padding:20px;max-width:465px"
32+
>
1833
<tbody>
1934
<tr style="width:100%">
2035
<td>
21-
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="margin-top:32px">
36+
<table
37+
align="center"
38+
width="100%"
39+
border="0"
40+
cellpadding="0"
41+
cellspacing="0"
42+
role="presentation"
43+
style="margin-top:32px"
44+
>
2245
<tbody>
2346
<tr>
24-
<td><img alt="Vercel" height="37" src="/static/vercel-logo.png" style="margin-top:0px;margin-bottom:0px;margin-left:auto;margin-right:auto;display:block;outline:none;border:none;text-decoration:none" width="40" /></td>
47+
<td>
48+
<img
49+
alt="Vercel"
50+
height="37"
51+
src="/static/vercel-logo.png"
52+
style="margin-top:0px;margin-bottom:0px;margin-left:auto;margin-right:auto;display:block;outline:none;border:none;text-decoration:none"
53+
width="40"
54+
/>
55+
</td>
2556
</tr>
2657
</tbody>
2758
</table>
28-
<h1 style="color:rgb(0,0,0);font-size:24px;font-weight:400;text-align:center;padding:0px;margin-top:30px;margin-bottom:30px;margin-left:0px;margin-right:0px">Join <strong></strong> on <strong>Vercel</strong></h1>
29-
<p style="color:rgb(0,0,0);font-size:14px;line-height:24px;margin:16px 0">Hello <!-- -->,</p>
30-
<p style="color:rgb(0,0,0);font-size:14px;line-height:24px;margin:16px 0"><strong></strong> (<a href="mailto:undefined" style="color:rgb(37,99,235);text-decoration-line:none" target="_blank"></a>) has invited you to the <strong></strong> team on<!-- --> <strong>Vercel</strong>.</p>
31-
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation">
59+
<h1
60+
style="color:rgb(0,0,0);font-size:24px;font-weight:400;text-align:center;padding:0px;margin-top:30px;margin-bottom:30px;margin-left:0px;margin-right:0px"
61+
>
62+
Join <strong></strong> on <strong>Vercel</strong>
63+
</h1>
64+
<p
65+
style="color:rgb(0,0,0);font-size:14px;line-height:24px;margin:16px 0"
66+
>
67+
Hello
68+
<!-- -->,
69+
</p>
70+
<p
71+
style="color:rgb(0,0,0);font-size:14px;line-height:24px;margin:16px 0"
72+
>
73+
<strong></strong> (<a
74+
href="mailto:undefined"
75+
style="color:rgb(37,99,235);text-decoration-line:none"
76+
target="_blank"
77+
></a
78+
>) has invited you to the <strong></strong> team on<!-- -->
79+
<strong>Vercel</strong>.
80+
</p>
81+
<table
82+
align="center"
83+
width="100%"
84+
border="0"
85+
cellpadding="0"
86+
cellspacing="0"
87+
role="presentation"
88+
>
3289
<tbody>
3390
<tr>
3491
<td>
35-
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation">
92+
<table
93+
align="center"
94+
width="100%"
95+
border="0"
96+
cellpadding="0"
97+
cellspacing="0"
98+
role="presentation"
99+
>
36100
<tbody style="width:100%">
37101
<tr style="width:100%">
38-
<td align="right" data-id="__react-email-column"><img height="64" style="border-radius:9999px;display:block;outline:none;border:none;text-decoration:none" width="64" /></td>
39-
<td align="center" data-id="__react-email-column"><img alt="invited you to" height="9" src="/static/vercel-arrow.png" style="display:block;outline:none;border:none;text-decoration:none" width="12" /></td>
40-
<td align="left" data-id="__react-email-column"><img height="64" style="border-radius:9999px;display:block;outline:none;border:none;text-decoration:none" width="64" /></td>
102+
<td align="right" data-id="__react-email-column">
103+
<img
104+
height="64"
105+
style="border-radius:9999px;display:block;outline:none;border:none;text-decoration:none"
106+
width="64"
107+
/>
108+
</td>
109+
<td align="center" data-id="__react-email-column">
110+
<img
111+
alt="invited you to"
112+
height="9"
113+
src="/static/vercel-arrow.png"
114+
style="display:block;outline:none;border:none;text-decoration:none"
115+
width="12"
116+
/>
117+
</td>
118+
<td align="left" data-id="__react-email-column">
119+
<img
120+
height="64"
121+
style="border-radius:9999px;display:block;outline:none;border:none;text-decoration:none"
122+
width="64"
123+
/>
124+
</td>
41125
</tr>
42126
</tbody>
43127
</table>
44128
</td>
45129
</tr>
46130
</tbody>
47131
</table>
48-
<table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="text-align:center;margin-top:32px;margin-bottom:32px">
132+
<table
133+
align="center"
134+
width="100%"
135+
border="0"
136+
cellpadding="0"
137+
cellspacing="0"
138+
role="presentation"
139+
style="text-align:center;margin-top:32px;margin-bottom:32px"
140+
>
49141
<tbody>
50142
<tr>
51-
<td><a style="background-color:rgb(0,0,0);border-radius:0.25rem;color:rgb(255,255,255);font-size:12px;font-weight:600;text-decoration-line:none;text-align:center;padding-left:1.25rem;padding-right:1.25rem;padding-top:0.75rem;padding-bottom:0.75rem;line-height:100%;text-decoration:none;display:inline-block;max-width:100%;mso-padding-alt:0px;padding:12px 20px 12px 20px" target="_blank"><span><!--[if mso]><i style="mso-font-width:500%;mso-text-raise:18" hidden>&#8202;&#8202;</i><![endif]--></span><span style="max-width:100%;display:inline-block;line-height:120%;mso-padding-alt:0px;mso-text-raise:9px">Join the team</span><span><!--[if mso]><i style="mso-font-width:500%" hidden>&#8202;&#8202;&#8203;</i><![endif]--></span></a></td>
143+
<td>
144+
<a
145+
style="background-color:rgb(0,0,0);border-radius:0.25rem;color:rgb(255,255,255);font-size:12px;font-weight:600;text-decoration-line:none;text-align:center;padding-left:1.25rem;padding-right:1.25rem;padding-top:0.75rem;padding-bottom:0.75rem;line-height:100%;text-decoration:none;display:inline-block;max-width:100%;mso-padding-alt:0px;padding:12px 20px 12px 20px"
146+
target="_blank"
147+
><span
148+
><!--[if mso
149+
]><i
150+
style="mso-font-width:500%;mso-text-raise:18"
151+
hidden
152+
>&#8202;&#8202;</i
153+
><!
154+
[endif]--></span
155+
><span
156+
style="max-width:100%;display:inline-block;line-height:120%;mso-padding-alt:0px;mso-text-raise:9px"
157+
>Join the team</span
158+
><span
159+
><!--[if mso
160+
]><i style="mso-font-width:500%" hidden
161+
>&#8202;&#8202;&#8203;</i
162+
><!
163+
[endif]--></span
164+
></a
165+
>
166+
</td>
52167
</tr>
53168
</tbody>
54169
</table>
55-
<p style="color:rgb(0,0,0);font-size:14px;line-height:24px;margin:16px 0">or copy and paste this URL into your browser:<!-- --> <a style="color:rgb(37,99,235);text-decoration-line:none" target="_blank"></a></p>
56-
<hr style="border-width:1px;border-style:solid;border-color:rgb(234,234,234);margin-top:26px;margin-bottom:26px;margin-left:0px;margin-right:0px;width:100%;border:none;border-top:1px solid #eaeaea" />
57-
<p style="color:rgb(102,102,102);font-size:12px;line-height:24px;margin:16px 0">This invitation was intended for<!-- --> <span style="color:rgb(0,0,0)"></span>. This invite was sent from <span style="color:rgb(0,0,0)"></span> <!-- -->located in<!-- --> <span style="color:rgb(0,0,0)"></span>. If you were not expecting this invitation, you can ignore this email. If you are concerned about your account&#x27;s safety, please reply to this email to get in touch with us.</p>
170+
<p
171+
style="color:rgb(0,0,0);font-size:14px;line-height:24px;margin:16px 0"
172+
>
173+
or copy and paste this URL into your browser:<!-- -->
174+
<a
175+
style="color:rgb(37,99,235);text-decoration-line:none"
176+
target="_blank"
177+
></a>
178+
</p>
179+
<hr
180+
style="border-width:1px;border-style:solid;border-color:rgb(234,234,234);margin-top:26px;margin-bottom:26px;margin-left:0px;margin-right:0px;width:100%;border:none;border-top:1px solid #eaeaea"
181+
/>
182+
<p
183+
style="color:rgb(102,102,102);font-size:12px;line-height:24px;margin:16px 0"
184+
>
185+
This invitation was intended for<!-- -->
186+
<span style="color:rgb(0,0,0)"></span>. This invite was sent from
187+
<span style="color:rgb(0,0,0)"></span>
188+
<!-- -->located in<!-- -->
189+
<span style="color:rgb(0,0,0)"></span>. If you were not expecting
190+
this invitation, you can ignore this email. If you are concerned
191+
about your account&#x27;s safety, please reply to this email to
192+
get in touch with us.
193+
</p>
58194
</td>
59195
</tr>
60196
</tbody>
61-
</table><!--/$-->
197+
</table>
198+
<!--/$-->
62199
</body>
63-
64-
</html>"
200+
</html>
201+
"
65202
`;

packages/render/package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,17 @@
8686
},
8787
"dependencies": {
8888
"html-to-text": "9.0.5",
89-
"js-beautify": "^1.14.11",
89+
"prettier": "3.3.3",
9090
"react": "^18.0 || ^19.0 || ^19.0.0-rc",
9191
"react-dom": "^18.0 || ^19.0 || ^19.0.0-rc",
9292
"react-promise-suspense": "0.3.4"
9393
},
9494
"devDependencies": {
95-
"@types/react": "npm:[email protected]",
96-
"@types/react-dom": "npm:[email protected]",
9795
"@edge-runtime/vm": "3.1.8",
9896
"@types/html-to-text": "9.0.4",
99-
"@types/js-beautify": "1.14.3",
97+
"@types/prettier": "3.0.0",
98+
"@types/react": "npm:[email protected]",
99+
"@types/react-dom": "npm:[email protected]",
100100
"eslint-config-custom": "workspace:*",
101101
"jsdom": "23.0.1",
102102
"tsconfig": "workspace:*",
+13-11
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
// importing the exact function used here will cause
2-
// issues with esm because js-beautify is written with commonjs only
3-
import jsBeautify from "js-beautify";
1+
import { format } from "prettier/standalone";
2+
import html from "prettier/plugins/html";
3+
import type { Options } from "prettier";
44

5-
const defaults = {
6-
unformatted: ["code", "pre", "em", "strong", "span"],
7-
indent_inner_html: true,
8-
indent_char: " ",
9-
indent_size: 2,
10-
sep: "\n",
5+
const defaults: Options = {
6+
endOfLine: "lf",
7+
tabWidth: 2,
8+
plugins: [html],
9+
parser: "html",
1110
};
1211

13-
export const pretty = (str: string, options = {}) => {
14-
return jsBeautify.html(str, { ...defaults, ...options });
12+
export const pretty = (str: string, options: Options = {}) => {
13+
return format(str, {
14+
...defaults,
15+
...options,
16+
});
1517
};

0 commit comments

Comments
 (0)