react-email 1.3.0 → 1.4.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/CHANGELOG.md +2 -7
- package/dist/_preview/pages.js +2 -2
- package/dist/_preview/root.js +1 -1
- package/dist/commands/dev.js +14 -7
- package/emails/static/background.png +0 -0
- package/emails/test.jsx +3 -0
- package/emails/test.tsx +3 -0
- package/package.json +2 -2
- package/preview/package.json +1 -1
- package/preview/src/pages/index.tsx +4 -1
- package/preview/src/pages/preview/[slug].tsx +3 -1
- package/source/_preview/pages.ts +2 -2
- package/source/_preview/root.ts +1 -1
- package/source/commands/dev.ts +20 -7
package/CHANGELOG.md
CHANGED
package/dist/_preview/pages.js
CHANGED
|
@@ -12,11 +12,11 @@ exports.pages = [
|
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
title: 'index.tsx',
|
|
15
|
-
content: "import { promises as fs } from 'fs';\nimport path from 'path';\nimport { Button, Heading, Text } from '../components';\nimport { Layout } from '../components/layout';\nimport Link from 'next/link';\n\ninterface HomeProps {}\n\nexport const CONTENT_DIR = 'emails';\n\nconst getEmails = async () => {\n const emailsDirectory = path.join(process.cwd(), CONTENT_DIR);\n const filenames = await fs.readdir(emailsDirectory);\n const emails = filenames.map((file) => file.replace(/\\.(jsx|tsx)$/g, ''));\n\n return emails;\n};\n\nexport async function getStaticProps({ params }) {\n try {\n const emails = await getEmails();\n return emails\n ? { props: { navItems: emails } }\n : { props: { navItems: [] } };\n } catch (error) {\n console.error(error);\n return { props: { navItems: [] } };\n }\n}\n\nconst Home: React.FC<Readonly<HomeProps>> = ({ navItems }: any) => {\n return (\n <Layout navItems={navItems}>\n <div className=\"max-w-md border border-slate-6 mx-auto mt-56 rounded-md p-8\">\n <Heading as=\"h2\" weight=\"medium\">\n Welcome to the React Email preview!\n </Heading>\n <Text as=\"p\" className=\"mt-2 mb-4\">\n To start developing your next email template, you can create a{' '}\n <code>.jsx</code> or <code>.tsx</code> file under the \"emails\" folder.\n </Text>\n\n <Button asChild>\n <Link href=\"https://react.email/docs\">Check the docs</Link>\n </Button>\n </div>\n </Layout>\n );\n};\n\nexport default Home;\n",
|
|
15
|
+
content: "import { promises as fs } from 'fs';\nimport path from 'path';\nimport { Button, Heading, Text } from '../components';\nimport { Layout } from '../components/layout';\nimport Link from 'next/link';\n\ninterface HomeProps {}\n\nexport const CONTENT_DIR = 'emails';\n\nconst getEmails = async () => {\n const emailsDirectory = path.join(process.cwd(), CONTENT_DIR);\n\n const filenames = await fs.readdir(emailsDirectory);\n const emails = filenames\n .map((file) => file.replace(/\\.(jsx|tsx)$/g, ''))\n .filter((file) => file !== 'components');\n\n return emails;\n};\n\nexport async function getStaticProps({ params }) {\n try {\n const emails = await getEmails();\n return emails\n ? { props: { navItems: emails } }\n : { props: { navItems: [] } };\n } catch (error) {\n console.error(error);\n return { props: { navItems: [] } };\n }\n}\n\nconst Home: React.FC<Readonly<HomeProps>> = ({ navItems }: any) => {\n return (\n <Layout navItems={navItems}>\n <div className=\"max-w-md border border-slate-6 mx-auto mt-56 rounded-md p-8\">\n <Heading as=\"h2\" weight=\"medium\">\n Welcome to the React Email preview!\n </Heading>\n <Text as=\"p\" className=\"mt-2 mb-4\">\n To start developing your next email template, you can create a{' '}\n <code>.jsx</code> or <code>.tsx</code> file under the \"emails\" folder.\n </Text>\n\n <Button asChild>\n <Link href=\"https://react.email/docs\">Check the docs</Link>\n </Button>\n </div>\n </Layout>\n );\n};\n\nexport default Home;\n",
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
dir: 'preview',
|
|
19
19
|
title: '[slug].tsx',
|
|
20
|
-
content: "import { promises as fs } from 'fs';\nimport path from 'path';\nimport { render } from '@react-email/render';\nimport { GetStaticPaths } from 'next';\nimport { Layout } from '../../components/layout';\nimport
|
|
20
|
+
content: "import * as React from 'react';\nimport { promises as fs } from 'fs';\nimport path from 'path';\nimport { render } from '@react-email/render';\nimport { GetStaticPaths } from 'next';\nimport { Layout } from '../../components/layout';\nimport { Code } from '../../components';\nimport Head from 'next/head';\nimport { useRouter } from 'next/router';\n\ninterface PreviewProps {}\n\nexport const CONTENT_DIR = 'emails';\n\nconst getEmails = async () => {\n const emailsDirectory = path.join(process.cwd(), CONTENT_DIR);\n const filenames = await fs.readdir(emailsDirectory);\n const emails = filenames\n .map((file) => file.replace(/\\.(jsx|tsx)$/g, ''))\n .filter((file) => file !== 'components');\n return { emails, filenames };\n};\n\nexport const getStaticPaths: GetStaticPaths = async () => {\n const { emails } = await getEmails();\n const paths = emails.map((email) => {\n return { params: { slug: email } };\n });\n return { paths, fallback: true };\n};\n\nexport async function getStaticProps({ params }) {\n try {\n const { emails, filenames } = await getEmails();\n const template = filenames.filter((email) => {\n const [fileName] = email.split('.');\n return params.slug === fileName;\n });\n\n const Email = (await import(`../../../emails/${params.slug}`)).default;\n const markup = render(<Email />, { pretty: true });\n const path = `${process.cwd()}/${CONTENT_DIR}/${template[0]}`;\n const reactMarkup = await fs.readFile(path, {\n encoding: 'utf-8',\n });\n\n return emails\n ? { props: { navItems: emails, slug: params.slug, markup, reactMarkup } }\n : { notFound: true };\n } catch (error) {\n console.error(error);\n return { notFound: true };\n }\n}\n\nconst Preview: React.FC<Readonly<PreviewProps>> = ({\n navItems,\n markup,\n reactMarkup,\n slug,\n}: any) => {\n const title = `${slug} — React Email`;\n const router = useRouter();\n const [viewMode, setViewMode] = React.useState('desktop');\n\n const handleViewMode = (mode: string) => {\n setViewMode(mode);\n\n router.push({\n pathname: router.pathname,\n query: {\n ...router.query,\n view: mode,\n },\n });\n };\n\n React.useEffect(() => {\n if (router.query.view === 'source' || router.query.view === 'desktop') {\n setViewMode(router.query.view);\n }\n }, [router.query.view]);\n\n return (\n <Layout\n navItems={navItems}\n title={slug}\n viewMode={viewMode}\n setViewMode={handleViewMode}\n >\n <Head>\n <title>{title}</title>\n </Head>\n {viewMode === 'desktop' ? (\n <iframe\n srcDoc={markup}\n frameBorder=\"0\"\n className=\"w-full h-[calc(100vh_-_70px)]\"\n />\n ) : (\n <div className=\"flex gap-6 mx-auto p-6\">\n <Code>{reactMarkup}</Code>\n <Code>{markup}</Code>\n </div>\n )}\n </Layout>\n );\n};\n\nexport default Preview;\n",
|
|
21
21
|
},
|
|
22
22
|
];
|
package/dist/_preview/root.js
CHANGED
|
@@ -8,7 +8,7 @@ exports.root = [
|
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
10
|
title: 'package.json',
|
|
11
|
-
content: '{\n "name": "react-email-preview",\n "version": "0.0.4",\n "description": "The React Email preview application",\n "license": "MIT",\n "scripts": {\n "dev": "next dev",\n "build": "next build",\n "start": "next start",\n "lint": "next lint",\n "format:check": "prettier --check \\"**/*.{ts,tsx,md}\\"",\n "format": "prettier --write \\"**/*.{ts,tsx,md}\\""\n },\n "dependencies": {\n "@next/font": "13.0.4",\n "@radix-ui/colors": "0.1.8",\n "@radix-ui/react-collapsible": "1.0.1",\n "@radix-ui/react-slot": "1.0.1",\n "@radix-ui/react-toggle-group": "1.0.1",\n "@react-email/render": "0.0.2",\n "classnames": "2.3.2",\n "next": "13.0.4",\n "prism-react-renderer": "1.3.5",\n "react": "18.2.0",\n "react-dom": "18.2.0"\n },\n "devDependencies": {\n "@types/classnames": "2.3.1",\n "@types/node": "18.11.9",\n "@types/react": "18.0.25",\n "@types/react-dom": "18.0.9",\n "autoprefixer": "10.4.13",\n "postcss": "8.4.19",\n "tailwindcss": "3.2.4",\n "typescript": "4.9.3"\n }\n}
|
|
11
|
+
content: '{\n "name": "react-email-preview",\n "version": "0.0.4",\n "description": "The React Email preview application",\n "license": "MIT",\n "scripts": {\n "dev": "next dev",\n "build": "next build",\n "start": "next start",\n "lint": "next lint",\n "format:check": "prettier --check \\"**/*.{ts,tsx,md}\\"",\n "format": "prettier --write \\"**/*.{ts,tsx,md}\\""\n },\n "engines": {\n "node": ">=18.0.0"\n },\n "dependencies": {\n "@next/font": "13.0.4",\n "@radix-ui/colors": "0.1.8",\n "@radix-ui/react-collapsible": "1.0.1",\n "@radix-ui/react-slot": "1.0.1",\n "@radix-ui/react-toggle-group": "1.0.1",\n "@react-email/render": "0.0.2",\n "classnames": "2.3.2",\n "next": "13.0.4",\n "prism-react-renderer": "1.3.5",\n "react": "18.2.0",\n "react-dom": "18.2.0"\n },\n "devDependencies": {\n "@types/classnames": "2.3.1",\n "@types/node": "18.11.9",\n "@types/react": "18.0.25",\n "@types/react-dom": "18.0.9",\n "autoprefixer": "10.4.13",\n "postcss": "8.4.19",\n "tailwindcss": "3.2.4",\n "typescript": "4.9.3"\n }\n}',
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
title: 'postcss.config.js',
|
package/dist/commands/dev.js
CHANGED
|
@@ -31,11 +31,12 @@ const dev = async () => {
|
|
|
31
31
|
};
|
|
32
32
|
exports.dev = dev;
|
|
33
33
|
const prepareFiles = async () => {
|
|
34
|
-
const spinner = (0, ora_1.default)('Preparing React
|
|
34
|
+
const spinner = (0, ora_1.default)('Preparing React Email files...').start();
|
|
35
35
|
const isFirstTime = !(0, check_directory_exist_1.checkDirectoryExist)(constants_1.REACT_EMAIL_ROOT);
|
|
36
36
|
if (isFirstTime) {
|
|
37
37
|
await (0, create_directory_1.createDirectory)(constants_1.REACT_EMAIL_ROOT);
|
|
38
38
|
await (0, create_directory_1.createDirectory)(path_1.default.join(constants_1.REACT_EMAIL_ROOT, 'src'));
|
|
39
|
+
await (0, create_directory_1.createDirectory)(path_1.default.join(constants_1.REACT_EMAIL_ROOT, 'public'));
|
|
39
40
|
await Promise.all([
|
|
40
41
|
createFilesAndDirectories(components_1.components, 'components'),
|
|
41
42
|
createFilesAndDirectories(utils_1.utils, 'utils'),
|
|
@@ -56,15 +57,14 @@ const checkForUpdates = async () => {
|
|
|
56
57
|
if (isUpToDate) {
|
|
57
58
|
return spinner.stopAndPersist({
|
|
58
59
|
symbol: log_symbols_1.default.success,
|
|
59
|
-
text: 'React
|
|
60
|
+
text: 'React Email is up-to-date',
|
|
60
61
|
});
|
|
61
62
|
}
|
|
62
63
|
return updatePackage();
|
|
63
64
|
};
|
|
64
65
|
const updatePackage = async () => {
|
|
65
|
-
const spinner = (0, ora_1.default)('Updating React
|
|
66
|
+
const spinner = (0, ora_1.default)('Updating React Email...').start();
|
|
66
67
|
await Promise.all([
|
|
67
|
-
createFilesAndDirectories(components_1.components, 'components'),
|
|
68
68
|
createFilesAndDirectories(utils_1.utils, 'utils'),
|
|
69
69
|
createFilesAndDirectories(styles_1.styles, 'styles'),
|
|
70
70
|
createFilesAndDirectories(root_1.root),
|
|
@@ -72,18 +72,25 @@ const updatePackage = async () => {
|
|
|
72
72
|
]);
|
|
73
73
|
spinner.stopAndPersist({
|
|
74
74
|
symbol: log_symbols_1.default.success,
|
|
75
|
-
text: 'React
|
|
75
|
+
text: 'React Email is updated',
|
|
76
76
|
});
|
|
77
77
|
};
|
|
78
78
|
const generateEmailsPreview = async () => {
|
|
79
79
|
const spinner = (0, ora_1.default)('Generating emails preview').start();
|
|
80
80
|
const hasEmailsDirectory = fs_1.default.existsSync(constants_1.CLIENT_EMAILS_PATH);
|
|
81
81
|
const hasPackageEmailsDirectory = fs_1.default.existsSync(constants_1.PACKAGE_EMAILS_PATH);
|
|
82
|
+
const hasPackagePublicDirectory = fs_1.default.existsSync(`${constants_1.REACT_EMAIL_ROOT}/public/static`);
|
|
82
83
|
if (hasEmailsDirectory) {
|
|
83
84
|
if (hasPackageEmailsDirectory) {
|
|
84
|
-
await fs_1.default.promises.
|
|
85
|
+
await fs_1.default.promises.rm(constants_1.PACKAGE_EMAILS_PATH, { recursive: true });
|
|
85
86
|
}
|
|
86
|
-
|
|
87
|
+
if (hasPackagePublicDirectory) {
|
|
88
|
+
await fs_1.default.promises.rm(`${constants_1.REACT_EMAIL_ROOT}/public`, {
|
|
89
|
+
recursive: true,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
await (0, cpy_1.default)(`${constants_1.CLIENT_EMAILS_PATH}/*{.tsx,.jsx}`, constants_1.PACKAGE_EMAILS_PATH);
|
|
93
|
+
await (0, cpy_1.default)(`${constants_1.CLIENT_EMAILS_PATH}/static`, `${constants_1.REACT_EMAIL_ROOT}/public/static`);
|
|
87
94
|
return spinner.stopAndPersist({
|
|
88
95
|
symbol: log_symbols_1.default.success,
|
|
89
96
|
text: 'Emails preview generated',
|
|
Binary file
|
package/emails/test.jsx
ADDED
package/emails/test.tsx
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-email",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "A live preview of your emails right in your browser.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"email": "./dist/index.js"
|
|
@@ -47,4 +47,4 @@
|
|
|
47
47
|
"prettier": "2.7.1",
|
|
48
48
|
"ts-node": "10.9.1"
|
|
49
49
|
}
|
|
50
|
-
}
|
|
50
|
+
}
|
package/preview/package.json
CHANGED
|
@@ -10,8 +10,11 @@ export const CONTENT_DIR = 'emails';
|
|
|
10
10
|
|
|
11
11
|
const getEmails = async () => {
|
|
12
12
|
const emailsDirectory = path.join(process.cwd(), CONTENT_DIR);
|
|
13
|
+
|
|
13
14
|
const filenames = await fs.readdir(emailsDirectory);
|
|
14
|
-
const emails = filenames
|
|
15
|
+
const emails = filenames
|
|
16
|
+
.map((file) => file.replace(/\.(jsx|tsx)$/g, ''))
|
|
17
|
+
.filter((file) => file !== 'components');
|
|
15
18
|
|
|
16
19
|
return emails;
|
|
17
20
|
};
|
|
@@ -15,7 +15,9 @@ export const CONTENT_DIR = 'emails';
|
|
|
15
15
|
const getEmails = async () => {
|
|
16
16
|
const emailsDirectory = path.join(process.cwd(), CONTENT_DIR);
|
|
17
17
|
const filenames = await fs.readdir(emailsDirectory);
|
|
18
|
-
const emails = filenames
|
|
18
|
+
const emails = filenames
|
|
19
|
+
.map((file) => file.replace(/\.(jsx|tsx)$/g, ''))
|
|
20
|
+
.filter((file) => file !== 'components');
|
|
19
21
|
return { emails, filenames };
|
|
20
22
|
};
|
|
21
23
|
|
package/source/_preview/pages.ts
CHANGED
|
@@ -12,12 +12,12 @@ export const pages = [
|
|
|
12
12
|
{
|
|
13
13
|
title: 'index.tsx',
|
|
14
14
|
content:
|
|
15
|
-
"import { promises as fs } from 'fs';\nimport path from 'path';\nimport { Button, Heading, Text } from '../components';\nimport { Layout } from '../components/layout';\nimport Link from 'next/link';\n\ninterface HomeProps {}\n\nexport const CONTENT_DIR = 'emails';\n\nconst getEmails = async () => {\n const emailsDirectory = path.join(process.cwd(), CONTENT_DIR);\n const filenames = await fs.readdir(emailsDirectory);\n const emails = filenames.map((file) => file.replace(/\\.(jsx|tsx)$/g, ''));\n\n return emails;\n};\n\nexport async function getStaticProps({ params }) {\n try {\n const emails = await getEmails();\n return emails\n ? { props: { navItems: emails } }\n : { props: { navItems: [] } };\n } catch (error) {\n console.error(error);\n return { props: { navItems: [] } };\n }\n}\n\nconst Home: React.FC<Readonly<HomeProps>> = ({ navItems }: any) => {\n return (\n <Layout navItems={navItems}>\n <div className=\"max-w-md border border-slate-6 mx-auto mt-56 rounded-md p-8\">\n <Heading as=\"h2\" weight=\"medium\">\n Welcome to the React Email preview!\n </Heading>\n <Text as=\"p\" className=\"mt-2 mb-4\">\n To start developing your next email template, you can create a{' '}\n <code>.jsx</code> or <code>.tsx</code> file under the \"emails\" folder.\n </Text>\n\n <Button asChild>\n <Link href=\"https://react.email/docs\">Check the docs</Link>\n </Button>\n </div>\n </Layout>\n );\n};\n\nexport default Home;\n",
|
|
15
|
+
"import { promises as fs } from 'fs';\nimport path from 'path';\nimport { Button, Heading, Text } from '../components';\nimport { Layout } from '../components/layout';\nimport Link from 'next/link';\n\ninterface HomeProps {}\n\nexport const CONTENT_DIR = 'emails';\n\nconst getEmails = async () => {\n const emailsDirectory = path.join(process.cwd(), CONTENT_DIR);\n\n const filenames = await fs.readdir(emailsDirectory);\n const emails = filenames\n .map((file) => file.replace(/\\.(jsx|tsx)$/g, ''))\n .filter((file) => file !== 'components');\n\n return emails;\n};\n\nexport async function getStaticProps({ params }) {\n try {\n const emails = await getEmails();\n return emails\n ? { props: { navItems: emails } }\n : { props: { navItems: [] } };\n } catch (error) {\n console.error(error);\n return { props: { navItems: [] } };\n }\n}\n\nconst Home: React.FC<Readonly<HomeProps>> = ({ navItems }: any) => {\n return (\n <Layout navItems={navItems}>\n <div className=\"max-w-md border border-slate-6 mx-auto mt-56 rounded-md p-8\">\n <Heading as=\"h2\" weight=\"medium\">\n Welcome to the React Email preview!\n </Heading>\n <Text as=\"p\" className=\"mt-2 mb-4\">\n To start developing your next email template, you can create a{' '}\n <code>.jsx</code> or <code>.tsx</code> file under the \"emails\" folder.\n </Text>\n\n <Button asChild>\n <Link href=\"https://react.email/docs\">Check the docs</Link>\n </Button>\n </div>\n </Layout>\n );\n};\n\nexport default Home;\n",
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
dir: 'preview',
|
|
19
19
|
title: '[slug].tsx',
|
|
20
20
|
content:
|
|
21
|
-
"import { promises as fs } from 'fs';\nimport path from 'path';\nimport { render } from '@react-email/render';\nimport { GetStaticPaths } from 'next';\nimport { Layout } from '../../components/layout';\nimport
|
|
21
|
+
"import * as React from 'react';\nimport { promises as fs } from 'fs';\nimport path from 'path';\nimport { render } from '@react-email/render';\nimport { GetStaticPaths } from 'next';\nimport { Layout } from '../../components/layout';\nimport { Code } from '../../components';\nimport Head from 'next/head';\nimport { useRouter } from 'next/router';\n\ninterface PreviewProps {}\n\nexport const CONTENT_DIR = 'emails';\n\nconst getEmails = async () => {\n const emailsDirectory = path.join(process.cwd(), CONTENT_DIR);\n const filenames = await fs.readdir(emailsDirectory);\n const emails = filenames\n .map((file) => file.replace(/\\.(jsx|tsx)$/g, ''))\n .filter((file) => file !== 'components');\n return { emails, filenames };\n};\n\nexport const getStaticPaths: GetStaticPaths = async () => {\n const { emails } = await getEmails();\n const paths = emails.map((email) => {\n return { params: { slug: email } };\n });\n return { paths, fallback: true };\n};\n\nexport async function getStaticProps({ params }) {\n try {\n const { emails, filenames } = await getEmails();\n const template = filenames.filter((email) => {\n const [fileName] = email.split('.');\n return params.slug === fileName;\n });\n\n const Email = (await import(`../../../emails/${params.slug}`)).default;\n const markup = render(<Email />, { pretty: true });\n const path = `${process.cwd()}/${CONTENT_DIR}/${template[0]}`;\n const reactMarkup = await fs.readFile(path, {\n encoding: 'utf-8',\n });\n\n return emails\n ? { props: { navItems: emails, slug: params.slug, markup, reactMarkup } }\n : { notFound: true };\n } catch (error) {\n console.error(error);\n return { notFound: true };\n }\n}\n\nconst Preview: React.FC<Readonly<PreviewProps>> = ({\n navItems,\n markup,\n reactMarkup,\n slug,\n}: any) => {\n const title = `${slug} — React Email`;\n const router = useRouter();\n const [viewMode, setViewMode] = React.useState('desktop');\n\n const handleViewMode = (mode: string) => {\n setViewMode(mode);\n\n router.push({\n pathname: router.pathname,\n query: {\n ...router.query,\n view: mode,\n },\n });\n };\n\n React.useEffect(() => {\n if (router.query.view === 'source' || router.query.view === 'desktop') {\n setViewMode(router.query.view);\n }\n }, [router.query.view]);\n\n return (\n <Layout\n navItems={navItems}\n title={slug}\n viewMode={viewMode}\n setViewMode={handleViewMode}\n >\n <Head>\n <title>{title}</title>\n </Head>\n {viewMode === 'desktop' ? (\n <iframe\n srcDoc={markup}\n frameBorder=\"0\"\n className=\"w-full h-[calc(100vh_-_70px)]\"\n />\n ) : (\n <div className=\"flex gap-6 mx-auto p-6\">\n <Code>{reactMarkup}</Code>\n <Code>{markup}</Code>\n </div>\n )}\n </Layout>\n );\n};\n\nexport default Preview;\n",
|
|
22
22
|
},
|
|
23
23
|
];
|
package/source/_preview/root.ts
CHANGED
|
@@ -7,7 +7,7 @@ export const root = [
|
|
|
7
7
|
{
|
|
8
8
|
title: 'package.json',
|
|
9
9
|
content:
|
|
10
|
-
'{\n "name": "react-email-preview",\n "version": "0.0.4",\n "description": "The React Email preview application",\n "license": "MIT",\n "scripts": {\n "dev": "next dev",\n "build": "next build",\n "start": "next start",\n "lint": "next lint",\n "format:check": "prettier --check \\"**/*.{ts,tsx,md}\\"",\n "format": "prettier --write \\"**/*.{ts,tsx,md}\\""\n },\n "dependencies": {\n "@next/font": "13.0.4",\n "@radix-ui/colors": "0.1.8",\n "@radix-ui/react-collapsible": "1.0.1",\n "@radix-ui/react-slot": "1.0.1",\n "@radix-ui/react-toggle-group": "1.0.1",\n "@react-email/render": "0.0.2",\n "classnames": "2.3.2",\n "next": "13.0.4",\n "prism-react-renderer": "1.3.5",\n "react": "18.2.0",\n "react-dom": "18.2.0"\n },\n "devDependencies": {\n "@types/classnames": "2.3.1",\n "@types/node": "18.11.9",\n "@types/react": "18.0.25",\n "@types/react-dom": "18.0.9",\n "autoprefixer": "10.4.13",\n "postcss": "8.4.19",\n "tailwindcss": "3.2.4",\n "typescript": "4.9.3"\n }\n}
|
|
10
|
+
'{\n "name": "react-email-preview",\n "version": "0.0.4",\n "description": "The React Email preview application",\n "license": "MIT",\n "scripts": {\n "dev": "next dev",\n "build": "next build",\n "start": "next start",\n "lint": "next lint",\n "format:check": "prettier --check \\"**/*.{ts,tsx,md}\\"",\n "format": "prettier --write \\"**/*.{ts,tsx,md}\\""\n },\n "engines": {\n "node": ">=18.0.0"\n },\n "dependencies": {\n "@next/font": "13.0.4",\n "@radix-ui/colors": "0.1.8",\n "@radix-ui/react-collapsible": "1.0.1",\n "@radix-ui/react-slot": "1.0.1",\n "@radix-ui/react-toggle-group": "1.0.1",\n "@react-email/render": "0.0.2",\n "classnames": "2.3.2",\n "next": "13.0.4",\n "prism-react-renderer": "1.3.5",\n "react": "18.2.0",\n "react-dom": "18.2.0"\n },\n "devDependencies": {\n "@types/classnames": "2.3.1",\n "@types/node": "18.11.9",\n "@types/react": "18.0.25",\n "@types/react-dom": "18.0.9",\n "autoprefixer": "10.4.13",\n "postcss": "8.4.19",\n "tailwindcss": "3.2.4",\n "typescript": "4.9.3"\n }\n}',
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
title: 'postcss.config.js',
|
package/source/commands/dev.ts
CHANGED
|
@@ -31,12 +31,13 @@ export const dev = async () => {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
const prepareFiles = async () => {
|
|
34
|
-
const spinner = ora('Preparing React
|
|
34
|
+
const spinner = ora('Preparing React Email files...').start();
|
|
35
35
|
const isFirstTime = !checkDirectoryExist(REACT_EMAIL_ROOT);
|
|
36
36
|
|
|
37
37
|
if (isFirstTime) {
|
|
38
38
|
await createDirectory(REACT_EMAIL_ROOT);
|
|
39
39
|
await createDirectory(path.join(REACT_EMAIL_ROOT, 'src'));
|
|
40
|
+
await createDirectory(path.join(REACT_EMAIL_ROOT, 'public'));
|
|
40
41
|
|
|
41
42
|
await Promise.all([
|
|
42
43
|
createFilesAndDirectories(components, 'components'),
|
|
@@ -65,7 +66,7 @@ const checkForUpdates = async () => {
|
|
|
65
66
|
if (isUpToDate) {
|
|
66
67
|
return spinner.stopAndPersist({
|
|
67
68
|
symbol: logSymbols.success,
|
|
68
|
-
text: 'React
|
|
69
|
+
text: 'React Email is up-to-date',
|
|
69
70
|
});
|
|
70
71
|
}
|
|
71
72
|
|
|
@@ -73,10 +74,9 @@ const checkForUpdates = async () => {
|
|
|
73
74
|
};
|
|
74
75
|
|
|
75
76
|
const updatePackage = async () => {
|
|
76
|
-
const spinner = ora('Updating React
|
|
77
|
+
const spinner = ora('Updating React Email...').start();
|
|
77
78
|
|
|
78
79
|
await Promise.all([
|
|
79
|
-
createFilesAndDirectories(components, 'components'),
|
|
80
80
|
createFilesAndDirectories(utils, 'utils'),
|
|
81
81
|
createFilesAndDirectories(styles, 'styles'),
|
|
82
82
|
createFilesAndDirectories(root),
|
|
@@ -85,7 +85,7 @@ const updatePackage = async () => {
|
|
|
85
85
|
|
|
86
86
|
spinner.stopAndPersist({
|
|
87
87
|
symbol: logSymbols.success,
|
|
88
|
-
text: 'React
|
|
88
|
+
text: 'React Email is updated',
|
|
89
89
|
});
|
|
90
90
|
};
|
|
91
91
|
|
|
@@ -93,13 +93,26 @@ const generateEmailsPreview = async () => {
|
|
|
93
93
|
const spinner = ora('Generating emails preview').start();
|
|
94
94
|
const hasEmailsDirectory = fs.existsSync(CLIENT_EMAILS_PATH);
|
|
95
95
|
const hasPackageEmailsDirectory = fs.existsSync(PACKAGE_EMAILS_PATH);
|
|
96
|
+
const hasPackagePublicDirectory = fs.existsSync(
|
|
97
|
+
`${REACT_EMAIL_ROOT}/public/static`,
|
|
98
|
+
);
|
|
96
99
|
|
|
97
100
|
if (hasEmailsDirectory) {
|
|
98
101
|
if (hasPackageEmailsDirectory) {
|
|
99
|
-
await fs.promises.
|
|
102
|
+
await fs.promises.rm(PACKAGE_EMAILS_PATH, { recursive: true });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (hasPackagePublicDirectory) {
|
|
106
|
+
await fs.promises.rm(`${REACT_EMAIL_ROOT}/public`, {
|
|
107
|
+
recursive: true,
|
|
108
|
+
});
|
|
100
109
|
}
|
|
101
110
|
|
|
102
|
-
await copy(CLIENT_EMAILS_PATH
|
|
111
|
+
await copy(`${CLIENT_EMAILS_PATH}/*{.tsx,.jsx}`, PACKAGE_EMAILS_PATH);
|
|
112
|
+
await copy(
|
|
113
|
+
`${CLIENT_EMAILS_PATH}/static`,
|
|
114
|
+
`${REACT_EMAIL_ROOT}/public/static`,
|
|
115
|
+
);
|
|
103
116
|
return spinner.stopAndPersist({
|
|
104
117
|
symbol: logSymbols.success,
|
|
105
118
|
text: 'Emails preview generated',
|