react-email 4.0.16 → 4.1.0-canary.10

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.
Files changed (470) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/dev/index.js +40 -0
  3. package/dev/package.json +13 -0
  4. package/dist/index.js +1 -1
  5. package/package.json +13 -46
  6. package/readme.md +16 -0
  7. package/src/commands/build.ts +306 -0
  8. package/src/commands/dev.ts +27 -0
  9. package/src/commands/export.ts +204 -0
  10. package/src/commands/start.ts +38 -0
  11. package/src/index.ts +55 -0
  12. package/src/utils/__snapshots__/tree.spec.ts.snap +27 -0
  13. package/src/utils/esbuild/renderring-utilities-exporter.ts +1 -1
  14. package/src/utils/get-emails-directory-metadata.spec.ts +1 -1
  15. package/src/utils/get-preview-server-location.ts +51 -0
  16. package/src/utils/index.ts +2 -6
  17. package/src/utils/packageJson.ts +4 -0
  18. package/src/utils/preview/get-env-variables-for-preview-app.ts +14 -0
  19. package/src/utils/preview/hot-reloading/create-dependency-graph.spec.ts +284 -0
  20. package/src/utils/preview/hot-reloading/create-dependency-graph.ts +321 -0
  21. package/src/utils/preview/hot-reloading/get-imported-modules.spec.ts +151 -0
  22. package/src/utils/preview/hot-reloading/get-imported-modules.ts +49 -0
  23. package/src/utils/preview/hot-reloading/resolve-path-aliases.spec.ts +11 -0
  24. package/src/utils/preview/hot-reloading/resolve-path-aliases.ts +32 -0
  25. package/src/utils/preview/hot-reloading/setup-hot-reloading.ts +121 -0
  26. package/src/utils/preview/hot-reloading/test/tsconfig.json +8 -0
  27. package/src/utils/preview/index.ts +2 -0
  28. package/src/utils/preview/serve-static-file.ts +51 -0
  29. package/src/utils/preview/start-dev-server.ts +234 -0
  30. package/src/utils/tree.spec.ts +5 -0
  31. package/src/utils/tree.ts +76 -0
  32. package/src/utils/types/hot-reload-change.ts +1 -1
  33. package/src/utils/types/hot-reload-event.ts +1 -1
  34. package/tsconfig.json +4 -10
  35. package/dist/cli/index.d.mts +0 -1
  36. package/dist/cli/index.d.ts +0 -1
  37. package/dist/cli/index.js +0 -2785
  38. package/dist/cli/index.mjs +0 -1361
  39. package/dist/index.d.mts +0 -20
  40. package/dist/index.d.ts +0 -20
  41. package/dist/index.mjs +0 -21
  42. package/dist/package/index.d.mts +0 -33
  43. package/dist/package/index.d.ts +0 -33
  44. package/dist/package/index.js +0 -62
  45. package/dist/package/index.mjs +0 -7
  46. package/dist/preview/.next/BUILD_ID +0 -1
  47. package/dist/preview/.next/app-build-manifest.json +0 -44
  48. package/dist/preview/.next/app-path-routes-manifest.json +0 -6
  49. package/dist/preview/.next/build-manifest.json +0 -33
  50. package/dist/preview/.next/diagnostics/build-diagnostics.json +0 -6
  51. package/dist/preview/.next/diagnostics/framework.json +0 -1
  52. package/dist/preview/.next/export-marker.json +0 -6
  53. package/dist/preview/.next/images-manifest.json +0 -57
  54. package/dist/preview/.next/next-minimal-server.js.nft.json +0 -1
  55. package/dist/preview/.next/next-server.js.nft.json +0 -1
  56. package/dist/preview/.next/package.json +0 -1
  57. package/dist/preview/.next/prerender-manifest.json +0 -41
  58. package/dist/preview/.next/react-loadable-manifest.json +0 -1
  59. package/dist/preview/.next/required-server-files.json +0 -311
  60. package/dist/preview/.next/routes-manifest.json +0 -64
  61. package/dist/preview/.next/server/app/_not-found/page.js +0 -1
  62. package/dist/preview/.next/server/app/_not-found/page.js.nft.json +0 -1
  63. package/dist/preview/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  64. package/dist/preview/.next/server/app/favicon.ico/route.js +0 -1
  65. package/dist/preview/.next/server/app/favicon.ico/route.js.nft.json +0 -1
  66. package/dist/preview/.next/server/app/favicon.ico.body +0 -0
  67. package/dist/preview/.next/server/app/favicon.ico.meta +0 -1
  68. package/dist/preview/.next/server/app/page.js +0 -1
  69. package/dist/preview/.next/server/app/page.js.nft.json +0 -1
  70. package/dist/preview/.next/server/app/page_client-reference-manifest.js +0 -1
  71. package/dist/preview/.next/server/app/preview/[...slug]/page.js +0 -321
  72. package/dist/preview/.next/server/app/preview/[...slug]/page.js.nft.json +0 -1
  73. package/dist/preview/.next/server/app/preview/[...slug]/page_client-reference-manifest.js +0 -1
  74. package/dist/preview/.next/server/app-paths-manifest.json +0 -6
  75. package/dist/preview/.next/server/chunks/134.js +0 -6
  76. package/dist/preview/.next/server/chunks/235.js +0 -15
  77. package/dist/preview/.next/server/chunks/275.js +0 -1
  78. package/dist/preview/.next/server/chunks/343.js +0 -20
  79. package/dist/preview/.next/server/chunks/428.js +0 -14
  80. package/dist/preview/.next/server/chunks/963.js +0 -1
  81. package/dist/preview/.next/server/functions-config-manifest.json +0 -4
  82. package/dist/preview/.next/server/interception-route-rewrite-manifest.js +0 -1
  83. package/dist/preview/.next/server/middleware-build-manifest.js +0 -1
  84. package/dist/preview/.next/server/middleware-manifest.json +0 -6
  85. package/dist/preview/.next/server/middleware-react-loadable-manifest.js +0 -1
  86. package/dist/preview/.next/server/next-font-manifest.js +0 -1
  87. package/dist/preview/.next/server/next-font-manifest.json +0 -1
  88. package/dist/preview/.next/server/pages/500.html +0 -1
  89. package/dist/preview/.next/server/pages/_app.js +0 -1
  90. package/dist/preview/.next/server/pages/_app.js.nft.json +0 -1
  91. package/dist/preview/.next/server/pages/_document.js +0 -1
  92. package/dist/preview/.next/server/pages/_document.js.nft.json +0 -1
  93. package/dist/preview/.next/server/pages/_error.js +0 -1
  94. package/dist/preview/.next/server/pages/_error.js.nft.json +0 -1
  95. package/dist/preview/.next/server/pages-manifest.json +0 -5
  96. package/dist/preview/.next/server/server-reference-manifest.js +0 -1
  97. package/dist/preview/.next/server/server-reference-manifest.json +0 -1
  98. package/dist/preview/.next/server/webpack-runtime.js +0 -1
  99. package/dist/preview/.next/static/chunks/107-3043079e7cb8bcae.js +0 -1
  100. package/dist/preview/.next/static/chunks/293-297b1eb2241f9a70.js +0 -1
  101. package/dist/preview/.next/static/chunks/3bd82e28-cda2c00a924937c5.js +0 -1
  102. package/dist/preview/.next/static/chunks/45-1021fac82f766268.js +0 -1
  103. package/dist/preview/.next/static/chunks/484-e38a627386aae911.js +0 -1
  104. package/dist/preview/.next/static/chunks/589-817d8691661d370e.js +0 -1
  105. package/dist/preview/.next/static/chunks/902-c34acb56733e0ce1.js +0 -1
  106. package/dist/preview/.next/static/chunks/app/_not-found/page-4cbc7dce3ad33336.js +0 -1
  107. package/dist/preview/.next/static/chunks/app/layout-269b5cbd8f4cd2e3.js +0 -1
  108. package/dist/preview/.next/static/chunks/app/page-2dbfb5b2dc4b1191.js +0 -1
  109. package/dist/preview/.next/static/chunks/app/preview/[...slug]/page-79e0c9b528a62f8b.js +0 -1
  110. package/dist/preview/.next/static/chunks/f33a14d2-ec7c5f0b91818561.js +0 -6
  111. package/dist/preview/.next/static/chunks/framework-b887e9fc751a9906.js +0 -1
  112. package/dist/preview/.next/static/chunks/main-9a03e7ba8acb1900.js +0 -1
  113. package/dist/preview/.next/static/chunks/main-app-976577a424e11c75.js +0 -1
  114. package/dist/preview/.next/static/chunks/pages/_app-542a93a5a214e1c0.js +0 -1
  115. package/dist/preview/.next/static/chunks/pages/_error-d5fe1b1612642f76.js +0 -1
  116. package/dist/preview/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  117. package/dist/preview/.next/static/chunks/webpack-31c45daa2bd82a7b.js +0 -1
  118. package/dist/preview/.next/static/css/ac3decd5d6736fbe.css +0 -3
  119. package/dist/preview/.next/static/media/05613964ce6c782e-s.p.otf +0 -0
  120. package/dist/preview/.next/static/media/11c6126b9369e85e-s.p.otf +0 -0
  121. package/dist/preview/.next/static/media/26a46d62cd723877-s.woff2 +0 -0
  122. package/dist/preview/.next/static/media/26cb97734d8cb717-s.p.otf +0 -0
  123. package/dist/preview/.next/static/media/55c55f0601d81cf3-s.woff2 +0 -0
  124. package/dist/preview/.next/static/media/581909926a08bbc8-s.woff2 +0 -0
  125. package/dist/preview/.next/static/media/8e9860b6e62d6359-s.woff2 +0 -0
  126. package/dist/preview/.next/static/media/97e0cb1ae144a2a9-s.woff2 +0 -0
  127. package/dist/preview/.next/static/media/bb6462617151f6b7-s.p.otf +0 -0
  128. package/dist/preview/.next/static/media/cf6daef822ab0142-s.p.otf +0 -0
  129. package/dist/preview/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
  130. package/dist/preview/.next/static/media/e4051546b3043204-s.p.otf +0 -0
  131. package/dist/preview/.next/static/media/e4af272ccee01ff0-s.p.woff2 +0 -0
  132. package/dist/preview/.next/static/media/logo.2ce2a759.png +0 -0
  133. package/dist/preview/.next/static/yxjkw7Y7HRLmRWkl3S43z/_buildManifest.js +0 -1
  134. package/dist/preview/.next/static/yxjkw7Y7HRLmRWkl3S43z/_ssgManifest.js +0 -1
  135. package/dist/preview/.next/trace +0 -27
  136. package/dist/preview/.next/types/app/layout.ts +0 -84
  137. package/dist/preview/.next/types/app/page.ts +0 -84
  138. package/dist/preview/.next/types/app/preview/[...slug]/page.ts +0 -84
  139. package/dist/preview/.next/types/cache-life.d.ts +0 -141
  140. package/dist/preview/.next/types/package.json +0 -1
  141. package/module-punycode.d.ts +0 -3
  142. package/next-env.d.ts +0 -5
  143. package/next.config.js +0 -22
  144. package/postcss.config.js +0 -8
  145. package/scripts/build-preview-server.mjs +0 -33
  146. package/scripts/fill-caniemail-data.mjs +0 -36
  147. package/src/actions/email-validation/caniemail-data.ts +0 -85993
  148. package/src/actions/email-validation/check-compatibility.ts +0 -333
  149. package/src/actions/email-validation/check-images.spec.tsx +0 -100
  150. package/src/actions/email-validation/check-images.ts +0 -160
  151. package/src/actions/email-validation/check-links.spec.tsx +0 -113
  152. package/src/actions/email-validation/check-links.ts +0 -113
  153. package/src/actions/email-validation/get-code-location-from-ast-element.ts +0 -18
  154. package/src/actions/email-validation/quick-fetch.ts +0 -14
  155. package/src/actions/get-email-path-from-slug.ts +0 -32
  156. package/src/actions/get-emails-directory-metadata-action.ts +0 -19
  157. package/src/actions/render-email-by-path.tsx +0 -121
  158. package/src/animated-icons-data/help.json +0 -1082
  159. package/src/animated-icons-data/link.json +0 -1309
  160. package/src/animated-icons-data/load.json +0 -443
  161. package/src/animated-icons-data/mail.json +0 -1320
  162. package/src/app/env.ts +0 -15
  163. package/src/app/favicon.ico +0 -0
  164. package/src/app/fonts/SFMono/SFMonoBold.otf +0 -0
  165. package/src/app/fonts/SFMono/SFMonoBoldItalic.otf +0 -0
  166. package/src/app/fonts/SFMono/SFMonoHeavy.otf +0 -0
  167. package/src/app/fonts/SFMono/SFMonoHeavyItalic.otf +0 -0
  168. package/src/app/fonts/SFMono/SFMonoLight.otf +0 -0
  169. package/src/app/fonts/SFMono/SFMonoLightItalic.otf +0 -0
  170. package/src/app/fonts/SFMono/SFMonoMedium.otf +0 -0
  171. package/src/app/fonts/SFMono/SFMonoMediumItalic.otf +0 -0
  172. package/src/app/fonts/SFMono/SFMonoRegular.otf +0 -0
  173. package/src/app/fonts/SFMono/SFMonoRegularItalic.otf +0 -0
  174. package/src/app/fonts/SFMono/SFMonoSemibold.otf +0 -0
  175. package/src/app/fonts/SFMono/SFMonoSemiboldItalic.otf +0 -0
  176. package/src/app/fonts.ts +0 -39
  177. package/src/app/globals.css +0 -15
  178. package/src/app/layout.tsx +0 -43
  179. package/src/app/logo.png +0 -0
  180. package/src/app/page.tsx +0 -46
  181. package/src/app/preview/[...slug]/page.tsx +0 -157
  182. package/src/app/preview/[...slug]/preview.tsx +0 -216
  183. package/src/app/preview/[...slug]/rendering-error.tsx +0 -40
  184. package/src/commands/testing/out/magic-links/aws-verify-email.html +0 -165
  185. package/src/commands/testing/out/magic-links/linear-login-code.html +0 -90
  186. package/src/commands/testing/out/magic-links/notion-magic-link.html +0 -76
  187. package/src/commands/testing/out/magic-links/plaid-verify-identity.html +0 -78
  188. package/src/commands/testing/out/magic-links/raycast-magic-link.html +0 -91
  189. package/src/commands/testing/out/magic-links/slack-confirm.html +0 -240
  190. package/src/commands/testing/out/newsletters/codepen-challengers.html +0 -548
  191. package/src/commands/testing/out/newsletters/google-play-policy-update.html +0 -339
  192. package/src/commands/testing/out/newsletters/stack-overflow-tips.html +0 -231
  193. package/src/commands/testing/out/notifications/github-access-token.html +0 -104
  194. package/src/commands/testing/out/notifications/papermark-year-in-review.html +0 -317
  195. package/src/commands/testing/out/notifications/vercel-invite-user.html +0 -171
  196. package/src/commands/testing/out/notifications/yelp-recent-login.html +0 -195
  197. package/src/commands/testing/out/receipts/apple-receipt.html +0 -677
  198. package/src/commands/testing/out/receipts/nike-receipt.html +0 -724
  199. package/src/commands/testing/out/reset-password/dropbox-reset-password.html +0 -98
  200. package/src/commands/testing/out/reset-password/twitch-reset-password.html +0 -220
  201. package/src/commands/testing/out/reviews/airbnb-review.html +0 -206
  202. package/src/commands/testing/out/reviews/amazon-review.html +0 -356
  203. package/src/commands/testing/out/static/airbnb-logo.png +0 -0
  204. package/src/commands/testing/out/static/airbnb-review-user.jpg +0 -0
  205. package/src/commands/testing/out/static/amazon-book.jpg +0 -0
  206. package/src/commands/testing/out/static/amazon-facebook.jpg +0 -0
  207. package/src/commands/testing/out/static/amazon-instagram.jpg +0 -0
  208. package/src/commands/testing/out/static/amazon-logo.png +0 -0
  209. package/src/commands/testing/out/static/amazon-prime-logo.png +0 -0
  210. package/src/commands/testing/out/static/amazon-rating.gif +0 -0
  211. package/src/commands/testing/out/static/amazon-twitter.jpg +0 -0
  212. package/src/commands/testing/out/static/apple-card-icon.png +0 -0
  213. package/src/commands/testing/out/static/apple-hbo-max-icon.jpeg +0 -0
  214. package/src/commands/testing/out/static/apple-logo.png +0 -0
  215. package/src/commands/testing/out/static/apple-wallet.png +0 -0
  216. package/src/commands/testing/out/static/aws-logo.png +0 -0
  217. package/src/commands/testing/out/static/codepen-challengers.png +0 -0
  218. package/src/commands/testing/out/static/codepen-cube.png +0 -0
  219. package/src/commands/testing/out/static/codepen-pro.png +0 -0
  220. package/src/commands/testing/out/static/dropbox-logo.png +0 -0
  221. package/src/commands/testing/out/static/github.png +0 -0
  222. package/src/commands/testing/out/static/google-play-academy.png +0 -0
  223. package/src/commands/testing/out/static/google-play-chat.png +0 -0
  224. package/src/commands/testing/out/static/google-play-footer.png +0 -0
  225. package/src/commands/testing/out/static/google-play-header.png +0 -0
  226. package/src/commands/testing/out/static/google-play-icon.png +0 -0
  227. package/src/commands/testing/out/static/google-play-logo.png +0 -0
  228. package/src/commands/testing/out/static/google-play-pl.png +0 -0
  229. package/src/commands/testing/out/static/google-play.png +0 -0
  230. package/src/commands/testing/out/static/koala-logo.png +0 -0
  231. package/src/commands/testing/out/static/linear-logo.png +0 -0
  232. package/src/commands/testing/out/static/netlify-logo.png +0 -0
  233. package/src/commands/testing/out/static/nike-logo.png +0 -0
  234. package/src/commands/testing/out/static/nike-phone.png +0 -0
  235. package/src/commands/testing/out/static/nike-product.png +0 -0
  236. package/src/commands/testing/out/static/nike-recomendation-1.png +0 -0
  237. package/src/commands/testing/out/static/nike-recomendation-2.png +0 -0
  238. package/src/commands/testing/out/static/nike-recomendation-3.png +0 -0
  239. package/src/commands/testing/out/static/nike-recomendation-4.png +0 -0
  240. package/src/commands/testing/out/static/notion-logo.png +0 -0
  241. package/src/commands/testing/out/static/plaid-logo.png +0 -0
  242. package/src/commands/testing/out/static/raycast-bg.png +0 -0
  243. package/src/commands/testing/out/static/raycast-logo.png +0 -0
  244. package/src/commands/testing/out/static/slack-facebook.png +0 -0
  245. package/src/commands/testing/out/static/slack-linkedin.png +0 -0
  246. package/src/commands/testing/out/static/slack-logo.png +0 -0
  247. package/src/commands/testing/out/static/slack-twitter.png +0 -0
  248. package/src/commands/testing/out/static/stack-overflow-header.png +0 -0
  249. package/src/commands/testing/out/static/stack-overflow-logo-sm.png +0 -0
  250. package/src/commands/testing/out/static/stack-overflow-logo.png +0 -0
  251. package/src/commands/testing/out/static/stripe-logo.png +0 -0
  252. package/src/commands/testing/out/static/twitch-icon-facebook.png +0 -0
  253. package/src/commands/testing/out/static/twitch-icon-twitter.png +0 -0
  254. package/src/commands/testing/out/static/twitch-logo.png +0 -0
  255. package/src/commands/testing/out/static/vercel-arrow.png +0 -0
  256. package/src/commands/testing/out/static/vercel-logo.png +0 -0
  257. package/src/commands/testing/out/static/vercel-team.png +0 -0
  258. package/src/commands/testing/out/static/vercel-user.png +0 -0
  259. package/src/commands/testing/out/static/yelp-footer.png +0 -0
  260. package/src/commands/testing/out/static/yelp-header.png +0 -0
  261. package/src/commands/testing/out/static/yelp-logo.png +0 -0
  262. package/src/commands/testing/out/welcome/koala-welcome.html +0 -90
  263. package/src/commands/testing/out/welcome/netlify-welcome.html +0 -199
  264. package/src/commands/testing/out/welcome/stripe-welcome.html +0 -153
  265. package/src/components/button.tsx +0 -101
  266. package/src/components/code-container.tsx +0 -164
  267. package/src/components/code-snippet.tsx +0 -9
  268. package/src/components/code.tsx +0 -184
  269. package/src/components/heading.tsx +0 -113
  270. package/src/components/icons/icon-arrow-down.tsx +0 -16
  271. package/src/components/icons/icon-base.tsx +0 -26
  272. package/src/components/icons/icon-bug.tsx +0 -19
  273. package/src/components/icons/icon-button.tsx +0 -23
  274. package/src/components/icons/icon-check.tsx +0 -19
  275. package/src/components/icons/icon-clipboard.tsx +0 -40
  276. package/src/components/icons/icon-download.tsx +0 -19
  277. package/src/components/icons/icon-email.tsx +0 -18
  278. package/src/components/icons/icon-file.tsx +0 -19
  279. package/src/components/icons/icon-folder-open.tsx +0 -19
  280. package/src/components/icons/icon-folder.tsx +0 -18
  281. package/src/components/icons/icon-hide-sidebar.tsx +0 -23
  282. package/src/components/icons/icon-image.tsx +0 -19
  283. package/src/components/icons/icon-info.tsx +0 -18
  284. package/src/components/icons/icon-link.tsx +0 -14
  285. package/src/components/icons/icon-monitor.tsx +0 -19
  286. package/src/components/icons/icon-phone.tsx +0 -26
  287. package/src/components/icons/icon-reload.tsx +0 -18
  288. package/src/components/icons/icon-source.tsx +0 -19
  289. package/src/components/icons/icon-stamp.tsx +0 -14
  290. package/src/components/icons/icon-warning.tsx +0 -31
  291. package/src/components/index.ts +0 -7
  292. package/src/components/logo.tsx +0 -63
  293. package/src/components/resizable-wrapper.tsx +0 -173
  294. package/src/components/send.tsx +0 -134
  295. package/src/components/shell.tsx +0 -95
  296. package/src/components/sidebar/file-tree-directory-children.tsx +0 -134
  297. package/src/components/sidebar/file-tree-directory.tsx +0 -92
  298. package/src/components/sidebar/file-tree.tsx +0 -31
  299. package/src/components/sidebar/index.ts +0 -1
  300. package/src/components/sidebar/sidebar.tsx +0 -43
  301. package/src/components/text.tsx +0 -99
  302. package/src/components/toolbar/checking-results.tsx +0 -150
  303. package/src/components/toolbar/code-preview-line-link.tsx +0 -40
  304. package/src/components/toolbar/compatibility.tsx +0 -113
  305. package/src/components/toolbar/linter.tsx +0 -278
  306. package/src/components/toolbar/results.tsx +0 -51
  307. package/src/components/toolbar/spam-assassin.tsx +0 -155
  308. package/src/components/toolbar/toolbar-button.tsx +0 -52
  309. package/src/components/toolbar/use-cached-state.ts +0 -33
  310. package/src/components/toolbar.tsx +0 -349
  311. package/src/components/tooltip-content.tsx +0 -31
  312. package/src/components/tooltip.tsx +0 -19
  313. package/src/components/topbar/active-view-toggle-group.tsx +0 -86
  314. package/src/components/topbar/view-size-controls.tsx +0 -247
  315. package/src/components/topbar.tsx +0 -59
  316. package/src/contexts/emails.tsx +0 -59
  317. package/src/contexts/fragment-identifier.tsx +0 -48
  318. package/src/contexts/preview.tsx +0 -79
  319. package/src/hooks/use-clamped-state.ts +0 -24
  320. package/src/hooks/use-email-rendering-result.ts +0 -58
  321. package/src/hooks/use-fragment-identifier.ts +0 -14
  322. package/src/hooks/use-hot-reload.ts +0 -31
  323. package/src/hooks/use-icon-animation.ts +0 -41
  324. package/src/hooks/use-rendering-metadata.ts +0 -36
  325. package/src/package/body/dist/index.d.mts +0 -6
  326. package/src/package/body/dist/index.d.ts +0 -6
  327. package/src/package/body/dist/index.js +0 -79
  328. package/src/package/body/dist/index.mjs +0 -45
  329. package/src/package/button/dist/index.d.mts +0 -6
  330. package/src/package/button/dist/index.d.ts +0 -6
  331. package/src/package/button/dist/index.js +0 -252
  332. package/src/package/button/dist/index.mjs +0 -218
  333. package/src/package/code-block/dist/index.d.mts +0 -4906
  334. package/src/package/code-block/dist/index.d.ts +0 -4906
  335. package/src/package/code-block/dist/index.js +0 -18205
  336. package/src/package/code-block/dist/index.mjs +0 -18133
  337. package/src/package/code-inline/dist/index.d.mts +0 -11
  338. package/src/package/code-inline/dist/index.d.ts +0 -11
  339. package/src/package/code-inline/dist/index.js +0 -106
  340. package/src/package/code-inline/dist/index.mjs +0 -72
  341. package/src/package/column/dist/index.d.mts +0 -6
  342. package/src/package/column/dist/index.d.ts +0 -6
  343. package/src/package/column/dist/index.js +0 -79
  344. package/src/package/column/dist/index.mjs +0 -45
  345. package/src/package/components/dist/index.d.mts +0 -20
  346. package/src/package/components/dist/index.d.ts +0 -20
  347. package/src/package/components/dist/index.js +0 -62
  348. package/src/package/components/dist/index.mjs +0 -21
  349. package/src/package/container/dist/index.d.mts +0 -6
  350. package/src/package/container/dist/index.d.ts +0 -6
  351. package/src/package/container/dist/index.js +0 -93
  352. package/src/package/container/dist/index.mjs +0 -59
  353. package/src/package/font/dist/index.d.mts +0 -25
  354. package/src/package/font/dist/index.d.ts +0 -25
  355. package/src/package/font/dist/index.js +0 -55
  356. package/src/package/font/dist/index.mjs +0 -28
  357. package/src/package/head/dist/index.d.mts +0 -6
  358. package/src/package/head/dist/index.d.ts +0 -6
  359. package/src/package/head/dist/index.js +0 -83
  360. package/src/package/head/dist/index.mjs +0 -49
  361. package/src/package/heading/dist/index.d.mts +0 -43
  362. package/src/package/heading/dist/index.d.ts +0 -43
  363. package/src/package/heading/dist/index.js +0 -113
  364. package/src/package/heading/dist/index.mjs +0 -79
  365. package/src/package/hr/dist/index.d.mts +0 -6
  366. package/src/package/hr/dist/index.d.ts +0 -6
  367. package/src/package/hr/dist/index.js +0 -89
  368. package/src/package/hr/dist/index.mjs +0 -55
  369. package/src/package/html/dist/index.d.mts +0 -6
  370. package/src/package/html/dist/index.d.ts +0 -6
  371. package/src/package/html/dist/index.js +0 -79
  372. package/src/package/html/dist/index.mjs +0 -45
  373. package/src/package/img/dist/index.d.mts +0 -6
  374. package/src/package/img/dist/index.d.ts +0 -6
  375. package/src/package/img/dist/index.js +0 -94
  376. package/src/package/img/dist/index.mjs +0 -60
  377. package/src/package/link/dist/index.d.mts +0 -6
  378. package/src/package/link/dist/index.d.ts +0 -6
  379. package/src/package/link/dist/index.js +0 -90
  380. package/src/package/link/dist/index.mjs +0 -56
  381. package/src/package/markdown/dist/index.d.mts +0 -15
  382. package/src/package/markdown/dist/index.d.ts +0 -15
  383. package/src/package/markdown/dist/index.js +0 -92
  384. package/src/package/markdown/dist/index.mjs +0 -58
  385. package/src/package/preview/dist/index.d.mts +0 -12
  386. package/src/package/preview/dist/index.d.ts +0 -12
  387. package/src/package/preview/dist/index.js +0 -108
  388. package/src/package/preview/dist/index.mjs +0 -73
  389. package/src/package/render/dist/browser/index.d.mts +0 -24
  390. package/src/package/render/dist/browser/index.d.ts +0 -24
  391. package/src/package/render/dist/browser/index.js +0 -250
  392. package/src/package/render/dist/browser/index.mjs +0 -214
  393. package/src/package/render/dist/index.d.mts +0 -23
  394. package/src/package/render/dist/index.d.ts +0 -23
  395. package/src/package/render/dist/index.js +0 -768
  396. package/src/package/render/dist/index.mjs +0 -733
  397. package/src/package/render/dist/node/index.d.mts +0 -27
  398. package/src/package/render/dist/node/index.d.ts +0 -27
  399. package/src/package/render/dist/node/index.js +0 -212
  400. package/src/package/render/dist/node/index.mjs +0 -176
  401. package/src/package/row/dist/index.d.mts +0 -10
  402. package/src/package/row/dist/index.d.ts +0 -10
  403. package/src/package/row/dist/index.js +0 -93
  404. package/src/package/row/dist/index.mjs +0 -59
  405. package/src/package/section/dist/index.d.mts +0 -6
  406. package/src/package/section/dist/index.d.ts +0 -6
  407. package/src/package/section/dist/index.js +0 -93
  408. package/src/package/section/dist/index.mjs +0 -59
  409. package/src/package/tailwind/dist/index.d.ts +0 -19
  410. package/src/package/tailwind/dist/index.js +0 -48
  411. package/src/package/tailwind/dist/index.mjs +0 -17167
  412. package/src/package/tailwind/dist/tailwindcss/config.d.ts +0 -376
  413. package/src/package/tailwind/dist/tailwindcss/generated/.gitkeep +0 -0
  414. package/src/package/tailwind/dist/tailwindcss/generated/colors.d.ts +0 -298
  415. package/src/package/tailwind/dist/tailwindcss/generated/corePluginList.d.ts +0 -1
  416. package/src/package/tailwind/dist/tailwindcss/generated/default-theme.d.ts +0 -397
  417. package/src/package/tailwind/dist/tailwindcss/index.d.ts +0 -11
  418. package/src/package/text/dist/index.d.mts +0 -6
  419. package/src/package/text/dist/index.d.ts +0 -6
  420. package/src/package/text/dist/index.js +0 -89
  421. package/src/package/text/dist/index.mjs +0 -55
  422. package/src/utils/__snapshots__/get-email-component.spec.ts.snap +0 -3
  423. package/src/utils/caniemail/all-css-properties.ts +0 -358
  424. package/src/utils/caniemail/ast/__snapshots__/get-object-variables.spec.ts.snap +0 -74
  425. package/src/utils/caniemail/ast/__snapshots__/get-used-style-properties.spec.ts.snap +0 -24
  426. package/src/utils/caniemail/ast/get-object-variables.spec.ts +0 -19
  427. package/src/utils/caniemail/ast/get-object-variables.ts +0 -61
  428. package/src/utils/caniemail/ast/get-used-style-properties.spec.ts +0 -23
  429. package/src/utils/caniemail/ast/get-used-style-properties.ts +0 -91
  430. package/src/utils/caniemail/get-compatibility-stats-for-entry.ts +0 -118
  431. package/src/utils/caniemail/get-css-functions.ts +0 -25
  432. package/src/utils/caniemail/get-css-property-names.ts +0 -32
  433. package/src/utils/caniemail/get-css-property-with-value.ts +0 -14
  434. package/src/utils/caniemail/get-css-unit.ts +0 -3
  435. package/src/utils/caniemail/get-element-attributes.ts +0 -7
  436. package/src/utils/caniemail/get-element-names.ts +0 -20
  437. package/src/utils/caniemail/tailwind/generate-tailwind-rules.ts +0 -30
  438. package/src/utils/caniemail/tailwind/get-tailwind-config.ts +0 -187
  439. package/src/utils/caniemail/tailwind/get-tailwind-metadata.spec.ts +0 -25
  440. package/src/utils/caniemail/tailwind/get-tailwind-metadata.ts +0 -45
  441. package/src/utils/caniemail/tailwind/setup-tailwind-context.ts +0 -15
  442. package/src/utils/cn.ts +0 -6
  443. package/src/utils/constants.ts +0 -6
  444. package/src/utils/contains-email-template.spec.ts +0 -124
  445. package/src/utils/contains-email-template.ts +0 -33
  446. package/src/utils/copy-text-to-clipboard.ts +0 -7
  447. package/src/utils/get-email-component.spec.ts +0 -41
  448. package/src/utils/get-email-component.ts +0 -134
  449. package/src/utils/get-line-and-column-from-offset.spec.ts +0 -11
  450. package/src/utils/get-line-and-column-from-offset.ts +0 -11
  451. package/src/utils/improve-error-with-sourcemap.ts +0 -86
  452. package/src/utils/js-email-detection.spec.ts +0 -24
  453. package/src/utils/language-map.ts +0 -7
  454. package/src/utils/linting.ts +0 -60
  455. package/src/utils/load-stream.ts +0 -15
  456. package/src/utils/result.ts +0 -49
  457. package/src/utils/run-bundled-code.ts +0 -64
  458. package/src/utils/sanitize.ts +0 -6
  459. package/src/utils/static-node-modules-for-vm.ts +0 -93
  460. package/src/utils/testing/js-email-export-default.js +0 -17
  461. package/src/utils/testing/js-email-test.js +0 -18
  462. package/src/utils/testing/mdx-email-test.js +0 -128
  463. package/src/utils/testing/request-response-email.tsx +0 -9
  464. package/src/utils/types/as.ts +0 -26
  465. package/src/utils/types/email-template.ts +0 -8
  466. package/src/utils/types/error-object.ts +0 -11
  467. package/src/utils/unreachable.ts +0 -8
  468. package/tailwind-internals.d.ts +0 -133
  469. package/tailwind.config.ts +0 -99
  470. /package/src/{components/toolbar/results-table.tsx → utils/preview/hot-reloading/test/some-file.ts} +0 -0
@@ -1,1361 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/cli/index.ts
4
- import { program } from "commander";
5
-
6
- // package.json
7
- var package_default = {
8
- name: "react-email",
9
- version: "4.0.16",
10
- description: "A live preview of your emails right in your browser.",
11
- bin: {
12
- email: "./dist/cli/index.mjs"
13
- },
14
- scripts: {
15
- build: "tsup-node && node ./scripts/build-preview-server.mjs && pnpm install --frozen-lockfile",
16
- "caniemail:fetch": "node ./scripts/fill-caniemail-data.mjs",
17
- clean: "rm -rf dist",
18
- dev: "tsup-node --watch",
19
- "dev:preview": "cd ../../apps/demo && tsx ../../packages/react-email/src/cli/index.ts dev",
20
- test: "vitest run",
21
- "test:watch": "vitest"
22
- },
23
- license: "MIT",
24
- repository: {
25
- type: "git",
26
- url: "https://github.com/resend/react-email.git",
27
- directory: "packages/react-email"
28
- },
29
- keywords: [
30
- "react",
31
- "email"
32
- ],
33
- engines: {
34
- node: ">=18.0.0"
35
- },
36
- dependencies: {
37
- "@babel/parser": "^7.27.0",
38
- "@babel/traverse": "^7.27.0",
39
- chalk: "^5.0.0",
40
- chokidar: "^4.0.3",
41
- commander: "^13.0.0",
42
- debounce: "^2.0.0",
43
- esbuild: "^0.25.0",
44
- glob: "^11.0.0",
45
- "log-symbols": "^7.0.0",
46
- "mime-types": "^3.0.0",
47
- next: "^15.3.1",
48
- "normalize-path": "^3.0.0",
49
- ora: "^8.0.0",
50
- "socket.io": "^4.8.1"
51
- },
52
- devDependencies: {
53
- "@babel/core": "7.26.10",
54
- "@lottiefiles/dotlottie-react": "0.13.3",
55
- "@radix-ui/colors": "3.0.0",
56
- "@radix-ui/react-collapsible": "1.1.7",
57
- "@radix-ui/react-dropdown-menu": "2.1.10",
58
- "@radix-ui/react-popover": "1.1.10",
59
- "@radix-ui/react-slot": "1.2.0",
60
- "@radix-ui/react-tabs": "1.1.7",
61
- "@radix-ui/react-toggle-group": "1.1.6",
62
- "@radix-ui/react-tooltip": "1.2.3",
63
- "@react-email/components": "workspace:*",
64
- "@swc/core": "1.11.21",
65
- "@types/babel__core": "7.20.5",
66
- "@types/babel__traverse": "7.20.7",
67
- "@types/fs-extra": "11.0.1",
68
- "@types/mime-types": "2.1.4",
69
- "@types/node": "22.14.1",
70
- "@types/normalize-path": "3.0.2",
71
- "@types/react": "19.0.10",
72
- "@types/react-dom": "19.0.4",
73
- "@types/webpack": "5.28.5",
74
- autoprefixer: "10.4.21",
75
- clsx: "2.1.1",
76
- "framer-motion": "12.7.5",
77
- jiti: "2.4.2",
78
- json5: "2.2.3",
79
- "module-punycode": "npm:punycode@2.3.1",
80
- "node-html-parser": "7.0.1",
81
- postcss: "8.5.3",
82
- "pretty-bytes": "6.1.1",
83
- "prism-react-renderer": "2.4.1",
84
- react: "19.0.0",
85
- "react-dom": "19.0.0",
86
- sharp: "0.34.1",
87
- "socket.io-client": "4.8.1",
88
- sonner: "2.0.3",
89
- "source-map-js": "1.2.1",
90
- spamc: "0.0.5",
91
- "stacktrace-parser": "0.1.11",
92
- "tailwind-merge": "3.2.0",
93
- tailwindcss: "3.4.0",
94
- tsup: "8.4.0",
95
- tsx: "4.19.3",
96
- typescript: "5.8.3",
97
- "use-debounce": "10.0.4",
98
- zod: "3.24.3"
99
- }
100
- };
101
-
102
- // src/cli/commands/build.ts
103
- import { spawn } from "node:child_process";
104
- import fs5 from "node:fs";
105
- import path8 from "node:path";
106
- import logSymbols3 from "log-symbols";
107
- import ora2 from "ora";
108
-
109
- // src/utils/get-emails-directory-metadata.ts
110
- import fs from "node:fs";
111
- import path from "node:path";
112
- var isFileAnEmail = async (fullPath) => {
113
- let fileHandle;
114
- try {
115
- fileHandle = await fs.promises.open(fullPath, "r");
116
- } catch (exception) {
117
- console.warn(exception);
118
- return false;
119
- }
120
- const stat = await fileHandle.stat();
121
- if (stat.isDirectory()) {
122
- await fileHandle.close();
123
- return false;
124
- }
125
- const { ext } = path.parse(fullPath);
126
- if (![".js", ".tsx", ".jsx"].includes(ext)) {
127
- await fileHandle.close();
128
- return false;
129
- }
130
- const fileContents = await fileHandle.readFile("utf8");
131
- await fileHandle.close();
132
- const hasES6DefaultExport = /\bexport\s+default\b/gm.test(fileContents);
133
- const hasCommonJSExport = /\bmodule\.exports\s*=/gm.test(fileContents);
134
- const hasNamedExport = /\bexport\s+\{[^}]*\bdefault\b[^}]*\}/gm.test(
135
- fileContents
136
- );
137
- return hasES6DefaultExport || hasCommonJSExport || hasNamedExport;
138
- };
139
- var mergeDirectoriesWithSubDirectories = (emailsDirectoryMetadata) => {
140
- let currentResultingMergedDirectory = emailsDirectoryMetadata;
141
- while (currentResultingMergedDirectory.emailFilenames.length === 0 && currentResultingMergedDirectory.subDirectories.length === 1) {
142
- const onlySubDirectory = currentResultingMergedDirectory.subDirectories[0];
143
- currentResultingMergedDirectory = {
144
- ...onlySubDirectory,
145
- directoryName: path.join(
146
- currentResultingMergedDirectory.directoryName,
147
- onlySubDirectory.directoryName
148
- )
149
- };
150
- }
151
- return currentResultingMergedDirectory;
152
- };
153
- var getEmailsDirectoryMetadata = async (absolutePathToEmailsDirectory, keepFileExtensions = false, isSubDirectory = false, baseDirectoryPath = absolutePathToEmailsDirectory) => {
154
- if (!fs.existsSync(absolutePathToEmailsDirectory)) return;
155
- const dirents = await fs.promises.readdir(absolutePathToEmailsDirectory, {
156
- withFileTypes: true
157
- });
158
- const isEmailPredicates = await Promise.all(
159
- dirents.map(
160
- (dirent) => isFileAnEmail(path.join(absolutePathToEmailsDirectory, dirent.name))
161
- )
162
- );
163
- const emailFilenames = dirents.filter((_, i) => isEmailPredicates[i]).map(
164
- (dirent) => keepFileExtensions ? dirent.name : dirent.name.replace(path.extname(dirent.name), "")
165
- );
166
- const subDirectories = await Promise.all(
167
- dirents.filter(
168
- (dirent) => dirent.isDirectory() && !dirent.name.startsWith("_") && dirent.name !== "static"
169
- ).map((dirent) => {
170
- const direntAbsolutePath = path.join(
171
- absolutePathToEmailsDirectory,
172
- dirent.name
173
- );
174
- return getEmailsDirectoryMetadata(
175
- direntAbsolutePath,
176
- keepFileExtensions,
177
- true,
178
- baseDirectoryPath
179
- );
180
- })
181
- );
182
- const emailsMetadata = {
183
- absolutePath: absolutePathToEmailsDirectory,
184
- relativePath: path.relative(
185
- baseDirectoryPath,
186
- absolutePathToEmailsDirectory
187
- ),
188
- directoryName: absolutePathToEmailsDirectory.split(path.sep).pop(),
189
- emailFilenames,
190
- subDirectories
191
- };
192
- return isSubDirectory ? mergeDirectoriesWithSubDirectories(emailsMetadata) : emailsMetadata;
193
- };
194
-
195
- // src/utils/register-spinner-autostopping.ts
196
- import logSymbols from "log-symbols";
197
- var spinners = /* @__PURE__ */ new Set();
198
- process.on("SIGINT", () => {
199
- spinners.forEach((spinner) => {
200
- if (spinner.isSpinning) {
201
- spinner.stop();
202
- }
203
- });
204
- });
205
- process.on("exit", (code) => {
206
- if (code !== 0) {
207
- spinners.forEach((spinner) => {
208
- if (spinner.isSpinning) {
209
- spinner.stopAndPersist({
210
- symbol: logSymbols.error
211
- });
212
- }
213
- });
214
- }
215
- });
216
- var registerSpinnerAutostopping = (spinner) => {
217
- spinners.add(spinner);
218
- };
219
-
220
- // src/cli/utils/preview/hot-reloading/setup-hot-reloading.ts
221
- import path6 from "node:path";
222
- import { watch } from "chokidar";
223
- import debounce from "debounce";
224
- import { Server as SocketServer } from "socket.io";
225
-
226
- // src/cli/utils/preview/hot-reloading/create-dependency-graph.ts
227
- import { existsSync as existsSync2, promises as fs3, statSync } from "node:fs";
228
- import path5 from "node:path";
229
-
230
- // src/cli/utils/preview/start-dev-server.ts
231
- import http from "node:http";
232
- import path4 from "node:path";
233
- import url from "node:url";
234
- import chalk from "chalk";
235
- import logSymbols2 from "log-symbols";
236
- import next from "next";
237
- import ora from "ora";
238
-
239
- // src/cli/utils/preview/get-env-variables-for-preview-app.ts
240
- import path2 from "node:path";
241
- var getEnvVariablesForPreviewApp = (relativePathToEmailsDirectory, cwd) => {
242
- return {
243
- EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
244
- EMAILS_DIR_ABSOLUTE_PATH: path2.resolve(cwd, relativePathToEmailsDirectory),
245
- USER_PROJECT_LOCATION: cwd,
246
- NEXT_PUBLIC_IS_PREVIEW_DEVELOPMENT: isDev ? "true" : "false"
247
- };
248
- };
249
-
250
- // src/cli/utils/preview/serve-static-file.ts
251
- import { existsSync, promises as fs2 } from "node:fs";
252
- import path3 from "node:path";
253
- import { lookup } from "mime-types";
254
- var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
255
- const pathname = parsedUrl.pathname.replace("/static", "./static");
256
- const ext = path3.parse(pathname).ext;
257
- const staticBaseDir = path3.resolve(process.cwd(), staticDirRelativePath);
258
- const fileAbsolutePath = path3.resolve(staticBaseDir, pathname);
259
- if (!fileAbsolutePath.startsWith(staticBaseDir)) {
260
- res.statusCode = 403;
261
- res.end();
262
- return;
263
- }
264
- try {
265
- const fileHandle = await fs2.open(fileAbsolutePath, "r");
266
- const fileData = await fs2.readFile(fileHandle);
267
- res.setHeader("Content-type", lookup(ext) || "text/plain");
268
- res.end(fileData);
269
- fileHandle.close();
270
- } catch (exception) {
271
- if (!existsSync(fileAbsolutePath)) {
272
- res.statusCode = 404;
273
- res.end();
274
- } else {
275
- const sanitizedFilePath = fileAbsolutePath.replace(/\n|\r/g, "");
276
- console.error(
277
- `Could not read file at ${sanitizedFilePath} to be served, here's the exception:`,
278
- exception
279
- );
280
- res.statusCode = 500;
281
- res.end(
282
- "Could not read file to be served! Check your terminal for more information."
283
- );
284
- }
285
- }
286
- };
287
-
288
- // src/cli/utils/preview/start-dev-server.ts
289
- var devServer;
290
- var safeAsyncServerListen = (server, port) => {
291
- return new Promise((resolve) => {
292
- server.listen(port, () => {
293
- resolve({ portAlreadyInUse: false });
294
- });
295
- server.on("error", (e) => {
296
- if (e.code === "EADDRINUSE") {
297
- resolve({ portAlreadyInUse: true });
298
- }
299
- });
300
- });
301
- };
302
- var filename = url.fileURLToPath(import.meta.url);
303
- var dirname = path4.dirname(filename);
304
- var isDev = !filename.endsWith(path4.join("cli", "index.mjs"));
305
- var cliPackageLocation = isDev ? path4.resolve(dirname, "../../../..") : path4.resolve(dirname, "../..");
306
- var previewServerLocation = isDev ? path4.resolve(dirname, "../../../..") : path4.resolve(dirname, "../preview");
307
- var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, port) => {
308
- const [majorNodeVersion] = process.versions.node.split(".");
309
- if (majorNodeVersion && Number.parseInt(majorNodeVersion) < 18) {
310
- console.error(
311
- ` ${logSymbols2.error} Node ${majorNodeVersion} is not supported. Please upgrade to Node 18 or higher.`
312
- );
313
- process.exit(1);
314
- }
315
- devServer = http.createServer((req, res) => {
316
- if (!req.url) {
317
- res.end(404);
318
- return;
319
- }
320
- const parsedUrl = url.parse(req.url, true);
321
- res.setHeader(
322
- "Cache-Control",
323
- "no-cache, max-age=0, must-revalidate, no-store"
324
- );
325
- res.setHeader("Pragma", "no-cache");
326
- res.setHeader("Expires", "-1");
327
- try {
328
- if (parsedUrl.path?.includes("static/") && !parsedUrl.path.includes("_next/static/")) {
329
- void serveStaticFile(res, parsedUrl, staticBaseDirRelativePath);
330
- } else if (!isNextReady) {
331
- void nextReadyPromise.then(
332
- () => nextHandleRequest?.(req, res, parsedUrl)
333
- );
334
- } else {
335
- void nextHandleRequest?.(req, res, parsedUrl);
336
- }
337
- } catch (e) {
338
- console.error("caught error", e);
339
- res.writeHead(500);
340
- res.end();
341
- }
342
- });
343
- const { portAlreadyInUse } = await safeAsyncServerListen(devServer, port);
344
- if (!portAlreadyInUse) {
345
- console.log(chalk.greenBright(` React Email ${package_default.version}`));
346
- console.log(` Running preview at: http://localhost:${port}
347
- `);
348
- } else {
349
- const nextPortToTry = port + 1;
350
- console.warn(
351
- ` ${logSymbols2.warning} Port ${port} is already in use, trying ${nextPortToTry}`
352
- );
353
- return startDevServer(
354
- emailsDirRelativePath,
355
- staticBaseDirRelativePath,
356
- nextPortToTry
357
- );
358
- }
359
- devServer.on("close", async () => {
360
- await app.close();
361
- });
362
- devServer.on("error", (e) => {
363
- spinner.stopAndPersist({
364
- symbol: logSymbols2.error,
365
- text: `Preview Server had an error: ${e}`
366
- });
367
- process.exit(1);
368
- });
369
- const spinner = ora({
370
- text: "Getting react-email preview server ready...\n",
371
- prefixText: " "
372
- }).start();
373
- registerSpinnerAutostopping(spinner);
374
- const timeBeforeNextReady = performance.now();
375
- process.env = {
376
- NODE_ENV: "development",
377
- ...process.env,
378
- ...getEnvVariablesForPreviewApp(
379
- // If we don't do normalization here, stuff like https://github.com/resend/react-email/issues/1354 happens.
380
- path4.normalize(emailsDirRelativePath),
381
- process.cwd()
382
- )
383
- };
384
- const app = next({
385
- // passing in env here does not get the environment variables there
386
- dev: isDev,
387
- conf: {
388
- images: {
389
- // This is to avoid the warning with sharp
390
- unoptimized: true
391
- }
392
- },
393
- hostname: "localhost",
394
- port,
395
- dir: previewServerLocation
396
- });
397
- let isNextReady = false;
398
- const nextReadyPromise = app.prepare();
399
- try {
400
- await nextReadyPromise;
401
- } catch (exception) {
402
- spinner.stopAndPersist({
403
- symbol: logSymbols2.error,
404
- text: ` Preview Server had an error: ${exception}`
405
- });
406
- process.exit(1);
407
- }
408
- isNextReady = true;
409
- const nextHandleRequest = app.getRequestHandler();
410
- const secondsToNextReady = ((performance.now() - timeBeforeNextReady) / 1e3).toFixed(1);
411
- spinner.stopAndPersist({
412
- text: `Ready in ${secondsToNextReady}s
413
- `,
414
- symbol: logSymbols2.success
415
- });
416
- return devServer;
417
- };
418
- var makeExitHandler = (options) => (_codeOrSignal) => {
419
- if (typeof devServer !== "undefined") {
420
- console.log("\n shutting down dev server");
421
- devServer.close();
422
- devServer = void 0;
423
- }
424
- if (options?.shouldKillProcess) {
425
- process.exit(options.killWithErrorCode ? 1 : 0);
426
- }
427
- };
428
- process.on("exit", makeExitHandler());
429
- process.on(
430
- "SIGINT",
431
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
432
- );
433
- process.on(
434
- "SIGUSR1",
435
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
436
- );
437
- process.on(
438
- "SIGUSR2",
439
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
440
- );
441
- process.on(
442
- "uncaughtException",
443
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: true })
444
- );
445
-
446
- // src/cli/utils/preview/hot-reloading/get-imported-modules.ts
447
- import { parse } from "@babel/parser";
448
- import traverseModule from "@babel/traverse";
449
- var traverse = (
450
- // we keep this check here so that this still works with the dev:preview
451
- // script's use of tsx
452
- typeof traverseModule === "function" ? traverseModule : (
453
- // @ts-expect-error This is fine since the default export is wrapped in a
454
- // default function. The problem is that babel/traverse is not ESM.
455
- traverseModule.default
456
- )
457
- );
458
- var getImportedModules = (contents) => {
459
- const importedPaths = [];
460
- const parsedContents = parse(contents, {
461
- sourceType: "unambiguous",
462
- strictMode: false,
463
- errorRecovery: true,
464
- plugins: ["jsx", "typescript", "decorators"]
465
- });
466
- traverse(parsedContents, {
467
- ImportDeclaration({ node }) {
468
- importedPaths.push(node.source.value);
469
- },
470
- ExportAllDeclaration({ node }) {
471
- importedPaths.push(node.source.value);
472
- },
473
- ExportNamedDeclaration({ node }) {
474
- if (node.source) {
475
- importedPaths.push(node.source.value);
476
- }
477
- },
478
- TSExternalModuleReference({ node }) {
479
- importedPaths.push(node.expression.value);
480
- },
481
- CallExpression({ node }) {
482
- if ("name" in node.callee && node.callee.name === "require") {
483
- if (node.arguments.length === 1) {
484
- const importPathNode = node.arguments[0];
485
- if (importPathNode.type === "StringLiteral") {
486
- importedPaths.push(importPathNode.value);
487
- }
488
- }
489
- }
490
- }
491
- });
492
- return importedPaths;
493
- };
494
-
495
- // src/cli/utils/preview/hot-reloading/create-dependency-graph.ts
496
- var readAllFilesInsideDirectory = async (directory) => {
497
- let allFilePaths = [];
498
- const topLevelDirents = await fs3.readdir(directory, { withFileTypes: true });
499
- for await (const dirent of topLevelDirents) {
500
- const pathToDirent = path5.join(directory, dirent.name);
501
- if (dirent.isDirectory()) {
502
- allFilePaths = allFilePaths.concat(
503
- await readAllFilesInsideDirectory(pathToDirent)
504
- );
505
- } else {
506
- allFilePaths.push(pathToDirent);
507
- }
508
- }
509
- return allFilePaths;
510
- };
511
- var isJavascriptModule = (filePath) => {
512
- const extensionName = path5.extname(filePath);
513
- return [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"].includes(extensionName);
514
- };
515
- var checkFileExtensionsUntilItExists = (pathWithoutExtension) => {
516
- if (existsSync2(`${pathWithoutExtension}.ts`)) {
517
- return `${pathWithoutExtension}.ts`;
518
- }
519
- if (existsSync2(`${pathWithoutExtension}.tsx`)) {
520
- return `${pathWithoutExtension}.tsx`;
521
- }
522
- if (existsSync2(`${pathWithoutExtension}.js`)) {
523
- return `${pathWithoutExtension}.js`;
524
- }
525
- if (existsSync2(`${pathWithoutExtension}.jsx`)) {
526
- return `${pathWithoutExtension}.jsx`;
527
- }
528
- if (existsSync2(`${pathWithoutExtension}.mjs`)) {
529
- return `${pathWithoutExtension}.mjs`;
530
- }
531
- if (existsSync2(`${pathWithoutExtension}.cjs`)) {
532
- return `${pathWithoutExtension}.cjs`;
533
- }
534
- };
535
- var createDependencyGraph = async (directory) => {
536
- const filePaths = await readAllFilesInsideDirectory(directory);
537
- const modulePaths = filePaths.filter(isJavascriptModule);
538
- const graph = Object.fromEntries(
539
- modulePaths.map((path12) => [
540
- path12,
541
- {
542
- path: path12,
543
- dependencyPaths: [],
544
- dependentPaths: [],
545
- moduleDependencies: []
546
- }
547
- ])
548
- );
549
- const getDependencyPaths = async (filePath) => {
550
- const contents = await fs3.readFile(filePath, "utf8");
551
- const importedPaths = isJavascriptModule(filePath) ? getImportedModules(contents) : [];
552
- const importedPathsRelativeToDirectory = importedPaths.map(
553
- (dependencyPath) => {
554
- const isModulePath = !dependencyPath.startsWith(".");
555
- if (isModulePath || path5.isAbsolute(dependencyPath)) {
556
- return dependencyPath;
557
- }
558
- let pathToDependencyFromDirectory = path5.resolve(
559
- /*
560
- path.resolve resolves paths differently from what imports on javascript do.
561
-
562
- So if we wouldn't do this, for an email at "/path/to/email.tsx" with a dependency path of "./other-email"
563
- would end up going into /path/to/email.tsx/other-email instead of /path/to/other-email which is the
564
- one the import is meant to go to
565
- */
566
- path5.dirname(filePath),
567
- dependencyPath
568
- );
569
- let isDirectory = false;
570
- try {
571
- isDirectory = statSync(pathToDependencyFromDirectory).isDirectory();
572
- } catch (_) {
573
- }
574
- if (isDirectory) {
575
- const pathToSubDirectory = pathToDependencyFromDirectory;
576
- const pathWithExtension = checkFileExtensionsUntilItExists(
577
- `${pathToSubDirectory}/index`
578
- );
579
- if (pathWithExtension) {
580
- pathToDependencyFromDirectory = pathWithExtension;
581
- } else if (isDev) {
582
- console.warn(
583
- `Could not find index file for directory at ${pathToDependencyFromDirectory}. This is probably going to cause issues with both hot reloading and your code.`
584
- );
585
- }
586
- }
587
- const extension = path5.extname(pathToDependencyFromDirectory);
588
- const pathWithEnsuredExtension = (() => {
589
- if (extension.length > 0 && existsSync2(pathToDependencyFromDirectory)) {
590
- return pathToDependencyFromDirectory;
591
- }
592
- return checkFileExtensionsUntilItExists(
593
- pathToDependencyFromDirectory.replace(extension, "")
594
- );
595
- })();
596
- if (pathWithEnsuredExtension) {
597
- pathToDependencyFromDirectory = pathWithEnsuredExtension;
598
- } else if (isDev) {
599
- console.warn(
600
- `Could not find file at ${pathToDependencyFromDirectory}`
601
- );
602
- }
603
- return pathToDependencyFromDirectory;
604
- }
605
- );
606
- const moduleDependencies = importedPathsRelativeToDirectory.filter(
607
- (dependencyPath) => !dependencyPath.startsWith(".") && !path5.isAbsolute(dependencyPath)
608
- );
609
- const nonNodeModuleImportPathsRelativeToDirectory = importedPathsRelativeToDirectory.filter(
610
- (dependencyPath) => dependencyPath.startsWith(".") || path5.isAbsolute(dependencyPath)
611
- );
612
- return {
613
- dependencyPaths: nonNodeModuleImportPathsRelativeToDirectory,
614
- moduleDependencies
615
- };
616
- };
617
- const updateModuleDependenciesInGraph = async (moduleFilePath) => {
618
- if (graph[moduleFilePath] === void 0) {
619
- graph[moduleFilePath] = {
620
- path: moduleFilePath,
621
- dependencyPaths: [],
622
- dependentPaths: [],
623
- moduleDependencies: []
624
- };
625
- }
626
- const { moduleDependencies, dependencyPaths: newDependencyPaths } = await getDependencyPaths(moduleFilePath);
627
- graph[moduleFilePath].moduleDependencies = moduleDependencies;
628
- for (const dependencyPath of graph[moduleFilePath].dependencyPaths) {
629
- if (newDependencyPaths.includes(dependencyPath)) continue;
630
- const dependencyModule = graph[dependencyPath];
631
- if (dependencyModule !== void 0) {
632
- dependencyModule.dependentPaths = dependencyModule.dependentPaths.filter(
633
- (dependentPath) => dependentPath !== moduleFilePath
634
- );
635
- }
636
- }
637
- graph[moduleFilePath].dependencyPaths = newDependencyPaths;
638
- for await (const dependencyPath of newDependencyPaths) {
639
- if (graph[dependencyPath] === void 0) {
640
- await updateModuleDependenciesInGraph(dependencyPath);
641
- }
642
- const dependencyModule = graph[dependencyPath];
643
- if (dependencyModule === void 0) {
644
- throw new Error(
645
- `Loading the dependency path ${dependencyPath} did not initialize it at all. This is a bug in React Email.`
646
- );
647
- }
648
- if (!dependencyModule.dependentPaths.includes(moduleFilePath)) {
649
- dependencyModule.dependentPaths.push(moduleFilePath);
650
- }
651
- }
652
- };
653
- for (const filePath of modulePaths) {
654
- await updateModuleDependenciesInGraph(filePath);
655
- }
656
- const removeModuleFromGraph = (filePath) => {
657
- const module = graph[filePath];
658
- if (module) {
659
- for (const dependencyPath of module.dependencyPaths) {
660
- if (graph[dependencyPath]) {
661
- graph[dependencyPath].dependentPaths = graph[dependencyPath].dependentPaths.filter(
662
- (dependentPath) => dependentPath !== filePath
663
- );
664
- }
665
- }
666
- delete graph[filePath];
667
- }
668
- };
669
- return [
670
- graph,
671
- async (event, pathToModified) => {
672
- switch (event) {
673
- case "change":
674
- if (isJavascriptModule(pathToModified)) {
675
- await updateModuleDependenciesInGraph(pathToModified);
676
- }
677
- break;
678
- case "add":
679
- if (isJavascriptModule(pathToModified)) {
680
- await updateModuleDependenciesInGraph(pathToModified);
681
- }
682
- break;
683
- case "addDir": {
684
- const filesInsideAddedDirectory = await readAllFilesInsideDirectory(pathToModified);
685
- const modulesInsideAddedDirectory = filesInsideAddedDirectory.filter(isJavascriptModule);
686
- for await (const filePath of modulesInsideAddedDirectory) {
687
- await updateModuleDependenciesInGraph(filePath);
688
- }
689
- break;
690
- }
691
- case "unlink":
692
- if (isJavascriptModule(pathToModified)) {
693
- removeModuleFromGraph(pathToModified);
694
- }
695
- break;
696
- case "unlinkDir": {
697
- const filesInsideDeletedDirectory = await readAllFilesInsideDirectory(pathToModified);
698
- const modulesInsideDeletedDirectory = filesInsideDeletedDirectory.filter(isJavascriptModule);
699
- for await (const filePath of modulesInsideDeletedDirectory) {
700
- removeModuleFromGraph(filePath);
701
- }
702
- break;
703
- }
704
- }
705
- },
706
- {
707
- resolveDependentsOf: function resolveDependentsOf(pathToModule) {
708
- const moduleEntry = graph[pathToModule];
709
- const dependentPaths = [];
710
- if (moduleEntry) {
711
- for (const dependentPath of moduleEntry.dependentPaths) {
712
- const dependentsOfDependent = resolveDependentsOf(dependentPath);
713
- dependentPaths.push(...dependentsOfDependent);
714
- dependentPaths.push(dependentPath);
715
- }
716
- }
717
- return dependentPaths;
718
- }
719
- }
720
- ];
721
- };
722
-
723
- // src/cli/utils/preview/hot-reloading/setup-hot-reloading.ts
724
- var setupHotreloading = async (devServer2, emailDirRelativePath) => {
725
- let clients = [];
726
- const io = new SocketServer(devServer2);
727
- io.on("connection", (client) => {
728
- clients.push(client);
729
- client.on("disconnect", () => {
730
- clients = clients.filter((item) => item !== client);
731
- });
732
- });
733
- let changes = [];
734
- const reload = debounce(() => {
735
- clients.forEach((client) => {
736
- client.emit(
737
- "reload",
738
- changes.filter(
739
- (change) => (
740
- // Ensures only changes inside the emails directory are emitted
741
- path6.resolve(absolutePathToEmailsDirectory, change.filename).startsWith(absolutePathToEmailsDirectory)
742
- )
743
- )
744
- );
745
- });
746
- changes = [];
747
- }, 150);
748
- const absolutePathToEmailsDirectory = path6.resolve(
749
- process.cwd(),
750
- emailDirRelativePath
751
- );
752
- const [dependencyGraph, updateDependencyGraph, { resolveDependentsOf }] = await createDependencyGraph(absolutePathToEmailsDirectory);
753
- const watcher = watch("", {
754
- ignoreInitial: true,
755
- cwd: absolutePathToEmailsDirectory
756
- });
757
- const getFilesOutsideEmailsDirectory = () => Object.keys(dependencyGraph).filter(
758
- (p) => path6.relative(absolutePathToEmailsDirectory, p).startsWith("..")
759
- );
760
- let filesOutsideEmailsDirectory = getFilesOutsideEmailsDirectory();
761
- for (const p of filesOutsideEmailsDirectory) {
762
- watcher.add(p);
763
- }
764
- const exit = async () => {
765
- await watcher.close();
766
- };
767
- process.on("SIGINT", exit);
768
- process.on("uncaughtException", exit);
769
- watcher.on("all", async (event, relativePathToChangeTarget) => {
770
- const file = relativePathToChangeTarget.split(path6.sep);
771
- if (file.length === 0) {
772
- return;
773
- }
774
- const pathToChangeTarget = path6.resolve(
775
- absolutePathToEmailsDirectory,
776
- relativePathToChangeTarget
777
- );
778
- await updateDependencyGraph(event, pathToChangeTarget);
779
- const newFilesOutsideEmailsDirectory = getFilesOutsideEmailsDirectory();
780
- for (const p of filesOutsideEmailsDirectory) {
781
- if (!newFilesOutsideEmailsDirectory.includes(p)) {
782
- watcher.unwatch(p);
783
- }
784
- }
785
- for (const p of newFilesOutsideEmailsDirectory) {
786
- if (!filesOutsideEmailsDirectory.includes(p)) {
787
- watcher.add(p);
788
- }
789
- }
790
- filesOutsideEmailsDirectory = newFilesOutsideEmailsDirectory;
791
- changes.push({
792
- event,
793
- filename: relativePathToChangeTarget
794
- });
795
- for (const dependentPath of resolveDependentsOf(pathToChangeTarget)) {
796
- changes.push({
797
- event: "change",
798
- filename: path6.relative(absolutePathToEmailsDirectory, dependentPath)
799
- });
800
- }
801
- reload();
802
- });
803
- return watcher;
804
- };
805
-
806
- // src/cli/utils/tree.ts
807
- import { promises as fs4 } from "node:fs";
808
- import os from "node:os";
809
- import path7 from "node:path";
810
- var SYMBOLS = {
811
- BRANCH: "\u251C\u2500\u2500 ",
812
- EMPTY: "",
813
- INDENT: " ",
814
- LAST_BRANCH: "\u2514\u2500\u2500 ",
815
- VERTICAL: "\u2502 "
816
- };
817
- var getTreeLines = async (dirPath, depth, currentDepth = 0) => {
818
- const base = process.cwd();
819
- const dirFullpath = path7.resolve(base, dirPath);
820
- const dirname2 = path7.basename(dirFullpath);
821
- let lines = [dirname2];
822
- const dirStat = await fs4.stat(dirFullpath);
823
- if (dirStat.isDirectory() && currentDepth < depth) {
824
- const childDirents = await fs4.readdir(dirFullpath, { withFileTypes: true });
825
- childDirents.sort((a, b) => {
826
- if (a.isDirectory() && b.isFile()) {
827
- return -1;
828
- }
829
- if (a.isFile() && b.isDirectory()) {
830
- return 1;
831
- }
832
- return b.name > a.name ? -1 : 1;
833
- });
834
- for (let i = 0; i < childDirents.length; i++) {
835
- const dirent = childDirents[i];
836
- const isLast = i === childDirents.length - 1;
837
- const branchingSymbol = isLast ? SYMBOLS.LAST_BRANCH : SYMBOLS.BRANCH;
838
- const verticalSymbol = isLast ? SYMBOLS.INDENT : SYMBOLS.VERTICAL;
839
- if (dirent.isFile()) {
840
- lines.push(`${branchingSymbol}${dirent.name}`);
841
- } else {
842
- const pathToDirectory = path7.join(dirFullpath, dirent.name);
843
- const treeLinesForSubDirectory = await getTreeLines(
844
- pathToDirectory,
845
- depth,
846
- currentDepth + 1
847
- );
848
- lines = lines.concat(
849
- treeLinesForSubDirectory.map(
850
- (line, index) => index === 0 ? `${branchingSymbol}${line}` : `${verticalSymbol}${line}`
851
- )
852
- );
853
- }
854
- }
855
- }
856
- return lines;
857
- };
858
- var tree = async (dirPath, depth) => {
859
- const lines = await getTreeLines(dirPath, depth);
860
- return lines.join(os.EOL);
861
- };
862
-
863
- // src/cli/commands/build.ts
864
- var buildPreviewApp = (absoluteDirectory) => {
865
- return new Promise((resolve, reject) => {
866
- const nextBuild = spawn("npm", ["run", "build"], {
867
- cwd: absoluteDirectory,
868
- shell: true
869
- });
870
- nextBuild.stdout.pipe(process.stdout);
871
- nextBuild.stderr.pipe(process.stderr);
872
- nextBuild.on("close", (code) => {
873
- if (code === 0) {
874
- resolve();
875
- } else {
876
- reject(
877
- new Error(
878
- `Unable to build the Next app and it exited with code: ${code}`
879
- )
880
- );
881
- }
882
- });
883
- });
884
- };
885
- var setNextEnvironmentVariablesForBuild = async (emailsDirRelativePath, builtPreviewAppPath) => {
886
- const nextConfigContents = `
887
- const path = require('path');
888
- const emailsDirRelativePath = path.normalize('${emailsDirRelativePath}');
889
- const userProjectLocation = path.resolve(process.cwd(), '../');
890
- /** @type {import('next').NextConfig} */
891
- module.exports = {
892
- env: {
893
- NEXT_PUBLIC_IS_BUILDING: 'true',
894
- EMAILS_DIR_RELATIVE_PATH: emailsDirRelativePath,
895
- EMAILS_DIR_ABSOLUTE_PATH: path.resolve(userProjectLocation, emailsDirRelativePath),
896
- USER_PROJECT_LOCATION: userProjectLocation
897
- },
898
- // this is needed so that the code for building emails works properly
899
- webpack: (
900
- /** @type {import('webpack').Configuration & { externals: string[] }} */
901
- config,
902
- { isServer }
903
- ) => {
904
- if (isServer) {
905
- config.externals.push('esbuild');
906
- }
907
-
908
- return config;
909
- },
910
- typescript: {
911
- ignoreBuildErrors: true
912
- },
913
- eslint: {
914
- ignoreDuringBuilds: true
915
- },
916
- experimental: {
917
- webpackBuildWorker: true
918
- },
919
- }`;
920
- await fs5.promises.writeFile(
921
- path8.resolve(builtPreviewAppPath, "./next.config.js"),
922
- nextConfigContents,
923
- "utf8"
924
- );
925
- };
926
- var getEmailSlugsFromEmailDirectory = (emailDirectory, emailsDirectoryAbsolutePath) => {
927
- const directoryPathRelativeToEmailsDirectory = emailDirectory.absolutePath.replace(emailsDirectoryAbsolutePath, "").trim();
928
- const slugs = [];
929
- emailDirectory.emailFilenames.forEach(
930
- (filename3) => slugs.push(
931
- path8.join(directoryPathRelativeToEmailsDirectory, filename3).split(path8.sep).filter((segment) => segment.length > 0)
932
- )
933
- );
934
- emailDirectory.subDirectories.forEach((directory) => {
935
- slugs.push(
936
- ...getEmailSlugsFromEmailDirectory(
937
- directory,
938
- emailsDirectoryAbsolutePath
939
- )
940
- );
941
- });
942
- return slugs;
943
- };
944
- var forceSSGForEmailPreviews = async (emailsDirPath, builtPreviewAppPath) => {
945
- const emailDirectoryMetadata = (
946
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
947
- await getEmailsDirectoryMetadata(emailsDirPath)
948
- );
949
- const parameters = getEmailSlugsFromEmailDirectory(
950
- emailDirectoryMetadata,
951
- emailsDirPath
952
- ).map((slug) => ({ slug }));
953
- const removeForceDynamic = async (filePath) => {
954
- const contents = await fs5.promises.readFile(filePath, "utf8");
955
- await fs5.promises.writeFile(
956
- filePath,
957
- contents.replace("export const dynamic = 'force-dynamic';", ""),
958
- "utf8"
959
- );
960
- };
961
- await removeForceDynamic(
962
- path8.resolve(builtPreviewAppPath, "./src/app/layout.tsx")
963
- );
964
- await removeForceDynamic(
965
- path8.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx")
966
- );
967
- await fs5.promises.appendFile(
968
- path8.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx"),
969
- `
970
-
971
- export function generateStaticParams() {
972
- return Promise.resolve(
973
- ${JSON.stringify(parameters)}
974
- );
975
- }`,
976
- "utf8"
977
- );
978
- };
979
- var updatePackageJson = async (builtPreviewAppPath) => {
980
- const packageJsonPath = path8.resolve(builtPreviewAppPath, "./package.json");
981
- const packageJson = JSON.parse(
982
- await fs5.promises.readFile(packageJsonPath, "utf8")
983
- );
984
- packageJson.scripts.build = "next build";
985
- packageJson.scripts.start = "next start";
986
- packageJson.name = "preview-server";
987
- delete packageJson.devDependencies["@react-email/render"];
988
- delete packageJson.devDependencies["@react-email/components"];
989
- delete packageJson.scripts.prepare;
990
- await fs5.promises.writeFile(
991
- packageJsonPath,
992
- JSON.stringify(packageJson),
993
- "utf8"
994
- );
995
- };
996
- var npmInstall = async (builtPreviewAppPath, packageManager) => {
997
- return new Promise((resolve, reject) => {
998
- const childProc = spawn(
999
- packageManager,
1000
- [
1001
- "install",
1002
- packageManager === "deno" ? "" : "--include=dev",
1003
- packageManager === "deno" ? "--quiet" : "--silent"
1004
- ],
1005
- {
1006
- cwd: builtPreviewAppPath,
1007
- shell: true
1008
- }
1009
- );
1010
- childProc.stdout.pipe(process.stdout);
1011
- childProc.stderr.pipe(process.stderr);
1012
- childProc.on("close", (code) => {
1013
- if (code === 0) {
1014
- resolve();
1015
- } else {
1016
- reject(
1017
- new Error(
1018
- `Unable to install the dependencies and it exited with code: ${code}`
1019
- )
1020
- );
1021
- }
1022
- });
1023
- });
1024
- };
1025
- var build = async ({
1026
- dir: emailsDirRelativePath,
1027
- packageManager
1028
- }) => {
1029
- try {
1030
- const spinner = ora2({
1031
- text: "Starting build process...",
1032
- prefixText: " "
1033
- }).start();
1034
- registerSpinnerAutostopping(spinner);
1035
- spinner.text = `Checking if ${emailsDirRelativePath} folder exists`;
1036
- if (!fs5.existsSync(emailsDirRelativePath)) {
1037
- process.exit(1);
1038
- }
1039
- const emailsDirPath = path8.join(process.cwd(), emailsDirRelativePath);
1040
- const staticPath = path8.join(emailsDirPath, "static");
1041
- const builtPreviewAppPath = path8.join(process.cwd(), ".react-email");
1042
- if (fs5.existsSync(builtPreviewAppPath)) {
1043
- spinner.text = "Deleting pre-existing `.react-email` folder";
1044
- await fs5.promises.rm(builtPreviewAppPath, { recursive: true });
1045
- }
1046
- spinner.text = "Copying preview app from CLI to `.react-email`";
1047
- await fs5.promises.cp(cliPackageLocation, builtPreviewAppPath, {
1048
- recursive: true,
1049
- filter: (source) => {
1050
- return !/(\/|\\)cli(\/|\\)?/.test(source) && !/(\/|\\)\.next(\/|\\)?/.test(source) && !/(\/|\\)\.turbo(\/|\\)?/.test(source) && !/(\/|\\)node_modules(\/|\\)?$/.test(source);
1051
- }
1052
- });
1053
- if (fs5.existsSync(staticPath)) {
1054
- spinner.text = "Copying `static` folder into `.react-email/public/static`";
1055
- const builtStaticDirectory = path8.resolve(
1056
- builtPreviewAppPath,
1057
- "./public/static"
1058
- );
1059
- await fs5.promises.cp(staticPath, builtStaticDirectory, {
1060
- recursive: true
1061
- });
1062
- }
1063
- spinner.text = "Setting Next environment variables for preview app to work properly";
1064
- await setNextEnvironmentVariablesForBuild(
1065
- emailsDirRelativePath,
1066
- builtPreviewAppPath
1067
- );
1068
- spinner.text = "Setting server side generation for the email preview pages";
1069
- await forceSSGForEmailPreviews(emailsDirPath, builtPreviewAppPath);
1070
- spinner.text = "Updating package.json's build and start scripts";
1071
- await updatePackageJson(builtPreviewAppPath);
1072
- spinner.text = "Installing dependencies on `.react-email`";
1073
- await npmInstall(builtPreviewAppPath, packageManager);
1074
- spinner.stopAndPersist({
1075
- text: "Successfully prepared `.react-email` for `next build`",
1076
- symbol: logSymbols3.success
1077
- });
1078
- await buildPreviewApp(builtPreviewAppPath);
1079
- } catch (error) {
1080
- console.log(error);
1081
- process.exit(1);
1082
- }
1083
- };
1084
-
1085
- // src/cli/commands/dev.ts
1086
- import fs6 from "node:fs";
1087
- var dev = async ({ dir: emailsDirRelativePath, port }) => {
1088
- try {
1089
- if (!fs6.existsSync(emailsDirRelativePath)) {
1090
- console.error(`Missing ${emailsDirRelativePath} folder`);
1091
- process.exit(1);
1092
- }
1093
- const devServer2 = await startDevServer(
1094
- emailsDirRelativePath,
1095
- emailsDirRelativePath,
1096
- // defaults to ./emails/static for the static files that are served to the preview
1097
- Number.parseInt(port)
1098
- );
1099
- await setupHotreloading(devServer2, emailsDirRelativePath);
1100
- } catch (error) {
1101
- console.log(error);
1102
- process.exit(1);
1103
- }
1104
- };
1105
-
1106
- // src/cli/commands/export.ts
1107
- import fs8, { unlinkSync, writeFileSync } from "node:fs";
1108
- import { createRequire } from "node:module";
1109
- import path10 from "node:path";
1110
- import url2 from "node:url";
1111
- import { build as build2 } from "esbuild";
1112
- import { glob } from "glob";
1113
- import logSymbols4 from "log-symbols";
1114
- import normalize from "normalize-path";
1115
- import ora3 from "ora";
1116
-
1117
- // src/utils/esbuild/renderring-utilities-exporter.ts
1118
- import { promises as fs7 } from "node:fs";
1119
- import path9 from "node:path";
1120
-
1121
- // src/utils/esbuild/escape-string-for-regex.ts
1122
- function escapeStringForRegex(string) {
1123
- return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
1124
- }
1125
-
1126
- // src/utils/esbuild/renderring-utilities-exporter.ts
1127
- var renderingUtilitiesExporter = (emailTemplates) => ({
1128
- name: "rendering-utilities-exporter",
1129
- setup: (b) => {
1130
- b.onLoad(
1131
- {
1132
- filter: new RegExp(
1133
- emailTemplates.map((emailPath) => escapeStringForRegex(emailPath)).join("|")
1134
- )
1135
- },
1136
- async ({ path: pathToFile }) => {
1137
- return {
1138
- contents: `${await fs7.readFile(pathToFile, "utf8")};
1139
- export { render } from 'react-email-module-that-will-export-render'
1140
- export { createElement as reactEmailCreateReactElement } from 'react';
1141
- `,
1142
- loader: path9.extname(pathToFile).slice(1)
1143
- };
1144
- }
1145
- );
1146
- b.onResolve(
1147
- { filter: /^react-email-module-that-will-export-render$/ },
1148
- async (args) => {
1149
- const options = {
1150
- kind: "import-statement",
1151
- importer: args.importer,
1152
- resolveDir: args.resolveDir,
1153
- namespace: args.namespace
1154
- };
1155
- let result = await b.resolve("@react-email/render", options);
1156
- if (result.errors.length === 0) {
1157
- return result;
1158
- }
1159
- result = await b.resolve("@react-email/components", options);
1160
- if (result.errors.length > 0 && result.errors[0]) {
1161
- result.errors[0].text = "Failed trying to import `render` from either `@react-email/render` or `@react-email/components` to be able to render your email template.\n Maybe you don't have either of them installed?";
1162
- }
1163
- return result;
1164
- }
1165
- );
1166
- }
1167
- });
1168
-
1169
- // src/cli/commands/export.ts
1170
- var getEmailTemplatesFromDirectory = (emailDirectory) => {
1171
- const templatePaths = [];
1172
- emailDirectory.emailFilenames.forEach(
1173
- (filename3) => templatePaths.push(path10.join(emailDirectory.absolutePath, filename3))
1174
- );
1175
- emailDirectory.subDirectories.forEach((directory) => {
1176
- templatePaths.push(...getEmailTemplatesFromDirectory(directory));
1177
- });
1178
- return templatePaths;
1179
- };
1180
- var filename2 = url2.fileURLToPath(import.meta.url);
1181
- var require2 = createRequire(filename2);
1182
- var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirectoryPath, options) => {
1183
- if (fs8.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
1184
- fs8.rmSync(pathToWhereEmailMarkupShouldBeDumped, { recursive: true });
1185
- }
1186
- let spinner;
1187
- if (!options.silent) {
1188
- spinner = ora3("Preparing files...\n").start();
1189
- registerSpinnerAutostopping(spinner);
1190
- }
1191
- const emailsDirectoryMetadata = await getEmailsDirectoryMetadata(
1192
- path10.resolve(process.cwd(), emailsDirectoryPath),
1193
- true
1194
- );
1195
- if (typeof emailsDirectoryMetadata === "undefined") {
1196
- if (spinner) {
1197
- spinner.stopAndPersist({
1198
- symbol: logSymbols4.error,
1199
- text: `Could not find the directory at ${emailsDirectoryPath}`
1200
- });
1201
- }
1202
- return;
1203
- }
1204
- const allTemplates = getEmailTemplatesFromDirectory(emailsDirectoryMetadata);
1205
- try {
1206
- await build2({
1207
- bundle: true,
1208
- entryPoints: allTemplates,
1209
- format: "cjs",
1210
- jsx: "transform",
1211
- loader: { ".js": "jsx" },
1212
- logLevel: "silent",
1213
- outExtension: { ".js": ".cjs" },
1214
- outdir: pathToWhereEmailMarkupShouldBeDumped,
1215
- platform: "node",
1216
- plugins: [renderingUtilitiesExporter(allTemplates)],
1217
- write: true
1218
- });
1219
- } catch (exception) {
1220
- if (spinner) {
1221
- spinner.stopAndPersist({
1222
- symbol: logSymbols4.error,
1223
- text: "Failed to build emails"
1224
- });
1225
- }
1226
- const buildFailure = exception;
1227
- console.error(`
1228
- ${buildFailure.message}`);
1229
- process.exit(1);
1230
- }
1231
- if (spinner) {
1232
- spinner.succeed();
1233
- }
1234
- const allBuiltTemplates = glob.sync(
1235
- normalize(`${pathToWhereEmailMarkupShouldBeDumped}/**/*.cjs`),
1236
- {
1237
- absolute: true
1238
- }
1239
- );
1240
- for await (const template of allBuiltTemplates) {
1241
- try {
1242
- if (spinner) {
1243
- spinner.text = `rendering ${template.split("/").pop()}`;
1244
- spinner.render();
1245
- }
1246
- delete require2.cache[template];
1247
- const emailModule = require2(template);
1248
- const rendered = await emailModule.render(
1249
- emailModule.reactEmailCreateReactElement(emailModule.default, {}),
1250
- options
1251
- );
1252
- const htmlPath = template.replace(
1253
- ".cjs",
1254
- options.plainText ? ".txt" : ".html"
1255
- );
1256
- writeFileSync(htmlPath, rendered);
1257
- unlinkSync(template);
1258
- } catch (exception) {
1259
- if (spinner) {
1260
- spinner.stopAndPersist({
1261
- symbol: logSymbols4.error,
1262
- text: `failed when rendering ${template.split("/").pop()}`
1263
- });
1264
- }
1265
- console.error(exception);
1266
- process.exit(1);
1267
- }
1268
- }
1269
- if (spinner) {
1270
- spinner.succeed("Rendered all files");
1271
- spinner.text = "Copying static files";
1272
- spinner.render();
1273
- }
1274
- const staticDirectoryPath = path10.join(emailsDirectoryPath, "static");
1275
- if (fs8.existsSync(staticDirectoryPath)) {
1276
- const pathToDumpStaticFilesInto = path10.join(
1277
- pathToWhereEmailMarkupShouldBeDumped,
1278
- "static"
1279
- );
1280
- if (fs8.existsSync(pathToDumpStaticFilesInto))
1281
- await fs8.promises.rm(pathToDumpStaticFilesInto, { recursive: true });
1282
- try {
1283
- await fs8.promises.cp(staticDirectoryPath, pathToDumpStaticFilesInto, {
1284
- recursive: true
1285
- });
1286
- } catch (exception) {
1287
- console.error(exception);
1288
- if (spinner) {
1289
- spinner.stopAndPersist({
1290
- symbol: logSymbols4.error,
1291
- text: "Failed to copy static files"
1292
- });
1293
- }
1294
- console.error(
1295
- `Something went wrong while copying the file to ${pathToWhereEmailMarkupShouldBeDumped}/static, ${exception}`
1296
- );
1297
- process.exit(1);
1298
- }
1299
- }
1300
- if (spinner && !options.silent) {
1301
- spinner.succeed();
1302
- const fileTree = await tree(pathToWhereEmailMarkupShouldBeDumped, 4);
1303
- console.log(fileTree);
1304
- spinner.stopAndPersist({
1305
- symbol: logSymbols4.success,
1306
- text: "Successfully exported emails"
1307
- });
1308
- }
1309
- };
1310
-
1311
- // src/cli/commands/start.ts
1312
- import { spawn as spawn2 } from "node:child_process";
1313
- import fs9 from "node:fs";
1314
- import path11 from "node:path";
1315
- var start = async () => {
1316
- try {
1317
- const usersProjectLocation = process.cwd();
1318
- const builtPreviewPath = path11.resolve(
1319
- usersProjectLocation,
1320
- "./.react-email"
1321
- );
1322
- if (!fs9.existsSync(builtPreviewPath)) {
1323
- console.error(
1324
- "Could not find .react-email, maybe you haven't ran email build?"
1325
- );
1326
- process.exit(1);
1327
- }
1328
- const nextStart = spawn2("npm", ["start"], {
1329
- cwd: builtPreviewPath,
1330
- stdio: "inherit"
1331
- });
1332
- process.on("SIGINT", () => {
1333
- nextStart.kill("SIGINT");
1334
- });
1335
- nextStart.on("exit", (code) => {
1336
- process.exit(code ?? 0);
1337
- });
1338
- } catch (error) {
1339
- console.log(error);
1340
- process.exit(1);
1341
- }
1342
- };
1343
-
1344
- // src/cli/index.ts
1345
- var PACKAGE_NAME = "react-email";
1346
- program.name(PACKAGE_NAME).description("A live preview of your emails right in your browser").version(package_default.version);
1347
- program.command("dev").description("Starts the preview email development app").option("-d, --dir <path>", "Directory with your email templates", "./emails").option("-p --port <port>", "Port to run dev server on", "3000").action(dev);
1348
- program.command("build").description("Copies the preview app for onto .react-email and builds it").option("-d, --dir <path>", "Directory with your email templates", "./emails").option(
1349
- "-p --packageManager <name>",
1350
- "Package name to use on installation on `.react-email`",
1351
- "npm"
1352
- ).action(build);
1353
- program.command("start").description('Runs the built preview app that is inside of ".react-email"').action(start);
1354
- program.command("export").description("Build the templates to the `out` directory").option("--outDir <path>", "Output directory", "out").option("-p, --pretty", "Pretty print the output", false).option("-t, --plainText", "Set output format as plain text", false).option("-d, --dir <path>", "Directory with your email templates", "./emails").option(
1355
- "-s, --silent",
1356
- "To, or not to show a spinner with process information",
1357
- false
1358
- ).action(
1359
- ({ outDir, pretty, plainText, silent, dir: srcDir }) => exportTemplates(outDir, srcDir, { silent, plainText, pretty })
1360
- );
1361
- program.parse();