@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.
- package/.next/BUILD_ID +1 -0
- package/.next/app-build-manifest.json +44 -0
- package/.next/app-path-routes-manifest.json +6 -0
- package/.next/build-manifest.json +33 -0
- package/.next/diagnostics/build-diagnostics.json +6 -0
- package/.next/diagnostics/framework.json +1 -0
- package/.next/export-marker.json +6 -0
- package/.next/images-manifest.json +57 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +41 -0
- package/.next/react-loadable-manifest.json +1 -0
- package/.next/required-server-files.json +311 -0
- package/.next/routes-manifest.json +64 -0
- package/.next/server/app/_not-found/page.js +1 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/.next/server/app/favicon.ico/route.js +1 -0
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -0
- package/.next/server/app/favicon.ico.body +0 -0
- package/.next/server/app/favicon.ico.meta +1 -0
- package/.next/server/app/page.js +1 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +1 -0
- package/.next/server/app/preview/[...slug]/page.js +321 -0
- package/.next/server/app/preview/[...slug]/page.js.nft.json +1 -0
- package/.next/server/app/preview/[...slug]/page_client-reference-manifest.js +1 -0
- package/.next/server/app-paths-manifest.json +6 -0
- package/.next/server/chunks/134.js +6 -0
- package/.next/server/chunks/235.js +15 -0
- package/.next/server/chunks/278.js +1 -0
- package/.next/server/chunks/343.js +20 -0
- package/.next/server/chunks/428.js +14 -0
- package/.next/server/chunks/963.js +1 -0
- package/.next/server/chunks/999.js +1 -0
- package/.next/server/functions-config-manifest.json +4 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +1 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +1 -0
- package/.next/server/pages/500.html +1 -0
- package/.next/server/pages/_app.js +1 -0
- package/.next/server/pages/_app.js.nft.json +1 -0
- package/.next/server/pages/_document.js +1 -0
- package/.next/server/pages/_document.js.nft.json +1 -0
- package/.next/server/pages/_error.js +1 -0
- package/.next/server/pages/_error.js.nft.json +1 -0
- package/.next/server/pages-manifest.json +5 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +1 -0
- package/.next/server/webpack-runtime.js +1 -0
- package/.next/static/VkyJa9K30jCrKBesOgrQT/_buildManifest.js +1 -0
- package/.next/static/VkyJa9K30jCrKBesOgrQT/_ssgManifest.js +1 -0
- package/.next/static/chunks/107-3043079e7cb8bcae.js +1 -0
- package/.next/static/chunks/293-67391ef0e44ffa4f.js +1 -0
- package/.next/static/chunks/3bd82e28-cda2c00a924937c5.js +1 -0
- package/.next/static/chunks/45-1021fac82f766268.js +1 -0
- package/.next/static/chunks/484-1969fe871b27074e.js +1 -0
- package/.next/static/chunks/484-e02de792ff5f9ea5.js +1 -0
- package/.next/static/chunks/589-817d8691661d370e.js +1 -0
- package/.next/static/chunks/902-c34acb56733e0ce1.js +1 -0
- package/.next/static/chunks/app/_not-found/page-4cbc7dce3ad33336.js +1 -0
- package/.next/static/chunks/app/layout-74628781c0b7e7bf.js +1 -0
- package/.next/static/chunks/app/layout-daeba68330ab58bb.js +1 -0
- package/.next/static/chunks/app/page-55cf199b7ca71958.js +1 -0
- package/.next/static/chunks/app/preview/[...slug]/page-07dd9a701d0b3e56.js +1 -0
- package/.next/static/chunks/app/preview/[...slug]/page-61b0ea70a8d72916.js +1 -0
- package/.next/static/chunks/f33a14d2-ec7c5f0b91818561.js +6 -0
- package/.next/static/chunks/framework-b887e9fc751a9906.js +1 -0
- package/.next/static/chunks/main-9a03e7ba8acb1900.js +1 -0
- package/.next/static/chunks/main-app-5bc2d814f500db60.js +1 -0
- package/.next/static/chunks/pages/_app-542a93a5a214e1c0.js +1 -0
- package/.next/static/chunks/pages/_error-d5fe1b1612642f76.js +1 -0
- package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/.next/static/chunks/webpack-31c45daa2bd82a7b.js +1 -0
- package/.next/static/css/35e8811589f0962b.css +3 -0
- package/.next/static/j4oDiQwPKPQgK5jAoiUTk/_buildManifest.js +1 -0
- package/.next/static/j4oDiQwPKPQgK5jAoiUTk/_ssgManifest.js +1 -0
- package/.next/static/media/05613964ce6c782e-s.p.otf +0 -0
- package/.next/static/media/11c6126b9369e85e-s.p.otf +0 -0
- package/.next/static/media/26a46d62cd723877-s.woff2 +0 -0
- package/.next/static/media/26cb97734d8cb717-s.p.otf +0 -0
- package/.next/static/media/55c55f0601d81cf3-s.woff2 +0 -0
- package/.next/static/media/581909926a08bbc8-s.woff2 +0 -0
- package/.next/static/media/6d93bde91c0c2823-s.woff2 +0 -0
- package/.next/static/media/97e0cb1ae144a2a9-s.woff2 +0 -0
- package/.next/static/media/a34f9d1faa5f3315-s.p.woff2 +0 -0
- package/.next/static/media/bb6462617151f6b7-s.p.otf +0 -0
- package/.next/static/media/cf6daef822ab0142-s.p.otf +0 -0
- package/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
- package/.next/static/media/e4051546b3043204-s.p.otf +0 -0
- package/.next/static/media/logo.2ce2a759.png +0 -0
- package/.next/trace +27 -0
- package/.next/types/app/layout.ts +84 -0
- package/.next/types/app/page.ts +84 -0
- package/.next/types/app/preview/[...slug]/page.ts +84 -0
- package/.next/types/cache-life.d.ts +141 -0
- package/.next/types/package.json +1 -0
- package/_index.js +4 -0
- package/license.md +7 -0
- package/module-punycode.d.ts +3 -0
- package/next-env.d.ts +5 -0
- package/next.config.js +22 -0
- package/package.json +82 -0
- package/postcss.config.js +8 -0
- package/scripts/build-preview-server.mjs +29 -0
- package/scripts/fill-caniemail-data.mjs +36 -0
- package/src/actions/email-validation/caniemail-data.ts +85993 -0
- package/src/actions/email-validation/check-compatibility.ts +333 -0
- package/src/actions/email-validation/check-images.spec.tsx +100 -0
- package/src/actions/email-validation/check-images.ts +160 -0
- package/src/actions/email-validation/check-links.spec.tsx +113 -0
- package/src/actions/email-validation/check-links.ts +113 -0
- package/src/actions/email-validation/get-code-location-from-ast-element.ts +18 -0
- package/src/actions/email-validation/quick-fetch.ts +14 -0
- package/src/actions/get-email-path-from-slug.ts +32 -0
- package/src/actions/get-emails-directory-metadata-action.ts +19 -0
- package/src/actions/render-email-by-path.tsx +121 -0
- package/src/animated-icons-data/help.json +1082 -0
- package/src/animated-icons-data/link.json +1309 -0
- package/src/animated-icons-data/load.json +443 -0
- package/src/animated-icons-data/mail.json +1320 -0
- package/src/app/env.ts +15 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/fonts/SFMono/SFMonoBold.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoBoldItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoHeavy.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoHeavyItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoLight.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoLightItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoMedium.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoMediumItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoRegular.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoRegularItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoSemibold.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoSemiboldItalic.otf +0 -0
- package/src/app/fonts.ts +39 -0
- package/src/app/globals.css +15 -0
- package/src/app/layout.tsx +43 -0
- package/src/app/logo.png +0 -0
- package/src/app/page.tsx +46 -0
- package/src/app/preview/[...slug]/page.tsx +157 -0
- package/src/app/preview/[...slug]/preview.tsx +216 -0
- package/src/app/preview/[...slug]/rendering-error.tsx +40 -0
- package/src/components/button.tsx +101 -0
- package/src/components/code-container.tsx +164 -0
- package/src/components/code-snippet.tsx +9 -0
- package/src/components/code.tsx +184 -0
- package/src/components/heading.tsx +113 -0
- package/src/components/icons/icon-arrow-down.tsx +16 -0
- package/src/components/icons/icon-base.tsx +26 -0
- package/src/components/icons/icon-bug.tsx +19 -0
- package/src/components/icons/icon-button.tsx +23 -0
- package/src/components/icons/icon-check.tsx +19 -0
- package/src/components/icons/icon-clipboard.tsx +40 -0
- package/src/components/icons/icon-download.tsx +19 -0
- package/src/components/icons/icon-email.tsx +18 -0
- package/src/components/icons/icon-file.tsx +19 -0
- package/src/components/icons/icon-folder-open.tsx +19 -0
- package/src/components/icons/icon-folder.tsx +18 -0
- package/src/components/icons/icon-hide-sidebar.tsx +23 -0
- package/src/components/icons/icon-image.tsx +19 -0
- package/src/components/icons/icon-info.tsx +18 -0
- package/src/components/icons/icon-link.tsx +14 -0
- package/src/components/icons/icon-monitor.tsx +19 -0
- package/src/components/icons/icon-phone.tsx +26 -0
- package/src/components/icons/icon-reload.tsx +18 -0
- package/src/components/icons/icon-source.tsx +19 -0
- package/src/components/icons/icon-stamp.tsx +14 -0
- package/src/components/icons/icon-warning.tsx +31 -0
- package/src/components/index.ts +7 -0
- package/src/components/logo.tsx +63 -0
- package/src/components/resizable-wrapper.tsx +173 -0
- package/src/components/send.tsx +134 -0
- package/src/components/shell.tsx +92 -0
- package/src/components/sidebar/file-tree-directory-children.tsx +139 -0
- package/src/components/sidebar/file-tree-directory.tsx +92 -0
- package/src/components/sidebar/file-tree.tsx +31 -0
- package/src/components/sidebar/index.ts +1 -0
- package/src/components/sidebar/sidebar.tsx +43 -0
- package/src/components/text.tsx +99 -0
- package/src/components/toolbar/checking-results.tsx +150 -0
- package/src/components/toolbar/code-preview-line-link.tsx +40 -0
- package/src/components/toolbar/compatibility.tsx +113 -0
- package/src/components/toolbar/linter.tsx +278 -0
- package/src/components/toolbar/results-table.tsx +0 -0
- package/src/components/toolbar/results.tsx +51 -0
- package/src/components/toolbar/spam-assassin.tsx +155 -0
- package/src/components/toolbar/toolbar-button.tsx +52 -0
- package/src/components/toolbar/use-cached-state.ts +33 -0
- package/src/components/toolbar.tsx +349 -0
- package/src/components/tooltip-content.tsx +31 -0
- package/src/components/tooltip.tsx +19 -0
- package/src/components/topbar/active-view-toggle-group.tsx +86 -0
- package/src/components/topbar/view-size-controls.tsx +247 -0
- package/src/components/topbar.tsx +59 -0
- package/src/contexts/emails.tsx +59 -0
- package/src/contexts/fragment-identifier.tsx +48 -0
- package/src/contexts/preview.tsx +79 -0
- package/src/hooks/use-clamped-state.ts +24 -0
- package/src/hooks/use-email-rendering-result.ts +58 -0
- package/src/hooks/use-fragment-identifier.ts +14 -0
- package/src/hooks/use-hot-reload.ts +31 -0
- package/src/hooks/use-icon-animation.ts +41 -0
- package/src/hooks/use-rendering-metadata.ts +36 -0
- package/src/utils/__snapshots__/get-email-component.spec.ts.snap +3 -0
- package/src/utils/caniemail/all-css-properties.ts +358 -0
- package/src/utils/caniemail/ast/__snapshots__/get-object-variables.spec.ts.snap +74 -0
- package/src/utils/caniemail/ast/__snapshots__/get-used-style-properties.spec.ts.snap +24 -0
- package/src/utils/caniemail/ast/get-object-variables.spec.ts +19 -0
- package/src/utils/caniemail/ast/get-object-variables.ts +61 -0
- package/src/utils/caniemail/ast/get-used-style-properties.spec.ts +23 -0
- package/src/utils/caniemail/ast/get-used-style-properties.ts +91 -0
- package/src/utils/caniemail/get-compatibility-stats-for-entry.ts +118 -0
- package/src/utils/caniemail/get-css-functions.ts +25 -0
- package/src/utils/caniemail/get-css-property-names.ts +32 -0
- package/src/utils/caniemail/get-css-property-with-value.ts +14 -0
- package/src/utils/caniemail/get-css-unit.ts +3 -0
- package/src/utils/caniemail/get-element-attributes.ts +7 -0
- package/src/utils/caniemail/get-element-names.ts +20 -0
- package/src/utils/caniemail/tailwind/generate-tailwind-rules.ts +30 -0
- package/src/utils/caniemail/tailwind/get-tailwind-config.ts +187 -0
- package/src/utils/caniemail/tailwind/get-tailwind-metadata.spec.ts +25 -0
- package/src/utils/caniemail/tailwind/get-tailwind-metadata.ts +45 -0
- package/src/utils/caniemail/tailwind/setup-tailwind-context.ts +15 -0
- package/src/utils/cn.ts +6 -0
- package/src/utils/constants.ts +6 -0
- package/src/utils/contains-email-template.spec.ts +124 -0
- package/src/utils/contains-email-template.ts +33 -0
- package/src/utils/copy-text-to-clipboard.ts +7 -0
- package/src/utils/esbuild/escape-string-for-regex.ts +3 -0
- package/src/utils/esbuild/renderring-utilities-exporter.ts +63 -0
- package/src/utils/get-email-component.spec.ts +41 -0
- package/src/utils/get-email-component.ts +134 -0
- package/src/utils/get-emails-directory-metadata.spec.ts +82 -0
- package/src/utils/get-emails-directory-metadata.ts +141 -0
- package/src/utils/get-line-and-column-from-offset.spec.ts +11 -0
- package/src/utils/get-line-and-column-from-offset.ts +11 -0
- package/src/utils/improve-error-with-sourcemap.ts +85 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/js-email-detection.spec.ts +24 -0
- package/src/utils/language-map.ts +7 -0
- package/src/utils/linting.ts +60 -0
- package/src/utils/load-stream.ts +15 -0
- package/src/utils/register-spinner-autostopping.ts +28 -0
- package/src/utils/result.ts +49 -0
- package/src/utils/run-bundled-code.ts +64 -0
- package/src/utils/sanitize.ts +6 -0
- package/src/utils/static-node-modules-for-vm.ts +93 -0
- package/src/utils/testing/js-email-export-default.js +17 -0
- package/src/utils/testing/js-email-test.js +18 -0
- package/src/utils/testing/mdx-email-test.js +128 -0
- package/src/utils/testing/request-response-email.tsx +9 -0
- package/src/utils/types/as.ts +26 -0
- package/src/utils/types/email-template.ts +8 -0
- package/src/utils/types/error-object.ts +11 -0
- package/src/utils/types/hot-reload-change.ts +13 -0
- package/src/utils/unreachable.ts +8 -0
- package/tailwind-internals.d.ts +133 -0
- package/tailwind.config.ts +99 -0
- package/tsconfig.json +45 -0
- 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,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,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,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,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
|
+
}
|