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 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.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.5-canary.46",
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 updatePackageJsonScripts = function() {
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 updatePackageJsonScripts(builtPreviewAppPath) {
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
- updatePackageJsonScripts(builtPreviewAppPath)
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.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.5-canary.46",
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(path7.join(directoryPathRelativeToEmailsDirectory, filename))
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 updatePackageJsonScripts = async (builtPreviewAppPath) => {
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 updatePackageJsonScripts(builtPreviewAppPath);
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
@@ -14,7 +14,7 @@
14
14
  "license": "MIT",
15
15
  "repository": {
16
16
  "type": "git",
17
- "url": "https://github.com/resend/react-email.git",
17
+ "url": "https://github.com/resendlabs/react-email.git",
18
18
  "directory": "packages/react-email"
19
19
  },
20
20
  "keywords": [
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.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.5-canary.46",
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/verify-password.tsx but encoded like authentication%20verify-password.tsx
15
- const slug = decodeURIComponent(params.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
- return <Preview renderingResult={emailRenderingResult} slug={slug} />;
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: `${decodeURIComponent(params.slug)} — React Email` };
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}
@@ -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/${encodeURIComponent(emailSlug)}`,
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 ease-in-out duration-200',
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.05 },
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
- <SidebarDirectoryChildren
34
- currentEmailOpenSlug={currentEmailOpenSlug}
35
- emailsDirectoryMetadata={emailsDirectoryMetadata}
36
- isRoot
37
- open
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