react-email 2.0.0 → 2.0.1-canary.1
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/cli/index.d.mts +0 -0
- package/cli/index.d.ts +0 -0
- package/cli/index.js +10 -9
- package/cli/index.mjs +9 -9
- package/dist/package.json +1 -1
- package/dist/source/index.js +0 -0
- package/dist/source/utils/download-client.js +1 -1
- package/package.json +9 -9
- package/src/actions/get-emails-directory-metadata.ts +0 -5
- package/src/app/preview/{[slug] → [...slug]}/page.tsx +18 -6
- package/src/app/preview/{[slug] → [...slug]}/preview.tsx +1 -1
- package/src/components/shell.tsx +1 -1
- package/src/components/sidebar/sidebar-directory-children.tsx +3 -3
- package/src/components/sidebar/sidebar.tsx +8 -6
- package/src/components/topbar.tsx +2 -1
- /package/src/app/preview/{[slug] → [...slug]}/rendering-error.tsx +0 -0
package/cli/index.d.mts
CHANGED
|
File without changes
|
package/cli/index.d.ts
CHANGED
|
File without changes
|
package/cli/index.js
CHANGED
|
@@ -252,7 +252,7 @@ var import_commander = require("commander");
|
|
|
252
252
|
// package.json
|
|
253
253
|
var package_default = {
|
|
254
254
|
name: "react-email",
|
|
255
|
-
version: "2.0.
|
|
255
|
+
version: "2.0.1-canary.1",
|
|
256
256
|
description: "A live preview of your emails right in your browser.",
|
|
257
257
|
bin: {
|
|
258
258
|
email: "./cli/index.js"
|
|
@@ -302,7 +302,7 @@ var package_default = {
|
|
|
302
302
|
glob: "10.3.4",
|
|
303
303
|
"log-symbols": "4.1.0",
|
|
304
304
|
"mime-types": "2.1.35",
|
|
305
|
-
next: "14.0
|
|
305
|
+
next: "14.1.0",
|
|
306
306
|
"normalize-path": "3.0.0",
|
|
307
307
|
ora: "5.4.1",
|
|
308
308
|
postcss: "8.4.32",
|
|
@@ -872,8 +872,6 @@ var import_node_child_process = require("child_process");
|
|
|
872
872
|
var import_node_fs4 = __toESM(require("fs"));
|
|
873
873
|
var import_node_path5 = __toESM(require("path"));
|
|
874
874
|
var isFileAnEmail = function(fullPath) {
|
|
875
|
-
var unixFullPath = fullPath.replaceAll(import_node_path5.default.sep, "/");
|
|
876
|
-
if (/(\/|^)_[^/]*/.test(unixFullPath)) return false;
|
|
877
875
|
var stat = import_node_fs4.default.statSync(fullPath);
|
|
878
876
|
if (stat.isDirectory()) return false;
|
|
879
877
|
var ext = import_node_path5.default.parse(fullPath).ext;
|
|
@@ -1001,7 +999,9 @@ var getEmailSlugsFromEmailDirectory = function(emailDirectory, emailsDirectoryAb
|
|
|
1001
999
|
var directoryPathRelativeToEmailsDirectory = emailDirectory.absolutePath.replace(emailsDirectoryAbsolutePath, "").trim();
|
|
1002
1000
|
var slugs = [];
|
|
1003
1001
|
emailDirectory.emailFilenames.forEach(function(filename) {
|
|
1004
|
-
return slugs.push(import_node_path6.default.join(directoryPathRelativeToEmailsDirectory, filename))
|
|
1002
|
+
return slugs.push(import_node_path6.default.join(directoryPathRelativeToEmailsDirectory, filename).split(import_node_path6.default.sep).filter(function(segment) {
|
|
1003
|
+
return segment.length > 0;
|
|
1004
|
+
}));
|
|
1005
1005
|
});
|
|
1006
1006
|
emailDirectory.subDirectories.forEach(function(directory) {
|
|
1007
1007
|
var _slugs;
|
|
@@ -1029,7 +1029,7 @@ var forceSSGForEmailPreviews = function() {
|
|
|
1029
1029
|
});
|
|
1030
1030
|
return [
|
|
1031
1031
|
4,
|
|
1032
|
-
import_node_fs5.default.promises.appendFile(import_node_path6.default.resolve(builtPreviewAppPath, "./src/app/preview/[slug]/page.tsx"), "\n\nexport async function generateStaticParams() { \n return ".concat(JSON.stringify(parameters), ";\n}"), "utf8")
|
|
1032
|
+
import_node_fs5.default.promises.appendFile(import_node_path6.default.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx"), "\n\nexport async function generateStaticParams() { \n return ".concat(JSON.stringify(parameters), ";\n}"), "utf8")
|
|
1033
1033
|
];
|
|
1034
1034
|
case 2:
|
|
1035
1035
|
_state.sent();
|
|
@@ -1043,7 +1043,7 @@ var forceSSGForEmailPreviews = function() {
|
|
|
1043
1043
|
return _ref.apply(this, arguments);
|
|
1044
1044
|
};
|
|
1045
1045
|
}();
|
|
1046
|
-
var
|
|
1046
|
+
var updatePackageJson = function() {
|
|
1047
1047
|
var _ref = _async_to_generator(function(builtPreviewAppPath) {
|
|
1048
1048
|
var packageJsonPath, packageJson, _;
|
|
1049
1049
|
return _ts_generator(this, function(_state) {
|
|
@@ -1061,6 +1061,7 @@ var updatePackageJsonScripts = function() {
|
|
|
1061
1061
|
]);
|
|
1062
1062
|
packageJson.scripts.build = "next build";
|
|
1063
1063
|
packageJson.scripts.start = "next start";
|
|
1064
|
+
packageJson.dependencies.sharp = "0.33.2";
|
|
1064
1065
|
return [
|
|
1065
1066
|
4,
|
|
1066
1067
|
import_node_fs5.default.promises.writeFile(packageJsonPath, JSON.stringify(packageJson), "utf8")
|
|
@@ -1073,7 +1074,7 @@ var updatePackageJsonScripts = function() {
|
|
|
1073
1074
|
}
|
|
1074
1075
|
});
|
|
1075
1076
|
});
|
|
1076
|
-
return function
|
|
1077
|
+
return function updatePackageJson(builtPreviewAppPath) {
|
|
1077
1078
|
return _ref.apply(this, arguments);
|
|
1078
1079
|
};
|
|
1079
1080
|
}();
|
|
@@ -1187,7 +1188,7 @@ var build = function() {
|
|
|
1187
1188
|
spinner.text = "Updating package.json's build and start scripts";
|
|
1188
1189
|
return [
|
|
1189
1190
|
4,
|
|
1190
|
-
|
|
1191
|
+
updatePackageJson(builtPreviewAppPath)
|
|
1191
1192
|
];
|
|
1192
1193
|
case 9:
|
|
1193
1194
|
_state.sent();
|
package/cli/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { program } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "react-email",
|
|
9
|
-
version: "2.0.
|
|
9
|
+
version: "2.0.1-canary.1",
|
|
10
10
|
description: "A live preview of your emails right in your browser.",
|
|
11
11
|
bin: {
|
|
12
12
|
email: "./cli/index.js"
|
|
@@ -56,7 +56,7 @@ var package_default = {
|
|
|
56
56
|
glob: "10.3.4",
|
|
57
57
|
"log-symbols": "4.1.0",
|
|
58
58
|
"mime-types": "2.1.35",
|
|
59
|
-
next: "14.0
|
|
59
|
+
next: "14.1.0",
|
|
60
60
|
"normalize-path": "3.0.0",
|
|
61
61
|
ora: "5.4.1",
|
|
62
62
|
postcss: "8.4.32",
|
|
@@ -451,9 +451,6 @@ import { spawn } from "child_process";
|
|
|
451
451
|
import fs4 from "fs";
|
|
452
452
|
import path6 from "path";
|
|
453
453
|
var isFileAnEmail = (fullPath) => {
|
|
454
|
-
const unixFullPath = fullPath.replaceAll(path6.sep, "/");
|
|
455
|
-
if (/(\/|^)_[^/]*/.test(unixFullPath))
|
|
456
|
-
return false;
|
|
457
454
|
const stat = fs4.statSync(fullPath);
|
|
458
455
|
if (stat.isDirectory())
|
|
459
456
|
return false;
|
|
@@ -580,7 +577,9 @@ var getEmailSlugsFromEmailDirectory = (emailDirectory, emailsDirectoryAbsolutePa
|
|
|
580
577
|
const directoryPathRelativeToEmailsDirectory = emailDirectory.absolutePath.replace(emailsDirectoryAbsolutePath, "").trim();
|
|
581
578
|
const slugs = [];
|
|
582
579
|
emailDirectory.emailFilenames.forEach(
|
|
583
|
-
(filename) => slugs.push(
|
|
580
|
+
(filename) => slugs.push(
|
|
581
|
+
path7.join(directoryPathRelativeToEmailsDirectory, filename).split(path7.sep).filter((segment) => segment.length > 0)
|
|
582
|
+
)
|
|
584
583
|
);
|
|
585
584
|
emailDirectory.subDirectories.forEach((directory) => {
|
|
586
585
|
slugs.push(
|
|
@@ -602,7 +601,7 @@ var forceSSGForEmailPreviews = async (emailsDirPath, builtPreviewAppPath) => {
|
|
|
602
601
|
emailsDirPath
|
|
603
602
|
).map((slug) => ({ slug }));
|
|
604
603
|
await fs5.promises.appendFile(
|
|
605
|
-
path7.resolve(builtPreviewAppPath, "./src/app/preview/[slug]/page.tsx"),
|
|
604
|
+
path7.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx"),
|
|
606
605
|
`
|
|
607
606
|
|
|
608
607
|
export async function generateStaticParams() {
|
|
@@ -611,13 +610,14 @@ export async function generateStaticParams() {
|
|
|
611
610
|
"utf8"
|
|
612
611
|
);
|
|
613
612
|
};
|
|
614
|
-
var
|
|
613
|
+
var updatePackageJson = async (builtPreviewAppPath) => {
|
|
615
614
|
const packageJsonPath = path7.resolve(builtPreviewAppPath, "./package.json");
|
|
616
615
|
const packageJson = JSON.parse(
|
|
617
616
|
await fs5.promises.readFile(packageJsonPath, "utf8")
|
|
618
617
|
);
|
|
619
618
|
packageJson.scripts.build = "next build";
|
|
620
619
|
packageJson.scripts.start = "next start";
|
|
620
|
+
packageJson.dependencies.sharp = "0.33.2";
|
|
621
621
|
await fs5.promises.writeFile(
|
|
622
622
|
packageJsonPath,
|
|
623
623
|
JSON.stringify(packageJson),
|
|
@@ -686,7 +686,7 @@ var build = async ({
|
|
|
686
686
|
spinner.text = "Setting server side generation for the email preview pages";
|
|
687
687
|
await forceSSGForEmailPreviews(emailsDirPath, builtPreviewAppPath);
|
|
688
688
|
spinner.text = "Updating package.json's build and start scripts";
|
|
689
|
-
await
|
|
689
|
+
await updatePackageJson(builtPreviewAppPath);
|
|
690
690
|
spinner.text = "Installing dependencies on `.react-email`";
|
|
691
691
|
await npmInstall(builtPreviewAppPath, packageManager);
|
|
692
692
|
spinner.stopAndPersist({
|
package/dist/package.json
CHANGED
package/dist/source/index.js
CHANGED
|
File without changes
|
|
@@ -54,7 +54,7 @@ var downloadClient = function () { return __awaiter(void 0, void 0, void 0, func
|
|
|
54
54
|
return [4 /*yield*/, octokit.repos.downloadTarballArchive({
|
|
55
55
|
owner: 'resendlabs',
|
|
56
56
|
repo: 'react-email',
|
|
57
|
-
ref: 'v0.0.15',
|
|
57
|
+
ref: 'v0.0.15-canary.0',
|
|
58
58
|
})];
|
|
59
59
|
case 1:
|
|
60
60
|
downloadRes = _a.sent();
|
package/package.json
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-email",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1-canary.1",
|
|
4
4
|
"description": "A live preview of your emails right in your browser.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"email": "./cli/index.js"
|
|
7
7
|
},
|
|
8
|
-
"scripts": {
|
|
9
|
-
"build": "tsup",
|
|
10
|
-
"dev": "tsup --watch",
|
|
11
|
-
"clean": "rm -rf dist",
|
|
12
|
-
"lint": "eslint . && tsc"
|
|
13
|
-
},
|
|
14
8
|
"license": "MIT",
|
|
15
9
|
"repository": {
|
|
16
10
|
"type": "git",
|
|
@@ -50,7 +44,7 @@
|
|
|
50
44
|
"glob": "10.3.4",
|
|
51
45
|
"log-symbols": "4.1.0",
|
|
52
46
|
"mime-types": "2.1.35",
|
|
53
|
-
"next": "14.0
|
|
47
|
+
"next": "14.1.0",
|
|
54
48
|
"normalize-path": "3.0.0",
|
|
55
49
|
"ora": "5.4.1",
|
|
56
50
|
"postcss": "8.4.32",
|
|
@@ -80,5 +74,11 @@
|
|
|
80
74
|
"tsx": "4.7.0",
|
|
81
75
|
"vitest": "1.1.3",
|
|
82
76
|
"watch": "1.0.2"
|
|
77
|
+
},
|
|
78
|
+
"scripts": {
|
|
79
|
+
"build": "tsup",
|
|
80
|
+
"dev": "tsup --watch",
|
|
81
|
+
"clean": "rm -rf dist",
|
|
82
|
+
"lint": "eslint . && tsc"
|
|
83
83
|
}
|
|
84
|
-
}
|
|
84
|
+
}
|
|
@@ -4,11 +4,6 @@ import fs from 'node:fs';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
|
|
6
6
|
const isFileAnEmail = (fullPath: string): boolean => {
|
|
7
|
-
const unixFullPath = fullPath.replaceAll(path.sep, '/');
|
|
8
|
-
|
|
9
|
-
// eslint-disable-next-line prefer-named-capture-group
|
|
10
|
-
if (/(\/|^)_[^/]*/.test(unixFullPath)) return false;
|
|
11
|
-
|
|
12
7
|
const stat = fs.statSync(fullPath);
|
|
13
8
|
|
|
14
9
|
if (stat.isDirectory()) return false;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { Suspense } from 'react';
|
|
4
|
+
import { redirect } from 'next/navigation';
|
|
1
5
|
import { getEmailsDirectoryMetadata } from '../../../actions/get-emails-directory-metadata';
|
|
2
6
|
import { renderEmailBySlug } from '../../../actions/render-email-by-slug';
|
|
3
7
|
import { emailsDirectoryAbsolutePath } from '../../../utils/emails-directory-absolute-path';
|
|
@@ -6,13 +10,13 @@ import Preview from './preview';
|
|
|
6
10
|
export const dynamicParams = true;
|
|
7
11
|
|
|
8
12
|
export interface PreviewParams {
|
|
9
|
-
slug: string;
|
|
13
|
+
slug: string[];
|
|
10
14
|
}
|
|
11
15
|
|
|
12
16
|
export default async function Page({ params }: { params: PreviewParams }) {
|
|
13
|
-
// will come in here as a relative path to the email
|
|
14
|
-
// ex: authentication
|
|
15
|
-
const slug =
|
|
17
|
+
// will come in here as segments of a relative path to the email
|
|
18
|
+
// ex: ['authentication', 'verify-password.tsx']
|
|
19
|
+
const slug = params.slug.join('/');
|
|
16
20
|
const emailsDirMetadata = await getEmailsDirectoryMetadata(
|
|
17
21
|
emailsDirectoryAbsolutePath,
|
|
18
22
|
);
|
|
@@ -23,6 +27,8 @@ export default async function Page({ params }: { params: PreviewParams }) {
|
|
|
23
27
|
);
|
|
24
28
|
}
|
|
25
29
|
|
|
30
|
+
const emailPath = path.join(emailsDirectoryAbsolutePath, slug);
|
|
31
|
+
if (!fs.existsSync(emailPath)) redirect('/');
|
|
26
32
|
const emailRenderingResult = await renderEmailBySlug(slug);
|
|
27
33
|
|
|
28
34
|
if (
|
|
@@ -34,9 +40,15 @@ export default async function Page({ params }: { params: PreviewParams }) {
|
|
|
34
40
|
});
|
|
35
41
|
}
|
|
36
42
|
|
|
37
|
-
|
|
43
|
+
// This suspense is so that this page doesn't warning with
|
|
44
|
+
// de-opt into client-side rendering on build
|
|
45
|
+
return (
|
|
46
|
+
<Suspense>
|
|
47
|
+
<Preview renderingResult={emailRenderingResult} slug={slug} />
|
|
48
|
+
</Suspense>
|
|
49
|
+
);
|
|
38
50
|
}
|
|
39
51
|
|
|
40
52
|
export function generateMetadata({ params }: { params: PreviewParams }) {
|
|
41
|
-
return { title: `${
|
|
53
|
+
return { title: `${params.slug.pop()} — React Email` };
|
|
42
54
|
}
|
|
@@ -77,7 +77,7 @@ const Preview = ({
|
|
|
77
77
|
setActiveView={hasNoErrors ? handleViewChange : undefined}
|
|
78
78
|
>
|
|
79
79
|
{/* This relative is so that when there is any error the user can still switch between emails */}
|
|
80
|
-
<div className="relative h-full">
|
|
80
|
+
<div className="bg-white relative h-full">
|
|
81
81
|
{'error' in renderingResult ? (
|
|
82
82
|
<RenderingError error={renderingResult.error} />
|
|
83
83
|
) : null}
|
package/src/components/shell.tsx
CHANGED
|
@@ -59,7 +59,7 @@ export const Shell = ({
|
|
|
59
59
|
<div className="flex bg-slate-2">
|
|
60
60
|
<Sidebar
|
|
61
61
|
className={cn(
|
|
62
|
-
'w-screen max-w-full bg-black h-screen lg:h-auto z-50 lg:max-w-[275px] fixed top-[70px] lg:top-0 left-0',
|
|
62
|
+
'w-screen max-w-full bg-black h-screen lg:h-auto z-50 lg:z-auto lg:max-w-[275px] fixed top-[70px] lg:top-0 left-0',
|
|
63
63
|
{
|
|
64
64
|
'translate-x-0 lg:-translate-x-full': sidebarToggled,
|
|
65
65
|
'-translate-x-full lg:translate-x-0': !sidebarToggled,
|
|
@@ -67,7 +67,7 @@ export const SidebarDirectoryChildren = (props: {
|
|
|
67
67
|
return (
|
|
68
68
|
<Link
|
|
69
69
|
href={{
|
|
70
|
-
pathname: `/preview/${
|
|
70
|
+
pathname: `/preview/${emailSlug}`,
|
|
71
71
|
search: searchParams.toString(),
|
|
72
72
|
}}
|
|
73
73
|
key={emailSlug}
|
|
@@ -75,7 +75,7 @@ export const SidebarDirectoryChildren = (props: {
|
|
|
75
75
|
<motion.span
|
|
76
76
|
animate={{ x: 0, opacity: 1 }}
|
|
77
77
|
className={cn(
|
|
78
|
-
'text-[14px] flex items-center align-middle pl-3 h-8 max-w-full rounded-md text-slate-11 relative transition
|
|
78
|
+
'text-[14px] flex items-center align-middle pl-3 h-8 max-w-full rounded-md text-slate-11 relative transition-colors',
|
|
79
79
|
{
|
|
80
80
|
'text-cyan-11': isCurrentPage,
|
|
81
81
|
'hover:text-slate-12':
|
|
@@ -84,7 +84,7 @@ export const SidebarDirectoryChildren = (props: {
|
|
|
84
84
|
)}
|
|
85
85
|
initial={{ x: -10 + -index * 1.5, opacity: 0 }}
|
|
86
86
|
transition={{
|
|
87
|
-
x: { delay: 0.03 * index, duration: 0.
|
|
87
|
+
x: { delay: 0.03 * index, duration: 0.2 },
|
|
88
88
|
opacity: { delay: 0.03 * index, duration: 0.2 },
|
|
89
89
|
}}
|
|
90
90
|
>
|
|
@@ -30,12 +30,14 @@ export const Sidebar = ({
|
|
|
30
30
|
</div>
|
|
31
31
|
<nav className="p-4 flex-grow lg:pt-0 pl-0 w-screen h-[calc(100vh_-_70px)] lg:w-full lg:min-w-[275px] lg:max-w-[275px] flex flex-col overflow-y-auto">
|
|
32
32
|
<Collapsible.Root>
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
<React.Suspense>
|
|
34
|
+
<SidebarDirectoryChildren
|
|
35
|
+
currentEmailOpenSlug={currentEmailOpenSlug}
|
|
36
|
+
emailsDirectoryMetadata={emailsDirectoryMetadata}
|
|
37
|
+
isRoot
|
|
38
|
+
open
|
|
39
|
+
/>
|
|
40
|
+
</React.Suspense>
|
|
39
41
|
</Collapsible.Root>
|
|
40
42
|
</nav>
|
|
41
43
|
</aside>
|
|
@@ -11,6 +11,7 @@ import { IconPhone } from './icons/icon-phone';
|
|
|
11
11
|
import { IconSource } from './icons/icon-source';
|
|
12
12
|
import { Send } from './send';
|
|
13
13
|
import { Tooltip } from './tooltip';
|
|
14
|
+
import { pathSeparator } from '../utils/emails-directory-absolute-path';
|
|
14
15
|
|
|
15
16
|
interface TopbarProps {
|
|
16
17
|
currentEmailOpenSlug: string;
|
|
@@ -49,7 +50,7 @@ export const Topbar: React.FC<Readonly<TopbarProps>> = ({
|
|
|
49
50
|
|
|
50
51
|
<div className="items-center overflow-hidden hidden lg:flex text-center absolute left-1/2 transform -translate-x-1/2 top-1/2 -translate-y-1/2">
|
|
51
52
|
<Heading as="h2" className="truncate" size="2" weight="medium">
|
|
52
|
-
{currentEmailOpenSlug}
|
|
53
|
+
{currentEmailOpenSlug.split(pathSeparator).pop()}
|
|
53
54
|
</Heading>
|
|
54
55
|
</div>
|
|
55
56
|
|
|
File without changes
|