@react-email/preview-server 1.0.0-canary.0

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 (265) hide show
  1. package/.next/BUILD_ID +1 -0
  2. package/.next/app-build-manifest.json +44 -0
  3. package/.next/app-path-routes-manifest.json +6 -0
  4. package/.next/build-manifest.json +33 -0
  5. package/.next/diagnostics/build-diagnostics.json +6 -0
  6. package/.next/diagnostics/framework.json +1 -0
  7. package/.next/export-marker.json +6 -0
  8. package/.next/images-manifest.json +57 -0
  9. package/.next/next-minimal-server.js.nft.json +1 -0
  10. package/.next/next-server.js.nft.json +1 -0
  11. package/.next/package.json +1 -0
  12. package/.next/prerender-manifest.json +41 -0
  13. package/.next/react-loadable-manifest.json +1 -0
  14. package/.next/required-server-files.json +311 -0
  15. package/.next/routes-manifest.json +64 -0
  16. package/.next/server/app/_not-found/page.js +1 -0
  17. package/.next/server/app/_not-found/page.js.nft.json +1 -0
  18. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  19. package/.next/server/app/favicon.ico/route.js +1 -0
  20. package/.next/server/app/favicon.ico/route.js.nft.json +1 -0
  21. package/.next/server/app/favicon.ico.body +0 -0
  22. package/.next/server/app/favicon.ico.meta +1 -0
  23. package/.next/server/app/page.js +1 -0
  24. package/.next/server/app/page.js.nft.json +1 -0
  25. package/.next/server/app/page_client-reference-manifest.js +1 -0
  26. package/.next/server/app/preview/[...slug]/page.js +321 -0
  27. package/.next/server/app/preview/[...slug]/page.js.nft.json +1 -0
  28. package/.next/server/app/preview/[...slug]/page_client-reference-manifest.js +1 -0
  29. package/.next/server/app-paths-manifest.json +6 -0
  30. package/.next/server/chunks/134.js +6 -0
  31. package/.next/server/chunks/235.js +15 -0
  32. package/.next/server/chunks/278.js +1 -0
  33. package/.next/server/chunks/343.js +20 -0
  34. package/.next/server/chunks/428.js +14 -0
  35. package/.next/server/chunks/963.js +1 -0
  36. package/.next/server/chunks/999.js +1 -0
  37. package/.next/server/functions-config-manifest.json +4 -0
  38. package/.next/server/interception-route-rewrite-manifest.js +1 -0
  39. package/.next/server/middleware-build-manifest.js +1 -0
  40. package/.next/server/middleware-manifest.json +6 -0
  41. package/.next/server/middleware-react-loadable-manifest.js +1 -0
  42. package/.next/server/next-font-manifest.js +1 -0
  43. package/.next/server/next-font-manifest.json +1 -0
  44. package/.next/server/pages/500.html +1 -0
  45. package/.next/server/pages/_app.js +1 -0
  46. package/.next/server/pages/_app.js.nft.json +1 -0
  47. package/.next/server/pages/_document.js +1 -0
  48. package/.next/server/pages/_document.js.nft.json +1 -0
  49. package/.next/server/pages/_error.js +1 -0
  50. package/.next/server/pages/_error.js.nft.json +1 -0
  51. package/.next/server/pages-manifest.json +5 -0
  52. package/.next/server/server-reference-manifest.js +1 -0
  53. package/.next/server/server-reference-manifest.json +1 -0
  54. package/.next/server/webpack-runtime.js +1 -0
  55. package/.next/static/VkyJa9K30jCrKBesOgrQT/_buildManifest.js +1 -0
  56. package/.next/static/VkyJa9K30jCrKBesOgrQT/_ssgManifest.js +1 -0
  57. package/.next/static/chunks/107-3043079e7cb8bcae.js +1 -0
  58. package/.next/static/chunks/293-67391ef0e44ffa4f.js +1 -0
  59. package/.next/static/chunks/3bd82e28-cda2c00a924937c5.js +1 -0
  60. package/.next/static/chunks/45-1021fac82f766268.js +1 -0
  61. package/.next/static/chunks/484-1969fe871b27074e.js +1 -0
  62. package/.next/static/chunks/484-e02de792ff5f9ea5.js +1 -0
  63. package/.next/static/chunks/589-817d8691661d370e.js +1 -0
  64. package/.next/static/chunks/902-c34acb56733e0ce1.js +1 -0
  65. package/.next/static/chunks/app/_not-found/page-4cbc7dce3ad33336.js +1 -0
  66. package/.next/static/chunks/app/layout-74628781c0b7e7bf.js +1 -0
  67. package/.next/static/chunks/app/layout-daeba68330ab58bb.js +1 -0
  68. package/.next/static/chunks/app/page-55cf199b7ca71958.js +1 -0
  69. package/.next/static/chunks/app/preview/[...slug]/page-07dd9a701d0b3e56.js +1 -0
  70. package/.next/static/chunks/app/preview/[...slug]/page-61b0ea70a8d72916.js +1 -0
  71. package/.next/static/chunks/f33a14d2-ec7c5f0b91818561.js +6 -0
  72. package/.next/static/chunks/framework-b887e9fc751a9906.js +1 -0
  73. package/.next/static/chunks/main-9a03e7ba8acb1900.js +1 -0
  74. package/.next/static/chunks/main-app-5bc2d814f500db60.js +1 -0
  75. package/.next/static/chunks/pages/_app-542a93a5a214e1c0.js +1 -0
  76. package/.next/static/chunks/pages/_error-d5fe1b1612642f76.js +1 -0
  77. package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  78. package/.next/static/chunks/webpack-31c45daa2bd82a7b.js +1 -0
  79. package/.next/static/css/35e8811589f0962b.css +3 -0
  80. package/.next/static/j4oDiQwPKPQgK5jAoiUTk/_buildManifest.js +1 -0
  81. package/.next/static/j4oDiQwPKPQgK5jAoiUTk/_ssgManifest.js +1 -0
  82. package/.next/static/media/05613964ce6c782e-s.p.otf +0 -0
  83. package/.next/static/media/11c6126b9369e85e-s.p.otf +0 -0
  84. package/.next/static/media/26a46d62cd723877-s.woff2 +0 -0
  85. package/.next/static/media/26cb97734d8cb717-s.p.otf +0 -0
  86. package/.next/static/media/55c55f0601d81cf3-s.woff2 +0 -0
  87. package/.next/static/media/581909926a08bbc8-s.woff2 +0 -0
  88. package/.next/static/media/6d93bde91c0c2823-s.woff2 +0 -0
  89. package/.next/static/media/97e0cb1ae144a2a9-s.woff2 +0 -0
  90. package/.next/static/media/a34f9d1faa5f3315-s.p.woff2 +0 -0
  91. package/.next/static/media/bb6462617151f6b7-s.p.otf +0 -0
  92. package/.next/static/media/cf6daef822ab0142-s.p.otf +0 -0
  93. package/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
  94. package/.next/static/media/e4051546b3043204-s.p.otf +0 -0
  95. package/.next/static/media/logo.2ce2a759.png +0 -0
  96. package/.next/trace +27 -0
  97. package/.next/types/app/layout.ts +84 -0
  98. package/.next/types/app/page.ts +84 -0
  99. package/.next/types/app/preview/[...slug]/page.ts +84 -0
  100. package/.next/types/cache-life.d.ts +141 -0
  101. package/.next/types/package.json +1 -0
  102. package/_index.js +4 -0
  103. package/license.md +7 -0
  104. package/module-punycode.d.ts +3 -0
  105. package/next-env.d.ts +5 -0
  106. package/next.config.js +22 -0
  107. package/package.json +82 -0
  108. package/postcss.config.js +8 -0
  109. package/scripts/build-preview-server.mjs +29 -0
  110. package/scripts/fill-caniemail-data.mjs +36 -0
  111. package/src/actions/email-validation/caniemail-data.ts +85993 -0
  112. package/src/actions/email-validation/check-compatibility.ts +333 -0
  113. package/src/actions/email-validation/check-images.spec.tsx +100 -0
  114. package/src/actions/email-validation/check-images.ts +160 -0
  115. package/src/actions/email-validation/check-links.spec.tsx +113 -0
  116. package/src/actions/email-validation/check-links.ts +113 -0
  117. package/src/actions/email-validation/get-code-location-from-ast-element.ts +18 -0
  118. package/src/actions/email-validation/quick-fetch.ts +14 -0
  119. package/src/actions/get-email-path-from-slug.ts +32 -0
  120. package/src/actions/get-emails-directory-metadata-action.ts +19 -0
  121. package/src/actions/render-email-by-path.tsx +121 -0
  122. package/src/animated-icons-data/help.json +1082 -0
  123. package/src/animated-icons-data/link.json +1309 -0
  124. package/src/animated-icons-data/load.json +443 -0
  125. package/src/animated-icons-data/mail.json +1320 -0
  126. package/src/app/env.ts +15 -0
  127. package/src/app/favicon.ico +0 -0
  128. package/src/app/fonts/SFMono/SFMonoBold.otf +0 -0
  129. package/src/app/fonts/SFMono/SFMonoBoldItalic.otf +0 -0
  130. package/src/app/fonts/SFMono/SFMonoHeavy.otf +0 -0
  131. package/src/app/fonts/SFMono/SFMonoHeavyItalic.otf +0 -0
  132. package/src/app/fonts/SFMono/SFMonoLight.otf +0 -0
  133. package/src/app/fonts/SFMono/SFMonoLightItalic.otf +0 -0
  134. package/src/app/fonts/SFMono/SFMonoMedium.otf +0 -0
  135. package/src/app/fonts/SFMono/SFMonoMediumItalic.otf +0 -0
  136. package/src/app/fonts/SFMono/SFMonoRegular.otf +0 -0
  137. package/src/app/fonts/SFMono/SFMonoRegularItalic.otf +0 -0
  138. package/src/app/fonts/SFMono/SFMonoSemibold.otf +0 -0
  139. package/src/app/fonts/SFMono/SFMonoSemiboldItalic.otf +0 -0
  140. package/src/app/fonts.ts +39 -0
  141. package/src/app/globals.css +15 -0
  142. package/src/app/layout.tsx +43 -0
  143. package/src/app/logo.png +0 -0
  144. package/src/app/page.tsx +46 -0
  145. package/src/app/preview/[...slug]/page.tsx +157 -0
  146. package/src/app/preview/[...slug]/preview.tsx +216 -0
  147. package/src/app/preview/[...slug]/rendering-error.tsx +40 -0
  148. package/src/components/button.tsx +101 -0
  149. package/src/components/code-container.tsx +164 -0
  150. package/src/components/code-snippet.tsx +9 -0
  151. package/src/components/code.tsx +184 -0
  152. package/src/components/heading.tsx +113 -0
  153. package/src/components/icons/icon-arrow-down.tsx +16 -0
  154. package/src/components/icons/icon-base.tsx +26 -0
  155. package/src/components/icons/icon-bug.tsx +19 -0
  156. package/src/components/icons/icon-button.tsx +23 -0
  157. package/src/components/icons/icon-check.tsx +19 -0
  158. package/src/components/icons/icon-clipboard.tsx +40 -0
  159. package/src/components/icons/icon-download.tsx +19 -0
  160. package/src/components/icons/icon-email.tsx +18 -0
  161. package/src/components/icons/icon-file.tsx +19 -0
  162. package/src/components/icons/icon-folder-open.tsx +19 -0
  163. package/src/components/icons/icon-folder.tsx +18 -0
  164. package/src/components/icons/icon-hide-sidebar.tsx +23 -0
  165. package/src/components/icons/icon-image.tsx +19 -0
  166. package/src/components/icons/icon-info.tsx +18 -0
  167. package/src/components/icons/icon-link.tsx +14 -0
  168. package/src/components/icons/icon-monitor.tsx +19 -0
  169. package/src/components/icons/icon-phone.tsx +26 -0
  170. package/src/components/icons/icon-reload.tsx +18 -0
  171. package/src/components/icons/icon-source.tsx +19 -0
  172. package/src/components/icons/icon-stamp.tsx +14 -0
  173. package/src/components/icons/icon-warning.tsx +31 -0
  174. package/src/components/index.ts +7 -0
  175. package/src/components/logo.tsx +63 -0
  176. package/src/components/resizable-wrapper.tsx +173 -0
  177. package/src/components/send.tsx +134 -0
  178. package/src/components/shell.tsx +92 -0
  179. package/src/components/sidebar/file-tree-directory-children.tsx +139 -0
  180. package/src/components/sidebar/file-tree-directory.tsx +92 -0
  181. package/src/components/sidebar/file-tree.tsx +31 -0
  182. package/src/components/sidebar/index.ts +1 -0
  183. package/src/components/sidebar/sidebar.tsx +43 -0
  184. package/src/components/text.tsx +99 -0
  185. package/src/components/toolbar/checking-results.tsx +150 -0
  186. package/src/components/toolbar/code-preview-line-link.tsx +40 -0
  187. package/src/components/toolbar/compatibility.tsx +113 -0
  188. package/src/components/toolbar/linter.tsx +278 -0
  189. package/src/components/toolbar/results-table.tsx +0 -0
  190. package/src/components/toolbar/results.tsx +51 -0
  191. package/src/components/toolbar/spam-assassin.tsx +155 -0
  192. package/src/components/toolbar/toolbar-button.tsx +52 -0
  193. package/src/components/toolbar/use-cached-state.ts +33 -0
  194. package/src/components/toolbar.tsx +349 -0
  195. package/src/components/tooltip-content.tsx +31 -0
  196. package/src/components/tooltip.tsx +19 -0
  197. package/src/components/topbar/active-view-toggle-group.tsx +86 -0
  198. package/src/components/topbar/view-size-controls.tsx +247 -0
  199. package/src/components/topbar.tsx +59 -0
  200. package/src/contexts/emails.tsx +59 -0
  201. package/src/contexts/fragment-identifier.tsx +48 -0
  202. package/src/contexts/preview.tsx +79 -0
  203. package/src/hooks/use-clamped-state.ts +24 -0
  204. package/src/hooks/use-email-rendering-result.ts +58 -0
  205. package/src/hooks/use-fragment-identifier.ts +14 -0
  206. package/src/hooks/use-hot-reload.ts +31 -0
  207. package/src/hooks/use-icon-animation.ts +41 -0
  208. package/src/hooks/use-rendering-metadata.ts +36 -0
  209. package/src/utils/__snapshots__/get-email-component.spec.ts.snap +3 -0
  210. package/src/utils/caniemail/all-css-properties.ts +358 -0
  211. package/src/utils/caniemail/ast/__snapshots__/get-object-variables.spec.ts.snap +74 -0
  212. package/src/utils/caniemail/ast/__snapshots__/get-used-style-properties.spec.ts.snap +24 -0
  213. package/src/utils/caniemail/ast/get-object-variables.spec.ts +19 -0
  214. package/src/utils/caniemail/ast/get-object-variables.ts +61 -0
  215. package/src/utils/caniemail/ast/get-used-style-properties.spec.ts +23 -0
  216. package/src/utils/caniemail/ast/get-used-style-properties.ts +91 -0
  217. package/src/utils/caniemail/get-compatibility-stats-for-entry.ts +118 -0
  218. package/src/utils/caniemail/get-css-functions.ts +25 -0
  219. package/src/utils/caniemail/get-css-property-names.ts +32 -0
  220. package/src/utils/caniemail/get-css-property-with-value.ts +14 -0
  221. package/src/utils/caniemail/get-css-unit.ts +3 -0
  222. package/src/utils/caniemail/get-element-attributes.ts +7 -0
  223. package/src/utils/caniemail/get-element-names.ts +20 -0
  224. package/src/utils/caniemail/tailwind/generate-tailwind-rules.ts +30 -0
  225. package/src/utils/caniemail/tailwind/get-tailwind-config.ts +187 -0
  226. package/src/utils/caniemail/tailwind/get-tailwind-metadata.spec.ts +25 -0
  227. package/src/utils/caniemail/tailwind/get-tailwind-metadata.ts +45 -0
  228. package/src/utils/caniemail/tailwind/setup-tailwind-context.ts +15 -0
  229. package/src/utils/cn.ts +6 -0
  230. package/src/utils/constants.ts +6 -0
  231. package/src/utils/contains-email-template.spec.ts +124 -0
  232. package/src/utils/contains-email-template.ts +33 -0
  233. package/src/utils/copy-text-to-clipboard.ts +7 -0
  234. package/src/utils/esbuild/escape-string-for-regex.ts +3 -0
  235. package/src/utils/esbuild/renderring-utilities-exporter.ts +63 -0
  236. package/src/utils/get-email-component.spec.ts +41 -0
  237. package/src/utils/get-email-component.ts +134 -0
  238. package/src/utils/get-emails-directory-metadata.spec.ts +82 -0
  239. package/src/utils/get-emails-directory-metadata.ts +141 -0
  240. package/src/utils/get-line-and-column-from-offset.spec.ts +11 -0
  241. package/src/utils/get-line-and-column-from-offset.ts +11 -0
  242. package/src/utils/improve-error-with-sourcemap.ts +85 -0
  243. package/src/utils/index.ts +6 -0
  244. package/src/utils/js-email-detection.spec.ts +24 -0
  245. package/src/utils/language-map.ts +7 -0
  246. package/src/utils/linting.ts +60 -0
  247. package/src/utils/load-stream.ts +15 -0
  248. package/src/utils/register-spinner-autostopping.ts +28 -0
  249. package/src/utils/result.ts +49 -0
  250. package/src/utils/run-bundled-code.ts +64 -0
  251. package/src/utils/sanitize.ts +6 -0
  252. package/src/utils/static-node-modules-for-vm.ts +93 -0
  253. package/src/utils/testing/js-email-export-default.js +17 -0
  254. package/src/utils/testing/js-email-test.js +18 -0
  255. package/src/utils/testing/mdx-email-test.js +128 -0
  256. package/src/utils/testing/request-response-email.tsx +9 -0
  257. package/src/utils/types/as.ts +26 -0
  258. package/src/utils/types/email-template.ts +8 -0
  259. package/src/utils/types/error-object.ts +11 -0
  260. package/src/utils/types/hot-reload-change.ts +13 -0
  261. package/src/utils/unreachable.ts +8 -0
  262. package/tailwind-internals.d.ts +133 -0
  263. package/tailwind.config.ts +99 -0
  264. package/tsconfig.json +45 -0
  265. package/vitest.config.ts +15 -0
@@ -0,0 +1,85 @@
1
+ import path from 'node:path';
2
+ import { type RawSourceMap, SourceMapConsumer } from 'source-map-js';
3
+ import * as stackTraceParser from 'stacktrace-parser';
4
+ import type { ErrorObject } from './types/error-object';
5
+
6
+ export const improveErrorWithSourceMap = (
7
+ error: Error,
8
+
9
+ originalFilePath: string,
10
+ sourceMapToOriginalFile: RawSourceMap,
11
+ ): ErrorObject => {
12
+ let stack: string | undefined;
13
+
14
+ const sourceRoot =
15
+ sourceMapToOriginalFile.sourceRoot ?? path.dirname(originalFilePath);
16
+
17
+ const getStackLineFromMethodNameAndSource = (
18
+ methodName: string,
19
+ source: string,
20
+ line: number | undefined | null,
21
+ column: number | undefined | null,
22
+ ) => {
23
+ const columnAndLine =
24
+ column || line
25
+ ? `${line ?? ''}${line && column ? ':' : ''}${column ?? ''}`
26
+ : undefined;
27
+ const sourceToDisplay = path.relative(sourceRoot, source);
28
+ return methodName === '<unknown>'
29
+ ? ` at ${sourceToDisplay}${columnAndLine ? `:${columnAndLine}` : ''}`
30
+ : ` at ${methodName} (${sourceToDisplay}${
31
+ columnAndLine ? `:${columnAndLine}` : ''
32
+ })`;
33
+ };
34
+
35
+ if (typeof error.stack !== 'undefined') {
36
+ const parsedStack = stackTraceParser.parse(error.stack);
37
+ const sourceMapConsumer = new SourceMapConsumer(sourceMapToOriginalFile);
38
+ const newStackLines = [] as string[];
39
+ for (const stackFrame of parsedStack) {
40
+ if (stackFrame.file === originalFilePath) {
41
+ if (stackFrame.column || stackFrame.lineNumber) {
42
+ const positionWithError = sourceMapConsumer.originalPositionFor({
43
+ column: stackFrame.column ?? 0,
44
+ line: stackFrame.lineNumber ?? 0,
45
+ });
46
+
47
+ newStackLines.push(
48
+ getStackLineFromMethodNameAndSource(
49
+ stackFrame.methodName,
50
+ // This can actually be null
51
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
52
+ positionWithError.source ?? stackFrame.file,
53
+ positionWithError.line,
54
+ positionWithError.column,
55
+ ),
56
+ );
57
+ } else {
58
+ newStackLines.push(
59
+ getStackLineFromMethodNameAndSource(
60
+ stackFrame.methodName,
61
+ stackFrame.file,
62
+ stackFrame.lineNumber,
63
+ stackFrame.column,
64
+ ),
65
+ );
66
+ }
67
+ } else if (stackFrame.file) {
68
+ const stackLine = getStackLineFromMethodNameAndSource(
69
+ stackFrame.methodName,
70
+ stackFrame.file,
71
+ stackFrame.lineNumber,
72
+ stackFrame.column,
73
+ );
74
+ newStackLines.push(stackLine);
75
+ }
76
+ }
77
+ stack = newStackLines.join('\n');
78
+ }
79
+
80
+ return {
81
+ name: error.name,
82
+ message: error.message,
83
+ stack,
84
+ };
85
+ };
@@ -0,0 +1,6 @@
1
+ export * from './cn';
2
+ export * from './copy-text-to-clipboard';
3
+ export * from './language-map';
4
+ export * from './sanitize';
5
+ export * from './types/as';
6
+ export * from './unreachable';
@@ -0,0 +1,24 @@
1
+ import path from 'node:path';
2
+ import { getEmailsDirectoryMetadata } from './get-emails-directory-metadata';
3
+
4
+ describe('JavaScript Email Detection', async () => {
5
+ const testingDir = path.resolve(__dirname, 'testing');
6
+ const emailsMetadata = await getEmailsDirectoryMetadata(testingDir, true);
7
+
8
+ it('should detect JavaScript files with ES6 export default syntax', async () => {
9
+ expect(emailsMetadata).toBeDefined();
10
+ expect(emailsMetadata?.emailFilenames).toContain(
11
+ 'js-email-export-default.js',
12
+ );
13
+ });
14
+
15
+ it('should detect JavaScript files with CommonJS module.exports', async () => {
16
+ expect(emailsMetadata).toBeDefined();
17
+ expect(emailsMetadata?.emailFilenames).toContain('js-email-test.js');
18
+ });
19
+
20
+ it('should detect MDX-style JavaScript files with named exports', async () => {
21
+ expect(emailsMetadata).toBeDefined();
22
+ expect(emailsMetadata?.emailFilenames).toContain('mdx-email-test.js');
23
+ });
24
+ });
@@ -0,0 +1,7 @@
1
+ const languageMap = {
2
+ jsx: 'React',
3
+ markup: 'HTML',
4
+ markdown: 'Plain Text',
5
+ };
6
+
7
+ export default languageMap;
@@ -0,0 +1,60 @@
1
+ import { checkImages } from '../actions/email-validation/check-images';
2
+ import { checkLinks } from '../actions/email-validation/check-links';
3
+ import type { LintingRow } from '../components/toolbar/linter';
4
+ import { loadStream } from './load-stream';
5
+
6
+ export interface LintingSource<T> {
7
+ getStream(): Promise<ReadableStream<T>>;
8
+ mapValue(value: NoInfer<T>): LintingRow | undefined;
9
+ }
10
+
11
+ function createSource<T>(source: LintingSource<T>): LintingSource<T> {
12
+ return source;
13
+ }
14
+
15
+ export function getLintingSources(
16
+ markup: string,
17
+
18
+ urlBase: string,
19
+ ): LintingSource<unknown>[] {
20
+ return [
21
+ createSource({
22
+ getStream() {
23
+ return checkImages(markup, urlBase);
24
+ },
25
+ mapValue(result) {
26
+ if (result && result.status !== 'success') {
27
+ return {
28
+ result: result,
29
+ source: 'image',
30
+ };
31
+ }
32
+ },
33
+ }),
34
+ createSource({
35
+ getStream() {
36
+ return checkLinks(markup);
37
+ },
38
+ mapValue(result) {
39
+ if (result && result.status !== 'success') {
40
+ return {
41
+ result: result,
42
+ source: 'link',
43
+ };
44
+ }
45
+ },
46
+ }),
47
+ ];
48
+ }
49
+
50
+ export async function* loadLintingRowsFrom(sources: LintingSource<unknown>[]) {
51
+ for await (const source of sources) {
52
+ const stream = await source.getStream();
53
+ for await (const value of loadStream(stream)) {
54
+ const row = source.mapValue(value);
55
+ if (row) {
56
+ yield row;
57
+ }
58
+ }
59
+ }
60
+ }
@@ -0,0 +1,15 @@
1
+ export async function* loadStream<T>(stream: ReadableStream<T>) {
2
+ const reader = stream.getReader();
3
+ try {
4
+ while (true) {
5
+ const { value, done } = await reader.read();
6
+ if (done) {
7
+ break;
8
+ }
9
+
10
+ yield value;
11
+ }
12
+ } finally {
13
+ reader.releaseLock();
14
+ }
15
+ }
@@ -0,0 +1,28 @@
1
+ import logSymbols from 'log-symbols';
2
+ import type { Ora } from 'ora';
3
+
4
+ const spinners = new Set<Ora>();
5
+
6
+ process.on('SIGINT', () => {
7
+ spinners.forEach((spinner) => {
8
+ if (spinner.isSpinning) {
9
+ spinner.stop();
10
+ }
11
+ });
12
+ });
13
+
14
+ process.on('exit', (code) => {
15
+ if (code !== 0) {
16
+ spinners.forEach((spinner) => {
17
+ if (spinner.isSpinning) {
18
+ spinner.stopAndPersist({
19
+ symbol: logSymbols.error,
20
+ });
21
+ }
22
+ });
23
+ }
24
+ });
25
+
26
+ export const registerSpinnerAutostopping = (spinner: Ora) => {
27
+ spinners.add(spinner);
28
+ };
@@ -0,0 +1,49 @@
1
+ type Ok<T, _E> = {
2
+ value: T;
3
+ };
4
+ type Error<_T, E> = {
5
+ error: E;
6
+ };
7
+
8
+ /**
9
+ * Do not destructure this object, it is meant to have all fields together
10
+ * in the same object
11
+ */
12
+ export type Result<T, E> = Ok<T, E> | Error<T, E>;
13
+
14
+ export function isErr<T, E>(result: Result<T, E>): result is Error<T, E> {
15
+ return 'error' in result;
16
+ }
17
+
18
+ export function isOk<T, E>(result: Result<T, E>): result is Ok<T, E> {
19
+ return 'value' in result && !('error' in result);
20
+ }
21
+
22
+ export function mapResult<T, E, B>(
23
+ result: Result<T, E>,
24
+ callback: (value: T) => B,
25
+ ): Result<B, E> {
26
+ if (isOk(result)) {
27
+ return ok(callback(result.value));
28
+ }
29
+
30
+ return result;
31
+ }
32
+
33
+ export function ok<T, E>(value: NoInfer<T>): Ok<T, E>;
34
+ // biome-ignore lint/suspicious/noConfusingVoidType: This is required for void return types on functions that can still error
35
+ export function ok<T extends void = void, E = never>(value: void): Ok<void, E>;
36
+ export function ok<T, E>(value: NoInfer<T>): Ok<T, E> {
37
+ return {
38
+ value,
39
+ };
40
+ }
41
+
42
+ export function err<T, E>(error: NoInfer<E>): Error<T, E>;
43
+ // biome-ignore lint/suspicious/noConfusingVoidType: This is required for void return types on functions that can still error
44
+ export function err<T, E extends void = void>(error: void): Error<T, void>;
45
+ export function err<T, E>(error: NoInfer<E>): Error<T, E> {
46
+ return {
47
+ error,
48
+ };
49
+ }
@@ -0,0 +1,64 @@
1
+ import path from 'node:path';
2
+ import vm from 'node:vm';
3
+ import { err, ok, type Result } from './result';
4
+ import { staticNodeModulesForVM } from './static-node-modules-for-vm';
5
+
6
+ export const runBundledCode = (
7
+ code: string,
8
+ filename: string,
9
+ ): Result<unknown, unknown> => {
10
+ const fakeContext = {
11
+ ...global,
12
+ console,
13
+ Buffer,
14
+ AbortSignal,
15
+ Event,
16
+ EventTarget,
17
+ TextDecoder,
18
+ Request,
19
+ Response,
20
+ TextDecoderStream,
21
+ TextEncoder,
22
+ TextEncoderStream,
23
+ ReadableStream,
24
+ URL,
25
+ URLSearchParams,
26
+ Headers,
27
+ module: {
28
+ exports: {},
29
+ },
30
+ __filename: filename,
31
+ __dirname: path.dirname(filename),
32
+ require: (specifiedModule: string) => {
33
+ let m = specifiedModule;
34
+ if (specifiedModule.startsWith('node:')) {
35
+ m = m.split(':')[1]!;
36
+ }
37
+
38
+ if (m in staticNodeModulesForVM) {
39
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
40
+ return staticNodeModulesForVM[m];
41
+ }
42
+
43
+ // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-useless-template-literals
44
+ return require(`${specifiedModule}`) as unknown;
45
+ // this stupid string templating was necessary to not have
46
+ // webpack warnings like:
47
+ //
48
+ // Import trace for requested module:
49
+ // ./src/utils/get-email-component.tsx
50
+ // ./src/app/page.tsx
51
+ // ⚠ ./src/utils/get-email-component.tsx
52
+ // Critical dependency: the request of a dependency is an expression
53
+ },
54
+ process,
55
+ };
56
+
57
+ try {
58
+ vm.runInNewContext(code, fakeContext, { filename });
59
+ } catch (exception) {
60
+ return err(exception);
61
+ }
62
+
63
+ return ok(fakeContext.module.exports as unknown);
64
+ };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Sanitizes text by replacing underscores and hyphens with spaces
3
+ */
4
+ export const sanitize = (text: string): string => {
5
+ return text.replace(/[_-]/g, ' ');
6
+ };
@@ -0,0 +1,93 @@
1
+ import assert from 'node:assert';
2
+ import asyncHooks from 'node:async_hooks';
3
+ import buffer from 'node:buffer';
4
+ import childProcess from 'node:child_process';
5
+ import cluster from 'node:cluster';
6
+ import console from 'node:console';
7
+ import constants from 'node:constants';
8
+ import crypto from 'node:crypto';
9
+ import dgram from 'node:dgram';
10
+ import diagnosticsChannel from 'node:diagnostics_channel';
11
+ import dns from 'node:dns';
12
+ import domain from 'node:domain';
13
+ import events from 'node:events';
14
+ import fs from 'node:fs';
15
+ import fsPromises from 'node:fs/promises';
16
+ import http from 'node:http';
17
+ import http2 from 'node:http2';
18
+ import https from 'node:https';
19
+ import inspector from 'node:inspector';
20
+ import module from 'node:module';
21
+ import net from 'node:net';
22
+ import os from 'node:os';
23
+ import path from 'node:path';
24
+ import perfHooks from 'node:perf_hooks';
25
+ import process from 'node:process';
26
+ import querystring from 'node:querystring';
27
+ import readline from 'node:readline';
28
+ import repl from 'node:repl';
29
+ import stream from 'node:stream';
30
+ import stringDecoder from 'node:string_decoder';
31
+ import timers from 'node:timers';
32
+ import timersPromises from 'node:timers/promises';
33
+ import tls from 'node:tls';
34
+ import tty from 'node:tty';
35
+ import url from 'node:url';
36
+ import util from 'node:util';
37
+ import utilTypes from 'node:util/types';
38
+ import v8 from 'node:v8';
39
+ import vm from 'node:vm';
40
+ import workerThreads from 'node:worker_threads';
41
+ import zlib from 'node:zlib';
42
+ // See https://github.com/resend/react-email/issues/1841#issuecomment-2589985562
43
+ import punycode from 'module-punycode';
44
+
45
+ /**
46
+ * A map of the name of the modules (including `node:` prefixed ones)
47
+ * provided by Node because dynamic requires of them, even on the server
48
+ * will not be resolved properly
49
+ */
50
+ export const staticNodeModulesForVM = {
51
+ assert,
52
+ async_hooks: asyncHooks,
53
+ buffer,
54
+ child_process: childProcess,
55
+ cluster,
56
+ console,
57
+ constants,
58
+ crypto,
59
+ dgram,
60
+ diagnostics_channel: diagnosticsChannel,
61
+ dns,
62
+ domain,
63
+ events,
64
+ fs,
65
+ 'fs/promises': fsPromises,
66
+ http,
67
+ http2,
68
+ https,
69
+ inspector,
70
+ module,
71
+ net,
72
+ os,
73
+ path,
74
+ perf_hooks: perfHooks,
75
+ process,
76
+ punycode,
77
+ querystring,
78
+ readline,
79
+ repl,
80
+ stream,
81
+ string_decoder: stringDecoder,
82
+ timers,
83
+ 'timers/promises': timersPromises,
84
+ tls,
85
+ tty,
86
+ url,
87
+ util,
88
+ 'util/types': utilTypes,
89
+ v8,
90
+ vm,
91
+ worker_threads: workerThreads,
92
+ zlib,
93
+ };
@@ -0,0 +1,17 @@
1
+ // A JavaScript email component with ES6 export default
2
+ import { Button, Html } from '@react-email/components';
3
+
4
+ function Email() {
5
+ return (
6
+ <Html>
7
+ <Button
8
+ href="https://example.com"
9
+ style={{ background: '#000', color: '#fff', padding: '12px 20px' }}
10
+ >
11
+ Click me
12
+ </Button>
13
+ </Html>
14
+ );
15
+ }
16
+
17
+ export default Email;
@@ -0,0 +1,18 @@
1
+ // A simple JavaScript email component
2
+ const React = require('react');
3
+ const { Html, Button } = require('@react-email/components');
4
+
5
+ function Email() {
6
+ return (
7
+ <Html>
8
+ <Button
9
+ href="https://example.com"
10
+ style={{ background: '#000', color: '#fff', padding: '12px 20px' }}
11
+ >
12
+ Click me
13
+ </Button>
14
+ </Html>
15
+ );
16
+ }
17
+
18
+ module.exports = Email;
@@ -0,0 +1,128 @@
1
+ import { Button, Html } from '@react-email/components';
2
+ import { useMDXComponents as _provideComponents } from 'react';
3
+ import {
4
+ Fragment as _Fragment,
5
+ jsxDEV as _jsxDEV,
6
+ } from 'react/jsx-dev-runtime';
7
+
8
+ const MDXLayout = function Email2() {
9
+ return _jsxDEV(
10
+ Html,
11
+ {
12
+ children: _jsxDEV(
13
+ Button,
14
+ {
15
+ href: 'https://example.com',
16
+ style: {
17
+ background: '#000',
18
+ color: '#fff',
19
+ padding: '12px 20px',
20
+ },
21
+ children: 'Click me',
22
+ },
23
+ void 0,
24
+ false,
25
+ {
26
+ fileName:
27
+ '/Users/david/src/silencia-ai/silencia/proto/emails-raw/em1.mdx',
28
+ lineNumber: 7,
29
+ columnNumber: 7,
30
+ },
31
+ this,
32
+ ),
33
+ },
34
+ void 0,
35
+ false,
36
+ {
37
+ fileName:
38
+ '/Users/david/src/silencia-ai/silencia/proto/emails-raw/em1.mdx',
39
+ lineNumber: 6,
40
+ columnNumber: 5,
41
+ },
42
+ this,
43
+ );
44
+ };
45
+
46
+ function _createMdxContent(props) {
47
+ const _components = {
48
+ h1: 'h1',
49
+ ..._provideComponents(),
50
+ ...props.components,
51
+ };
52
+ return _jsxDEV(
53
+ _Fragment,
54
+ {
55
+ children: [
56
+ _jsxDEV(
57
+ _components.h1,
58
+ {
59
+ children: 'Hello!',
60
+ },
61
+ void 0,
62
+ false,
63
+ {
64
+ fileName:
65
+ '/Users/david/src/silencia-ai/silencia/proto/emails-raw/em1.mdx',
66
+ lineNumber: 17,
67
+ columnNumber: 1,
68
+ },
69
+ this,
70
+ ),
71
+ '\n',
72
+ _jsxDEV(
73
+ Email,
74
+ {},
75
+ void 0,
76
+ false,
77
+ {
78
+ fileName:
79
+ '/Users/david/src/silencia-ai/silencia/proto/emails-raw/em1.mdx',
80
+ lineNumber: 19,
81
+ columnNumber: 1,
82
+ },
83
+ this,
84
+ ),
85
+ ],
86
+ },
87
+ void 0,
88
+ true,
89
+ {
90
+ fileName:
91
+ '/Users/david/src/silencia-ai/silencia/proto/emails-raw/em1.mdx',
92
+ lineNumber: 1,
93
+ columnNumber: 1,
94
+ },
95
+ this,
96
+ );
97
+ }
98
+
99
+ function MDXContent(props = {}) {
100
+ return _jsxDEV(
101
+ MDXLayout,
102
+ {
103
+ ...props,
104
+ children: _jsxDEV(
105
+ _createMdxContent,
106
+ {
107
+ ...props,
108
+ },
109
+ void 0,
110
+ false,
111
+ {
112
+ fileName:
113
+ '/Users/david/src/silencia-ai/silencia/proto/emails-raw/em1.mdx',
114
+ },
115
+ this,
116
+ ),
117
+ },
118
+ void 0,
119
+ false,
120
+ {
121
+ fileName:
122
+ '/Users/david/src/silencia-ai/silencia/proto/emails-raw/em1.mdx',
123
+ },
124
+ this,
125
+ );
126
+ }
127
+
128
+ export { MDXContent as default };
@@ -0,0 +1,9 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ const req = new Request('https://react.email');
3
+ const res = new Response('{}');
4
+
5
+ const Email = () => {
6
+ return <div />;
7
+ };
8
+
9
+ export default Email;
@@ -0,0 +1,26 @@
1
+ export type As<
2
+ DefaultTag extends React.ElementType,
3
+ T1 extends React.ElementType,
4
+ T2 extends React.ElementType = T1,
5
+ T3 extends React.ElementType = T1,
6
+ T4 extends React.ElementType = T1,
7
+ T5 extends React.ElementType = T1,
8
+ > =
9
+ | (React.ComponentPropsWithRef<DefaultTag> & {
10
+ as?: DefaultTag;
11
+ })
12
+ | (React.ComponentPropsWithRef<T1> & {
13
+ as: T1;
14
+ })
15
+ | (React.ComponentPropsWithRef<T2> & {
16
+ as: T2;
17
+ })
18
+ | (React.ComponentPropsWithRef<T3> & {
19
+ as: T3;
20
+ })
21
+ | (React.ComponentPropsWithRef<T4> & {
22
+ as: T4;
23
+ })
24
+ | (React.ComponentPropsWithRef<T5> & {
25
+ as: T5;
26
+ });
@@ -0,0 +1,8 @@
1
+ export interface EmailTemplate {
2
+ (props: Record<string, unknown> | Record<string, never>): React.ReactNode;
3
+ PreviewProps?: Record<string, unknown>;
4
+ }
5
+
6
+ export const isEmailTemplate = (val: unknown): val is EmailTemplate => {
7
+ return typeof val === 'function';
8
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * An object that mimics the structure of the Error class,
3
+ * we just can't use the Error class here because server actions can't
4
+ * return classes
5
+ */
6
+ export interface ErrorObject {
7
+ name: string;
8
+ stack: string | undefined;
9
+ cause?: unknown;
10
+ message: string;
11
+ }
@@ -0,0 +1,13 @@
1
+ export interface HotReloadChange {
2
+ filename: string;
3
+ event:
4
+ | 'all'
5
+ | 'ready'
6
+ | 'add'
7
+ | 'change'
8
+ | 'addDir'
9
+ | 'unlink'
10
+ | 'unlinkDir'
11
+ | 'raw'
12
+ | 'error';
13
+ }