react-email 3.0.6 → 4.0.0-alpha.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 +6 -0
- package/dist/cli/index.js +768 -763
- package/dist/cli/index.mjs +480 -476
- package/dist/preview/.next/BUILD_ID +1 -1
- package/dist/preview/.next/app-build-manifest.json +14 -12
- package/dist/preview/.next/build-manifest.json +5 -5
- package/dist/preview/.next/cache/.rscinfo +1 -1
- package/dist/preview/.next/cache/webpack/client-production/0.pack +0 -0
- package/dist/preview/.next/cache/webpack/client-production/index.pack +0 -0
- package/dist/preview/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/dist/preview/.next/cache/webpack/server-production/0.pack +0 -0
- package/dist/preview/.next/cache/webpack/server-production/index.pack +0 -0
- package/dist/preview/.next/next-minimal-server.js.nft.json +1 -1
- package/dist/preview/.next/next-server.js.nft.json +1 -1
- package/dist/preview/.next/prerender-manifest.json +1 -1
- package/dist/preview/.next/server/app/_not-found/page.js +1 -1
- package/dist/preview/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/preview/.next/server/app/page.js +1 -1
- package/dist/preview/.next/server/app/page.js.nft.json +1 -1
- package/dist/preview/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/preview/.next/server/app/preview/[...slug]/page.js +6 -6
- package/dist/preview/.next/server/app/preview/[...slug]/page.js.nft.json +1 -1
- package/dist/preview/.next/server/app/preview/[...slug]/page_client-reference-manifest.js +1 -1
- package/dist/preview/.next/server/chunks/273.js +1 -0
- package/dist/preview/.next/server/chunks/594.js +10 -0
- package/dist/preview/.next/server/middleware-build-manifest.js +1 -1
- package/dist/preview/.next/server/pages/500.html +1 -1
- package/dist/preview/.next/server/server-reference-manifest.js +1 -1
- package/dist/preview/.next/server/server-reference-manifest.json +1 -1
- package/dist/preview/.next/server/webpack-runtime.js +1 -1
- package/dist/preview/.next/static/chunks/18b16e15-6ad9b58e10ff8891.js +1 -0
- package/dist/preview/.next/static/chunks/490-48951f2e19ae3aef.js +1 -0
- package/dist/preview/.next/static/chunks/600-2e2ca4c8bbd97b61.js +1 -0
- package/dist/preview/.next/static/chunks/app/{layout-a2901ed1c2c53661.js → layout-490964e2c3604d33.js} +1 -1
- package/dist/preview/.next/static/chunks/app/page-d2432acd08db8fc0.js +1 -0
- package/dist/preview/.next/static/chunks/app/preview/[...slug]/page-f4e211e00c026401.js +1 -0
- package/dist/preview/.next/static/chunks/webpack-7bf1ffb05f5540be.js +1 -0
- package/dist/preview/.next/static/css/5e0736cafbb392a9.css +3 -0
- package/dist/preview/.next/trace +21 -21
- package/package.json +12 -7
- package/postcss.config.js +1 -1
- package/src/actions/email-validation/check-links.ts +88 -0
- package/src/actions/email-validation/get-line-and-column-from-index.spec.ts +22 -0
- package/src/actions/email-validation/get-line-and-column-from-index.ts +43 -0
- package/src/actions/email-validation/quick-fetch.ts +12 -0
- package/src/actions/get-email-path-from-slug.ts +7 -4
- package/src/actions/render-email-by-path.tsx +3 -3
- 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/globals.css +0 -24
- package/src/app/layout.tsx +7 -3
- package/src/app/page.tsx +9 -10
- package/src/app/preview/[...slug]/page.tsx +3 -2
- package/src/app/preview/[...slug]/preview.tsx +5 -5
- package/src/app/preview/[...slug]/rendering-error.tsx +6 -6
- package/src/components/button.tsx +8 -8
- package/src/components/code-container.tsx +7 -7
- package/src/components/code-snippet.tsx +11 -0
- package/src/components/code.tsx +4 -4
- package/src/components/heading.tsx +1 -1
- package/src/components/icons/icon-button.tsx +1 -1
- package/src/components/icons/icon-circle-check.tsx +21 -0
- package/src/components/icons/icon-circle-close.tsx +17 -0
- package/src/components/icons/icon-circle-warning.tsx +17 -0
- package/src/components/icons/icon-email.tsx +18 -0
- package/src/components/icons/icon-link.tsx +14 -0
- package/src/components/icons/icon-stamp.tsx +14 -0
- package/src/components/send.tsx +9 -9
- package/src/components/shell.tsx +32 -34
- package/src/components/sidebar/{sidebar-directory-children.tsx → file-tree-directory-children.tsx} +22 -18
- package/src/components/sidebar/{sidebar-directory.tsx → file-tree-directory.tsx} +11 -12
- package/src/components/sidebar/file-tree.tsx +31 -0
- package/src/components/sidebar/link-checker.tsx +291 -0
- package/src/components/sidebar/sidebar.tsx +296 -22
- package/src/components/text.tsx +1 -1
- package/src/components/tooltip-content.tsx +3 -3
- package/src/components/tooltip.tsx +1 -1
- package/src/components/topbar.tsx +14 -17
- package/src/hooks/use-email-rendering-result.ts +2 -2
- package/src/hooks/use-icon-animation.ts +44 -0
- package/src/utils/cn.ts +1 -1
- package/src/utils/esbuild/renderring-utilities-exporter.ts +1 -1
- package/src/utils/get-email-component.ts +6 -6
- package/src/utils/get-emails-directory-metadata.spec.ts +0 -1
- package/src/utils/improve-error-with-sourcemap.ts +1 -1
- package/src/utils/static-node-modules-for-vm.ts +6 -6
- package/tsconfig.json +2 -6
- package/.eslintrc.js +0 -52
- package/.prettierignore +0 -3
- package/.prettierrc.js +0 -8
- package/dist/preview/.next/cache/eslint/.cache_1c3sgg +0 -1
- package/dist/preview/.next/server/chunks/391.js +0 -1
- package/dist/preview/.next/server/chunks/720.js +0 -10
- package/dist/preview/.next/static/chunks/12-b9450aa0845e7574.js +0 -1
- package/dist/preview/.next/static/chunks/154-4202f86af36ccff4.js +0 -1
- package/dist/preview/.next/static/chunks/app/page-54a86772095e22e0.js +0 -1
- package/dist/preview/.next/static/chunks/app/preview/[...slug]/page-2bfad134b65ddd79.js +0 -1
- package/dist/preview/.next/static/chunks/webpack-9255716c9496e606.js +0 -1
- package/dist/preview/.next/static/css/eb0a93282704d7ab.css +0 -3
- /package/dist/preview/.next/static/{Trk1e7GzgKOLunAXBDCy- → fZaiKz58wDr55pxLu9uHa}/_buildManifest.js +0 -0
- /package/dist/preview/.next/static/{Trk1e7GzgKOLunAXBDCy- → fZaiKz58wDr55pxLu9uHa}/_ssgManifest.js +0 -0
package/dist/cli/index.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import { program } from "commander";
|
|
|
13
13
|
// package.json
|
|
14
14
|
var package_default = {
|
|
15
15
|
name: "react-email",
|
|
16
|
-
version: "
|
|
16
|
+
version: "4.0.0-alpha.0",
|
|
17
17
|
description: "A live preview of your emails right in your browser.",
|
|
18
18
|
bin: {
|
|
19
19
|
email: "./dist/cli/index.js"
|
|
@@ -23,8 +23,7 @@ var package_default = {
|
|
|
23
23
|
dev: "tsup-node --watch",
|
|
24
24
|
test: "vitest run",
|
|
25
25
|
"test:watch": "vitest",
|
|
26
|
-
clean: "rm -rf dist"
|
|
27
|
-
lint: "eslint . && tsc"
|
|
26
|
+
clean: "rm -rf dist"
|
|
28
27
|
},
|
|
29
28
|
license: "MIT",
|
|
30
29
|
repository: {
|
|
@@ -40,8 +39,8 @@ var package_default = {
|
|
|
40
39
|
node: ">=18.0.0"
|
|
41
40
|
},
|
|
42
41
|
dependencies: {
|
|
43
|
-
"@babel/core": "7.24.5",
|
|
44
42
|
"@babel/parser": "7.24.5",
|
|
43
|
+
"@babel/traverse": "7.25.6",
|
|
45
44
|
chalk: "4.1.2",
|
|
46
45
|
chokidar: "4.0.3",
|
|
47
46
|
commander: "11.1.0",
|
|
@@ -55,16 +54,22 @@ var package_default = {
|
|
|
55
54
|
ora: "5.4.1",
|
|
56
55
|
"socket.io": "4.8.0"
|
|
57
56
|
},
|
|
57
|
+
overrides: {
|
|
58
|
+
react: "^19",
|
|
59
|
+
"react-dom": "^19"
|
|
60
|
+
},
|
|
58
61
|
devDependencies: {
|
|
59
62
|
"@radix-ui/colors": "1.0.1",
|
|
60
63
|
"@radix-ui/react-collapsible": "1.1.0",
|
|
61
64
|
"@radix-ui/react-popover": "1.1.1",
|
|
62
65
|
"@radix-ui/react-slot": "1.1.0",
|
|
66
|
+
"@radix-ui/react-tabs": "1.1.1",
|
|
63
67
|
"@radix-ui/react-toggle-group": "1.1.0",
|
|
64
68
|
"@radix-ui/react-tooltip": "1.1.2",
|
|
65
69
|
"@react-email/render": "workspace:*",
|
|
66
70
|
"@swc/core": "1.4.15",
|
|
67
71
|
"@types/babel__core": "7.20.5",
|
|
72
|
+
"@types/babel__traverse": "*",
|
|
68
73
|
"@types/fs-extra": "11.0.1",
|
|
69
74
|
"@types/mime-types": "2.1.4",
|
|
70
75
|
"@types/node": "22.10.2",
|
|
@@ -75,11 +80,11 @@ var package_default = {
|
|
|
75
80
|
"@vercel/style-guide": "5.1.0",
|
|
76
81
|
autoprefixer: "10.4.20",
|
|
77
82
|
clsx: "2.1.0",
|
|
78
|
-
eslint: "8.50.0",
|
|
79
|
-
"eslint-config-prettier": "9.0.0",
|
|
80
|
-
"eslint-config-turbo": "2.1.0",
|
|
81
83
|
"framer-motion": "12.0.0-alpha.2",
|
|
84
|
+
"lottie-react": "^2.4.0",
|
|
85
|
+
"node-html-parser": "6.1.13",
|
|
82
86
|
postcss: "8.4.40",
|
|
87
|
+
"prettier-plugin-tailwindcss": "0.6.6",
|
|
83
88
|
"prism-react-renderer": "2.1.0",
|
|
84
89
|
react: "^19",
|
|
85
90
|
"react-dom": "^19",
|
|
@@ -97,13 +102,112 @@ var package_default = {
|
|
|
97
102
|
}
|
|
98
103
|
};
|
|
99
104
|
|
|
100
|
-
// src/cli/commands/
|
|
101
|
-
import
|
|
105
|
+
// src/cli/commands/build.ts
|
|
106
|
+
import { spawn } from "node:child_process";
|
|
107
|
+
import fs5 from "node:fs";
|
|
108
|
+
import path8 from "node:path";
|
|
109
|
+
import logSymbols3 from "log-symbols";
|
|
110
|
+
import ora2 from "ora";
|
|
111
|
+
|
|
112
|
+
// src/utils/get-emails-directory-metadata.ts
|
|
113
|
+
import fs from "node:fs";
|
|
114
|
+
import path from "node:path";
|
|
115
|
+
var isFileAnEmail = (fullPath) => {
|
|
116
|
+
const stat = fs.statSync(fullPath);
|
|
117
|
+
if (stat.isDirectory())
|
|
118
|
+
return false;
|
|
119
|
+
const { ext } = path.parse(fullPath);
|
|
120
|
+
if (![".js", ".tsx", ".jsx"].includes(ext))
|
|
121
|
+
return false;
|
|
122
|
+
if (!fs.existsSync(fullPath)) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
const fileContents = fs.readFileSync(fullPath, "utf8");
|
|
126
|
+
return /\bexport\s+default\b/gm.test(fileContents);
|
|
127
|
+
};
|
|
128
|
+
var mergeDirectoriesWithSubDirectories = (emailsDirectoryMetadata) => {
|
|
129
|
+
let currentResultingMergedDirectory = emailsDirectoryMetadata;
|
|
130
|
+
while (currentResultingMergedDirectory.emailFilenames.length === 0 && currentResultingMergedDirectory.subDirectories.length === 1) {
|
|
131
|
+
const onlySubDirectory = currentResultingMergedDirectory.subDirectories[0];
|
|
132
|
+
currentResultingMergedDirectory = {
|
|
133
|
+
...onlySubDirectory,
|
|
134
|
+
directoryName: path.join(
|
|
135
|
+
currentResultingMergedDirectory.directoryName,
|
|
136
|
+
onlySubDirectory.directoryName
|
|
137
|
+
)
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return currentResultingMergedDirectory;
|
|
141
|
+
};
|
|
142
|
+
var getEmailsDirectoryMetadata = async (absolutePathToEmailsDirectory, keepFileExtensions = false, isSubDirectory = false, baseDirectoryPath = absolutePathToEmailsDirectory) => {
|
|
143
|
+
if (!fs.existsSync(absolutePathToEmailsDirectory))
|
|
144
|
+
return;
|
|
145
|
+
const dirents = await fs.promises.readdir(absolutePathToEmailsDirectory, {
|
|
146
|
+
withFileTypes: true
|
|
147
|
+
});
|
|
148
|
+
const emailFilenames = dirents.filter(
|
|
149
|
+
(dirent) => isFileAnEmail(path.join(absolutePathToEmailsDirectory, dirent.name))
|
|
150
|
+
).map(
|
|
151
|
+
(dirent) => keepFileExtensions ? dirent.name : dirent.name.replace(path.extname(dirent.name), "")
|
|
152
|
+
);
|
|
153
|
+
const subDirectories = await Promise.all(
|
|
154
|
+
dirents.filter(
|
|
155
|
+
(dirent) => dirent.isDirectory() && !dirent.name.startsWith("_") && dirent.name !== "static"
|
|
156
|
+
).map((dirent) => {
|
|
157
|
+
const direntAbsolutePath = path.join(
|
|
158
|
+
absolutePathToEmailsDirectory,
|
|
159
|
+
dirent.name
|
|
160
|
+
);
|
|
161
|
+
return getEmailsDirectoryMetadata(
|
|
162
|
+
direntAbsolutePath,
|
|
163
|
+
keepFileExtensions,
|
|
164
|
+
true,
|
|
165
|
+
baseDirectoryPath
|
|
166
|
+
);
|
|
167
|
+
})
|
|
168
|
+
);
|
|
169
|
+
const emailsMetadata = {
|
|
170
|
+
absolutePath: absolutePathToEmailsDirectory,
|
|
171
|
+
relativePath: path.relative(
|
|
172
|
+
baseDirectoryPath,
|
|
173
|
+
absolutePathToEmailsDirectory
|
|
174
|
+
),
|
|
175
|
+
directoryName: absolutePathToEmailsDirectory.split(path.sep).pop(),
|
|
176
|
+
emailFilenames,
|
|
177
|
+
subDirectories
|
|
178
|
+
};
|
|
179
|
+
return isSubDirectory ? mergeDirectoriesWithSubDirectories(emailsMetadata) : emailsMetadata;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// src/utils/register-spinner-autostopping.ts
|
|
183
|
+
import logSymbols from "log-symbols";
|
|
184
|
+
var spinners = /* @__PURE__ */ new Set();
|
|
185
|
+
process.on("SIGINT", () => {
|
|
186
|
+
spinners.forEach((spinner) => {
|
|
187
|
+
if (spinner.isSpinning) {
|
|
188
|
+
spinner.stop();
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
process.on("exit", (code) => {
|
|
193
|
+
if (code !== 0) {
|
|
194
|
+
spinners.forEach((spinner) => {
|
|
195
|
+
if (spinner.isSpinning) {
|
|
196
|
+
spinner.stopAndPersist({
|
|
197
|
+
symbol: logSymbols.error
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
var registerSpinnerAutostopping = (spinner) => {
|
|
204
|
+
spinners.add(spinner);
|
|
205
|
+
};
|
|
102
206
|
|
|
103
207
|
// src/cli/utils/tree.ts
|
|
104
|
-
import { promises as
|
|
208
|
+
import { promises as fs2 } from "node:fs";
|
|
105
209
|
import os from "node:os";
|
|
106
|
-
import
|
|
210
|
+
import path2 from "node:path";
|
|
107
211
|
var SYMBOLS = {
|
|
108
212
|
BRANCH: "\u251C\u2500\u2500 ",
|
|
109
213
|
EMPTY: "",
|
|
@@ -113,12 +217,12 @@ var SYMBOLS = {
|
|
|
113
217
|
};
|
|
114
218
|
var getTreeLines = async (dirPath, depth, currentDepth = 0) => {
|
|
115
219
|
const base = process.cwd();
|
|
116
|
-
const dirFullpath =
|
|
117
|
-
const dirname =
|
|
220
|
+
const dirFullpath = path2.resolve(base, dirPath);
|
|
221
|
+
const dirname = path2.basename(dirFullpath);
|
|
118
222
|
let lines = [dirname];
|
|
119
|
-
const dirStat = await
|
|
223
|
+
const dirStat = await fs2.stat(dirFullpath);
|
|
120
224
|
if (dirStat.isDirectory() && currentDepth < depth) {
|
|
121
|
-
const childDirents = await
|
|
225
|
+
const childDirents = await fs2.readdir(dirFullpath, { withFileTypes: true });
|
|
122
226
|
childDirents.sort((a, b) => {
|
|
123
227
|
if (a.isDirectory() && b.isFile()) {
|
|
124
228
|
return -1;
|
|
@@ -136,7 +240,7 @@ var getTreeLines = async (dirPath, depth, currentDepth = 0) => {
|
|
|
136
240
|
if (dirent.isFile()) {
|
|
137
241
|
lines.push(`${branchingSymbol}${dirent.name}`);
|
|
138
242
|
} else {
|
|
139
|
-
const pathToDirectory =
|
|
243
|
+
const pathToDirectory = path2.join(dirFullpath, dirent.name);
|
|
140
244
|
const treeLinesForSubDirectory = await getTreeLines(
|
|
141
245
|
pathToDirectory,
|
|
142
246
|
depth,
|
|
@@ -158,98 +262,46 @@ var tree = async (dirPath, depth) => {
|
|
|
158
262
|
};
|
|
159
263
|
|
|
160
264
|
// src/cli/utils/preview/hot-reloading/setup-hot-reloading.ts
|
|
161
|
-
import
|
|
162
|
-
import { Server as SocketServer } from "socket.io";
|
|
265
|
+
import path7 from "node:path";
|
|
163
266
|
import { watch } from "chokidar";
|
|
164
267
|
import debounce from "debounce";
|
|
268
|
+
import { Server as SocketServer } from "socket.io";
|
|
165
269
|
|
|
166
270
|
// src/cli/utils/preview/hot-reloading/create-dependency-graph.ts
|
|
167
|
-
import
|
|
168
|
-
import
|
|
169
|
-
|
|
170
|
-
// src/cli/utils/preview/hot-reloading/get-imported-modules.ts
|
|
171
|
-
import { traverse } from "@babel/core";
|
|
172
|
-
import { parse } from "@babel/parser";
|
|
173
|
-
var getImportedModules = (contents) => {
|
|
174
|
-
const importedPaths = [];
|
|
175
|
-
const parsedContents = parse(contents, {
|
|
176
|
-
sourceType: "unambiguous",
|
|
177
|
-
strictMode: false,
|
|
178
|
-
errorRecovery: true,
|
|
179
|
-
plugins: ["jsx", "typescript", "decorators"]
|
|
180
|
-
});
|
|
181
|
-
traverse(parsedContents, {
|
|
182
|
-
ImportDeclaration({ node }) {
|
|
183
|
-
importedPaths.push(node.source.value);
|
|
184
|
-
},
|
|
185
|
-
ExportAllDeclaration({ node }) {
|
|
186
|
-
importedPaths.push(node.source.value);
|
|
187
|
-
},
|
|
188
|
-
ExportNamedDeclaration({ node }) {
|
|
189
|
-
if (node.source) {
|
|
190
|
-
importedPaths.push(node.source.value);
|
|
191
|
-
}
|
|
192
|
-
},
|
|
193
|
-
CallExpression({ node }) {
|
|
194
|
-
if ("name" in node.callee && node.callee.name === "require") {
|
|
195
|
-
if (node.arguments.length === 1) {
|
|
196
|
-
const importPathNode = node.arguments[0];
|
|
197
|
-
if (importPathNode.type === "StringLiteral") {
|
|
198
|
-
importedPaths.push(importPathNode.value);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
return importedPaths;
|
|
205
|
-
};
|
|
271
|
+
import { promises as fs4, existsSync, statSync } from "node:fs";
|
|
272
|
+
import path6 from "node:path";
|
|
206
273
|
|
|
207
274
|
// src/cli/utils/preview/start-dev-server.ts
|
|
208
|
-
import path4 from "node:path";
|
|
209
275
|
import http from "node:http";
|
|
276
|
+
import path5 from "node:path";
|
|
210
277
|
import url from "node:url";
|
|
278
|
+
import chalk from "chalk";
|
|
279
|
+
import logSymbols2 from "log-symbols";
|
|
211
280
|
import next from "next";
|
|
212
281
|
import ora from "ora";
|
|
213
|
-
import logSymbols2 from "log-symbols";
|
|
214
|
-
import chalk from "chalk";
|
|
215
282
|
|
|
216
|
-
// src/utils/
|
|
217
|
-
import
|
|
218
|
-
var
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
process.on("exit", (code) => {
|
|
227
|
-
if (code !== 0) {
|
|
228
|
-
spinners.forEach((spinner) => {
|
|
229
|
-
if (spinner.isSpinning) {
|
|
230
|
-
spinner.stopAndPersist({
|
|
231
|
-
symbol: logSymbols.error
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
});
|
|
237
|
-
var registerSpinnerAutostopping = (spinner) => {
|
|
238
|
-
spinners.add(spinner);
|
|
283
|
+
// src/cli/utils/preview/get-env-variables-for-preview-app.ts
|
|
284
|
+
import path3 from "node:path";
|
|
285
|
+
var getEnvVariablesForPreviewApp = (relativePathToEmailsDirectory, cwd) => {
|
|
286
|
+
return {
|
|
287
|
+
EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
|
|
288
|
+
EMAILS_DIR_ABSOLUTE_PATH: path3.resolve(cwd, relativePathToEmailsDirectory),
|
|
289
|
+
USER_PROJECT_LOCATION: cwd
|
|
290
|
+
};
|
|
239
291
|
};
|
|
240
292
|
|
|
241
293
|
// src/cli/utils/preview/serve-static-file.ts
|
|
242
|
-
import
|
|
243
|
-
import
|
|
294
|
+
import { promises as fs3 } from "node:fs";
|
|
295
|
+
import path4 from "node:path";
|
|
244
296
|
import { lookup } from "mime-types";
|
|
245
297
|
var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
|
|
246
|
-
const staticBaseDir =
|
|
298
|
+
const staticBaseDir = path4.join(process.cwd(), staticDirRelativePath);
|
|
247
299
|
const pathname = parsedUrl.pathname;
|
|
248
|
-
const ext =
|
|
249
|
-
|
|
250
|
-
const fileHandle = await
|
|
300
|
+
const ext = path4.parse(pathname).ext;
|
|
301
|
+
const fileAbsolutePath = path4.join(staticBaseDir, pathname);
|
|
302
|
+
const fileHandle = await fs3.open(fileAbsolutePath, "r");
|
|
251
303
|
try {
|
|
252
|
-
const fileData = await
|
|
304
|
+
const fileData = await fs3.readFile(fileHandle);
|
|
253
305
|
res.setHeader("Content-type", lookup(ext) || "text/plain");
|
|
254
306
|
res.end(fileData);
|
|
255
307
|
} catch (exception) {
|
|
@@ -266,16 +318,6 @@ var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
|
|
|
266
318
|
}
|
|
267
319
|
};
|
|
268
320
|
|
|
269
|
-
// src/cli/utils/preview/get-env-variables-for-preview-app.ts
|
|
270
|
-
import path3 from "node:path";
|
|
271
|
-
var getEnvVariablesForPreviewApp = (relativePathToEmailsDirectory, cwd) => {
|
|
272
|
-
return {
|
|
273
|
-
EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
|
|
274
|
-
EMAILS_DIR_ABSOLUTE_PATH: path3.resolve(cwd, relativePathToEmailsDirectory),
|
|
275
|
-
USER_PROJECT_LOCATION: cwd
|
|
276
|
-
};
|
|
277
|
-
};
|
|
278
|
-
|
|
279
321
|
// src/cli/utils/preview/start-dev-server.ts
|
|
280
322
|
var devServer;
|
|
281
323
|
var safeAsyncServerListen = (server, port) => {
|
|
@@ -290,9 +332,9 @@ var safeAsyncServerListen = (server, port) => {
|
|
|
290
332
|
});
|
|
291
333
|
});
|
|
292
334
|
};
|
|
293
|
-
var isDev = !__filename.endsWith(
|
|
294
|
-
var cliPacakgeLocation = isDev ?
|
|
295
|
-
var previewServerLocation = isDev ?
|
|
335
|
+
var isDev = !__filename.endsWith(path5.join("cli", "index.js"));
|
|
336
|
+
var cliPacakgeLocation = isDev ? path5.resolve(__dirname, "../../../..") : path5.resolve(__dirname, "../..");
|
|
337
|
+
var previewServerLocation = isDev ? path5.resolve(__dirname, "../../../..") : path5.resolve(__dirname, "../preview");
|
|
296
338
|
var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, port) => {
|
|
297
339
|
devServer = http.createServer((req, res) => {
|
|
298
340
|
if (!req.url) {
|
|
@@ -307,7 +349,7 @@ var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, po
|
|
|
307
349
|
res.setHeader("Pragma", "no-cache");
|
|
308
350
|
res.setHeader("Expires", "-1");
|
|
309
351
|
try {
|
|
310
|
-
if (parsedUrl.path
|
|
352
|
+
if (parsedUrl.path?.includes("static/") && !parsedUrl.path.includes("_next/static/")) {
|
|
311
353
|
void serveStaticFile(res, parsedUrl, staticBaseDirRelativePath);
|
|
312
354
|
} else if (!isNextReady) {
|
|
313
355
|
void nextReadyPromise.then(
|
|
@@ -359,7 +401,7 @@ var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, po
|
|
|
359
401
|
NODE_ENV: "development",
|
|
360
402
|
...getEnvVariablesForPreviewApp(
|
|
361
403
|
// If we don't do normalization here, stuff like https://github.com/resend/react-email/issues/1354 happens.
|
|
362
|
-
|
|
404
|
+
path5.normalize(emailsDirRelativePath),
|
|
363
405
|
process.cwd()
|
|
364
406
|
)
|
|
365
407
|
};
|
|
@@ -417,12 +459,49 @@ process.on(
|
|
|
417
459
|
makeExitHandler({ shouldKillProcess: true, killWithErrorCode: true })
|
|
418
460
|
);
|
|
419
461
|
|
|
462
|
+
// src/cli/utils/preview/hot-reloading/get-imported-modules.ts
|
|
463
|
+
import { parse } from "@babel/parser";
|
|
464
|
+
import traverse from "@babel/traverse";
|
|
465
|
+
var getImportedModules = (contents) => {
|
|
466
|
+
const importedPaths = [];
|
|
467
|
+
const parsedContents = parse(contents, {
|
|
468
|
+
sourceType: "unambiguous",
|
|
469
|
+
strictMode: false,
|
|
470
|
+
errorRecovery: true,
|
|
471
|
+
plugins: ["jsx", "typescript", "decorators"]
|
|
472
|
+
});
|
|
473
|
+
traverse(parsedContents, {
|
|
474
|
+
ImportDeclaration({ node }) {
|
|
475
|
+
importedPaths.push(node.source.value);
|
|
476
|
+
},
|
|
477
|
+
ExportAllDeclaration({ node }) {
|
|
478
|
+
importedPaths.push(node.source.value);
|
|
479
|
+
},
|
|
480
|
+
ExportNamedDeclaration({ node }) {
|
|
481
|
+
if (node.source) {
|
|
482
|
+
importedPaths.push(node.source.value);
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
CallExpression({ node }) {
|
|
486
|
+
if ("name" in node.callee && node.callee.name === "require") {
|
|
487
|
+
if (node.arguments.length === 1) {
|
|
488
|
+
const importPathNode = node.arguments[0];
|
|
489
|
+
if (importPathNode.type === "StringLiteral") {
|
|
490
|
+
importedPaths.push(importPathNode.value);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
return importedPaths;
|
|
497
|
+
};
|
|
498
|
+
|
|
420
499
|
// src/cli/utils/preview/hot-reloading/create-dependency-graph.ts
|
|
421
500
|
var readAllFilesInsideDirectory = async (directory) => {
|
|
422
501
|
let allFilePaths = [];
|
|
423
|
-
const topLevelDirents = await
|
|
502
|
+
const topLevelDirents = await fs4.readdir(directory, { withFileTypes: true });
|
|
424
503
|
for await (const dirent of topLevelDirents) {
|
|
425
|
-
const pathToDirent =
|
|
504
|
+
const pathToDirent = path6.join(directory, dirent.name);
|
|
426
505
|
if (dirent.isDirectory()) {
|
|
427
506
|
allFilePaths = allFilePaths.concat(
|
|
428
507
|
await readAllFilesInsideDirectory(pathToDirent)
|
|
@@ -434,7 +513,7 @@ var readAllFilesInsideDirectory = async (directory) => {
|
|
|
434
513
|
return allFilePaths;
|
|
435
514
|
};
|
|
436
515
|
var isJavascriptModule = (filePath) => {
|
|
437
|
-
const extensionName =
|
|
516
|
+
const extensionName = path6.extname(filePath);
|
|
438
517
|
return [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"].includes(extensionName);
|
|
439
518
|
};
|
|
440
519
|
var checkFileExtensionsUntilItExists = (pathWithoutExtension) => {
|
|
@@ -472,64 +551,63 @@ var createDependencyGraph = async (directory) => {
|
|
|
472
551
|
])
|
|
473
552
|
);
|
|
474
553
|
const getDependencyPaths = async (filePath) => {
|
|
475
|
-
const contents = await
|
|
554
|
+
const contents = await fs4.readFile(filePath, "utf8");
|
|
476
555
|
const importedPaths = getImportedModules(contents);
|
|
477
556
|
const importedPathsRelativeToDirectory = importedPaths.map(
|
|
478
557
|
(dependencyPath) => {
|
|
479
558
|
const isModulePath = !dependencyPath.startsWith(".");
|
|
480
|
-
if (
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
559
|
+
if (isModulePath || path6.isAbsolute(dependencyPath)) {
|
|
560
|
+
return dependencyPath;
|
|
561
|
+
}
|
|
562
|
+
let pathToDependencyFromDirectory = path6.resolve(
|
|
563
|
+
/*
|
|
564
|
+
path.resolve resolves paths differently from what imports on javascript do.
|
|
565
|
+
|
|
566
|
+
So if we wouldn't do this, for an email at "/path/to/email.tsx" with a dependecy path of "./other-email"
|
|
567
|
+
would end up going into /path/to/email.tsx/other-email instead of /path/to/other-email which is the
|
|
568
|
+
one the import is meant to go to
|
|
569
|
+
*/
|
|
570
|
+
path6.dirname(filePath),
|
|
571
|
+
dependencyPath
|
|
572
|
+
);
|
|
573
|
+
let isDirectory = false;
|
|
574
|
+
try {
|
|
575
|
+
isDirectory = statSync(pathToDependencyFromDirectory).isDirectory();
|
|
576
|
+
} catch (_) {
|
|
577
|
+
}
|
|
578
|
+
if (isDirectory) {
|
|
579
|
+
const pathToSubDirectory = pathToDependencyFromDirectory;
|
|
580
|
+
const pathWithExtension = checkFileExtensionsUntilItExists(
|
|
581
|
+
`${pathToSubDirectory}/index`
|
|
491
582
|
);
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
if (isDirectory) {
|
|
498
|
-
const pathToSubDirectory = pathToDependencyFromDirectory;
|
|
499
|
-
const pathWithExtension = checkFileExtensionsUntilItExists(
|
|
500
|
-
`${pathToSubDirectory}/index`
|
|
583
|
+
if (pathWithExtension) {
|
|
584
|
+
pathToDependencyFromDirectory = pathWithExtension;
|
|
585
|
+
} else if (isDev) {
|
|
586
|
+
console.warn(
|
|
587
|
+
`Could not find index file for directory at ${pathToDependencyFromDirectory}. This is probably going to cause issues with both hot reloading and your code.`
|
|
501
588
|
);
|
|
502
|
-
if (pathWithExtension) {
|
|
503
|
-
pathToDependencyFromDirectory = pathWithExtension;
|
|
504
|
-
} else if (isDev) {
|
|
505
|
-
console.warn(
|
|
506
|
-
`Could not find index file for directory at ${pathToDependencyFromDirectory}. This is probably going to cause issues with both hot reloading and your code.`
|
|
507
|
-
);
|
|
508
|
-
}
|
|
509
589
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
590
|
+
}
|
|
591
|
+
if (!isJavascriptModule(pathToDependencyFromDirectory)) {
|
|
592
|
+
const pathWithExtension = checkFileExtensionsUntilItExists(
|
|
593
|
+
pathToDependencyFromDirectory
|
|
594
|
+
);
|
|
595
|
+
if (pathWithExtension) {
|
|
596
|
+
pathToDependencyFromDirectory = pathWithExtension;
|
|
597
|
+
} else if (isDev) {
|
|
598
|
+
console.warn(
|
|
599
|
+
`Could not determine the file extension for the file at ${pathToDependencyFromDirectory}`
|
|
513
600
|
);
|
|
514
|
-
if (pathWithExtension) {
|
|
515
|
-
pathToDependencyFromDirectory = pathWithExtension;
|
|
516
|
-
} else if (isDev) {
|
|
517
|
-
console.warn(
|
|
518
|
-
`Could not determine the file extension for the file at ${pathToDependencyFromDirectory}`
|
|
519
|
-
);
|
|
520
|
-
}
|
|
521
601
|
}
|
|
522
|
-
return pathToDependencyFromDirectory;
|
|
523
|
-
} else {
|
|
524
|
-
return dependencyPath;
|
|
525
602
|
}
|
|
603
|
+
return pathToDependencyFromDirectory;
|
|
526
604
|
}
|
|
527
605
|
);
|
|
528
606
|
const moduleDependencies = importedPathsRelativeToDirectory.filter(
|
|
529
|
-
(dependencyPath) => !dependencyPath.startsWith(".") && !
|
|
607
|
+
(dependencyPath) => !dependencyPath.startsWith(".") && !path6.isAbsolute(dependencyPath)
|
|
530
608
|
);
|
|
531
609
|
const nonNodeModuleImportPathsRelativeToDirectory = importedPathsRelativeToDirectory.filter(
|
|
532
|
-
(dependencyPath) => dependencyPath.startsWith(".") ||
|
|
610
|
+
(dependencyPath) => dependencyPath.startsWith(".") || path6.isAbsolute(dependencyPath)
|
|
533
611
|
);
|
|
534
612
|
return {
|
|
535
613
|
dependencyPaths: nonNodeModuleImportPathsRelativeToDirectory,
|
|
@@ -658,7 +736,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
658
736
|
});
|
|
659
737
|
changes = [];
|
|
660
738
|
}, 150);
|
|
661
|
-
const absolutePathToEmailsDirectory =
|
|
739
|
+
const absolutePathToEmailsDirectory = path7.resolve(
|
|
662
740
|
process.cwd(),
|
|
663
741
|
emailDirRelativePath
|
|
664
742
|
);
|
|
@@ -668,7 +746,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
668
746
|
cwd: absolutePathToEmailsDirectory
|
|
669
747
|
});
|
|
670
748
|
const getFilesOutsideEmailsDirectory = () => Object.keys(dependencyGraph).filter(
|
|
671
|
-
(p) =>
|
|
749
|
+
(p) => path7.relative(absolutePathToEmailsDirectory, p).startsWith("..")
|
|
672
750
|
);
|
|
673
751
|
let filesOutsideEmailsDirectory = getFilesOutsideEmailsDirectory();
|
|
674
752
|
for (const p of filesOutsideEmailsDirectory) {
|
|
@@ -680,11 +758,11 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
680
758
|
process.on("SIGINT", exit);
|
|
681
759
|
process.on("uncaughtException", exit);
|
|
682
760
|
watcher.on("all", async (event, relativePathToChangeTarget) => {
|
|
683
|
-
const file = relativePathToChangeTarget.split(
|
|
761
|
+
const file = relativePathToChangeTarget.split(path7.sep);
|
|
684
762
|
if (file.length === 0) {
|
|
685
763
|
return;
|
|
686
764
|
}
|
|
687
|
-
const pathToChangeTarget =
|
|
765
|
+
const pathToChangeTarget = path7.resolve(
|
|
688
766
|
absolutePathToEmailsDirectory,
|
|
689
767
|
relativePathToChangeTarget
|
|
690
768
|
);
|
|
@@ -708,7 +786,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
708
786
|
for (const dependentPath of resolveDependentsOf(pathToChangeTarget)) {
|
|
709
787
|
changes.push({
|
|
710
788
|
event: "change",
|
|
711
|
-
filename:
|
|
789
|
+
filename: path7.relative(absolutePathToEmailsDirectory, dependentPath)
|
|
712
790
|
});
|
|
713
791
|
}
|
|
714
792
|
reload();
|
|
@@ -716,300 +794,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
716
794
|
return watcher;
|
|
717
795
|
};
|
|
718
796
|
|
|
719
|
-
// src/cli/commands/dev.ts
|
|
720
|
-
var dev = async ({ dir: emailsDirRelativePath, port }) => {
|
|
721
|
-
try {
|
|
722
|
-
if (!fs4.existsSync(emailsDirRelativePath)) {
|
|
723
|
-
console.error(`Missing ${emailsDirRelativePath} folder`);
|
|
724
|
-
process.exit(1);
|
|
725
|
-
}
|
|
726
|
-
const devServer2 = await startDevServer(
|
|
727
|
-
emailsDirRelativePath,
|
|
728
|
-
emailsDirRelativePath,
|
|
729
|
-
// defaults to ./emails/static for the static files that are served to the preview
|
|
730
|
-
Number.parseInt(port)
|
|
731
|
-
);
|
|
732
|
-
await setupHotreloading(devServer2, emailsDirRelativePath);
|
|
733
|
-
} catch (error) {
|
|
734
|
-
console.log(error);
|
|
735
|
-
process.exit(1);
|
|
736
|
-
}
|
|
737
|
-
};
|
|
738
|
-
|
|
739
|
-
// src/cli/commands/export.ts
|
|
740
|
-
import fs7, { unlinkSync, writeFileSync } from "node:fs";
|
|
741
|
-
import path9 from "node:path";
|
|
742
|
-
import { glob } from "glob";
|
|
743
|
-
import { build } from "esbuild";
|
|
744
|
-
import ora2 from "ora";
|
|
745
|
-
import logSymbols3 from "log-symbols";
|
|
746
|
-
import normalize from "normalize-path";
|
|
747
|
-
|
|
748
|
-
// src/utils/get-emails-directory-metadata.ts
|
|
749
|
-
import fs5 from "node:fs";
|
|
750
|
-
import path7 from "node:path";
|
|
751
|
-
var isFileAnEmail = (fullPath) => {
|
|
752
|
-
const stat = fs5.statSync(fullPath);
|
|
753
|
-
if (stat.isDirectory())
|
|
754
|
-
return false;
|
|
755
|
-
const { ext } = path7.parse(fullPath);
|
|
756
|
-
if (![".js", ".tsx", ".jsx"].includes(ext))
|
|
757
|
-
return false;
|
|
758
|
-
if (!fs5.existsSync(fullPath)) {
|
|
759
|
-
return false;
|
|
760
|
-
}
|
|
761
|
-
const fileContents = fs5.readFileSync(fullPath, "utf8");
|
|
762
|
-
return /\bexport\s+default\b/gm.test(fileContents);
|
|
763
|
-
};
|
|
764
|
-
var mergeDirectoriesWithSubDirectories = (emailsDirectoryMetadata) => {
|
|
765
|
-
let currentResultingMergedDirectory = emailsDirectoryMetadata;
|
|
766
|
-
while (currentResultingMergedDirectory.emailFilenames.length === 0 && currentResultingMergedDirectory.subDirectories.length === 1) {
|
|
767
|
-
const onlySubDirectory = currentResultingMergedDirectory.subDirectories[0];
|
|
768
|
-
currentResultingMergedDirectory = {
|
|
769
|
-
...onlySubDirectory,
|
|
770
|
-
directoryName: path7.join(
|
|
771
|
-
currentResultingMergedDirectory.directoryName,
|
|
772
|
-
onlySubDirectory.directoryName
|
|
773
|
-
)
|
|
774
|
-
};
|
|
775
|
-
}
|
|
776
|
-
return currentResultingMergedDirectory;
|
|
777
|
-
};
|
|
778
|
-
var getEmailsDirectoryMetadata = async (absolutePathToEmailsDirectory, keepFileExtensions = false, isSubDirectory = false, baseDirectoryPath = absolutePathToEmailsDirectory) => {
|
|
779
|
-
if (!fs5.existsSync(absolutePathToEmailsDirectory))
|
|
780
|
-
return;
|
|
781
|
-
const dirents = await fs5.promises.readdir(absolutePathToEmailsDirectory, {
|
|
782
|
-
withFileTypes: true
|
|
783
|
-
});
|
|
784
|
-
const emailFilenames = dirents.filter(
|
|
785
|
-
(dirent) => isFileAnEmail(path7.join(absolutePathToEmailsDirectory, dirent.name))
|
|
786
|
-
).map(
|
|
787
|
-
(dirent) => keepFileExtensions ? dirent.name : dirent.name.replace(path7.extname(dirent.name), "")
|
|
788
|
-
);
|
|
789
|
-
const subDirectories = await Promise.all(
|
|
790
|
-
dirents.filter(
|
|
791
|
-
(dirent) => dirent.isDirectory() && !dirent.name.startsWith("_") && dirent.name !== "static"
|
|
792
|
-
).map((dirent) => {
|
|
793
|
-
const direntAbsolutePath = path7.join(
|
|
794
|
-
absolutePathToEmailsDirectory,
|
|
795
|
-
dirent.name
|
|
796
|
-
);
|
|
797
|
-
return getEmailsDirectoryMetadata(
|
|
798
|
-
direntAbsolutePath,
|
|
799
|
-
keepFileExtensions,
|
|
800
|
-
true,
|
|
801
|
-
baseDirectoryPath
|
|
802
|
-
);
|
|
803
|
-
})
|
|
804
|
-
);
|
|
805
|
-
const emailsMetadata = {
|
|
806
|
-
absolutePath: absolutePathToEmailsDirectory,
|
|
807
|
-
relativePath: path7.relative(
|
|
808
|
-
baseDirectoryPath,
|
|
809
|
-
absolutePathToEmailsDirectory
|
|
810
|
-
),
|
|
811
|
-
directoryName: absolutePathToEmailsDirectory.split(path7.sep).pop(),
|
|
812
|
-
emailFilenames,
|
|
813
|
-
subDirectories
|
|
814
|
-
};
|
|
815
|
-
return isSubDirectory ? mergeDirectoriesWithSubDirectories(emailsMetadata) : emailsMetadata;
|
|
816
|
-
};
|
|
817
|
-
|
|
818
|
-
// src/utils/esbuild/renderring-utilities-exporter.ts
|
|
819
|
-
import path8 from "node:path";
|
|
820
|
-
import { promises as fs6 } from "node:fs";
|
|
821
|
-
|
|
822
|
-
// src/utils/esbuild/escape-string-for-regex.ts
|
|
823
|
-
function escapeStringForRegex(string) {
|
|
824
|
-
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
// src/utils/esbuild/renderring-utilities-exporter.ts
|
|
828
|
-
var renderingUtilitiesExporter = (emailTemplates) => ({
|
|
829
|
-
name: "rendering-utilities-exporter",
|
|
830
|
-
setup: (b) => {
|
|
831
|
-
b.onLoad(
|
|
832
|
-
{
|
|
833
|
-
filter: new RegExp(
|
|
834
|
-
emailTemplates.map((emailPath) => escapeStringForRegex(emailPath)).join("|")
|
|
835
|
-
)
|
|
836
|
-
},
|
|
837
|
-
async ({ path: pathToFile }) => {
|
|
838
|
-
return {
|
|
839
|
-
contents: `${await fs6.readFile(pathToFile, "utf8")};
|
|
840
|
-
export { render } from 'react-email-module-that-will-export-render'
|
|
841
|
-
export { createElement as reactEmailCreateReactElement } from 'react';
|
|
842
|
-
`,
|
|
843
|
-
loader: path8.extname(pathToFile).slice(1)
|
|
844
|
-
};
|
|
845
|
-
}
|
|
846
|
-
);
|
|
847
|
-
b.onResolve(
|
|
848
|
-
{ filter: /^react-email-module-that-will-export-render$/ },
|
|
849
|
-
async (args) => {
|
|
850
|
-
const options = {
|
|
851
|
-
kind: "import-statement",
|
|
852
|
-
importer: args.importer,
|
|
853
|
-
resolveDir: args.resolveDir,
|
|
854
|
-
namespace: args.namespace
|
|
855
|
-
};
|
|
856
|
-
let result = await b.resolve("@react-email/render", options);
|
|
857
|
-
if (result.errors.length === 0) {
|
|
858
|
-
return result;
|
|
859
|
-
}
|
|
860
|
-
result = await b.resolve("@react-email/components", options);
|
|
861
|
-
if (result.errors.length > 0 && result.errors[0]) {
|
|
862
|
-
result.errors[0].text = "Failed trying to import `render` from either `@react-email/render` or `@react-email/components` to be able to render your email template.\n Maybe you don't have either of them installed?";
|
|
863
|
-
}
|
|
864
|
-
return result;
|
|
865
|
-
}
|
|
866
|
-
);
|
|
867
|
-
}
|
|
868
|
-
});
|
|
869
|
-
|
|
870
|
-
// src/cli/commands/export.ts
|
|
871
|
-
var getEmailTemplatesFromDirectory = (emailDirectory) => {
|
|
872
|
-
const templatePaths = [];
|
|
873
|
-
emailDirectory.emailFilenames.forEach(
|
|
874
|
-
(filename) => templatePaths.push(path9.join(emailDirectory.absolutePath, filename))
|
|
875
|
-
);
|
|
876
|
-
emailDirectory.subDirectories.forEach((directory) => {
|
|
877
|
-
templatePaths.push(...getEmailTemplatesFromDirectory(directory));
|
|
878
|
-
});
|
|
879
|
-
return templatePaths;
|
|
880
|
-
};
|
|
881
|
-
var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirectoryPath, options) => {
|
|
882
|
-
if (fs7.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
|
|
883
|
-
fs7.rmSync(pathToWhereEmailMarkupShouldBeDumped, { recursive: true });
|
|
884
|
-
}
|
|
885
|
-
let spinner;
|
|
886
|
-
if (!options.silent) {
|
|
887
|
-
spinner = ora2("Preparing files...\n").start();
|
|
888
|
-
registerSpinnerAutostopping(spinner);
|
|
889
|
-
}
|
|
890
|
-
const emailsDirectoryMetadata = await getEmailsDirectoryMetadata(
|
|
891
|
-
path9.resolve(process.cwd(), emailsDirectoryPath),
|
|
892
|
-
true
|
|
893
|
-
);
|
|
894
|
-
if (typeof emailsDirectoryMetadata === "undefined") {
|
|
895
|
-
if (spinner) {
|
|
896
|
-
spinner.stopAndPersist({
|
|
897
|
-
symbol: logSymbols3.error,
|
|
898
|
-
text: `Could not find the directory at ${emailsDirectoryPath}`
|
|
899
|
-
});
|
|
900
|
-
}
|
|
901
|
-
return;
|
|
902
|
-
}
|
|
903
|
-
const allTemplates = getEmailTemplatesFromDirectory(emailsDirectoryMetadata);
|
|
904
|
-
try {
|
|
905
|
-
await build({
|
|
906
|
-
bundle: true,
|
|
907
|
-
entryPoints: allTemplates,
|
|
908
|
-
plugins: [renderingUtilitiesExporter(allTemplates)],
|
|
909
|
-
platform: "node",
|
|
910
|
-
format: "cjs",
|
|
911
|
-
loader: { ".js": "jsx" },
|
|
912
|
-
outExtension: { ".js": ".cjs" },
|
|
913
|
-
jsx: "transform",
|
|
914
|
-
write: true,
|
|
915
|
-
outdir: pathToWhereEmailMarkupShouldBeDumped
|
|
916
|
-
});
|
|
917
|
-
} catch (exception) {
|
|
918
|
-
const buildFailure = exception;
|
|
919
|
-
if (spinner) {
|
|
920
|
-
spinner.stopAndPersist({
|
|
921
|
-
symbol: logSymbols3.error,
|
|
922
|
-
text: "Failed to build emails"
|
|
923
|
-
});
|
|
924
|
-
}
|
|
925
|
-
process.exit(1);
|
|
926
|
-
}
|
|
927
|
-
if (spinner) {
|
|
928
|
-
spinner.succeed();
|
|
929
|
-
}
|
|
930
|
-
const allBuiltTemplates = glob.sync(
|
|
931
|
-
normalize(`${pathToWhereEmailMarkupShouldBeDumped}/**/*.cjs`),
|
|
932
|
-
{
|
|
933
|
-
absolute: true
|
|
934
|
-
}
|
|
935
|
-
);
|
|
936
|
-
for await (const template of allBuiltTemplates) {
|
|
937
|
-
try {
|
|
938
|
-
if (spinner) {
|
|
939
|
-
spinner.text = `rendering ${template.split("/").pop()}`;
|
|
940
|
-
spinner.render();
|
|
941
|
-
}
|
|
942
|
-
delete __require.cache[template];
|
|
943
|
-
const emailModule = __require(template);
|
|
944
|
-
const rendered = await emailModule.render(
|
|
945
|
-
emailModule.reactEmailCreateReactElement(emailModule.default, {}),
|
|
946
|
-
options
|
|
947
|
-
);
|
|
948
|
-
const htmlPath = template.replace(
|
|
949
|
-
".cjs",
|
|
950
|
-
options.plainText ? ".txt" : ".html"
|
|
951
|
-
);
|
|
952
|
-
writeFileSync(htmlPath, rendered);
|
|
953
|
-
unlinkSync(template);
|
|
954
|
-
} catch (exception) {
|
|
955
|
-
if (spinner) {
|
|
956
|
-
spinner.stopAndPersist({
|
|
957
|
-
symbol: logSymbols3.error,
|
|
958
|
-
text: `failed when rendering ${template.split("/").pop()}`
|
|
959
|
-
});
|
|
960
|
-
}
|
|
961
|
-
console.error(exception);
|
|
962
|
-
process.exit(1);
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
if (spinner) {
|
|
966
|
-
spinner.succeed("Rendered all files");
|
|
967
|
-
spinner.text = "Copying static files";
|
|
968
|
-
spinner.render();
|
|
969
|
-
}
|
|
970
|
-
const staticDirectoryPath = path9.join(emailsDirectoryPath, "static");
|
|
971
|
-
if (fs7.existsSync(staticDirectoryPath)) {
|
|
972
|
-
const pathToDumpStaticFilesInto = path9.join(
|
|
973
|
-
pathToWhereEmailMarkupShouldBeDumped,
|
|
974
|
-
"static"
|
|
975
|
-
);
|
|
976
|
-
if (fs7.existsSync(pathToDumpStaticFilesInto))
|
|
977
|
-
await fs7.promises.rm(pathToDumpStaticFilesInto, { recursive: true });
|
|
978
|
-
try {
|
|
979
|
-
await fs7.promises.cp(staticDirectoryPath, pathToDumpStaticFilesInto, {
|
|
980
|
-
recursive: true
|
|
981
|
-
});
|
|
982
|
-
} catch (exception) {
|
|
983
|
-
console.error(exception);
|
|
984
|
-
if (spinner) {
|
|
985
|
-
spinner.stopAndPersist({
|
|
986
|
-
symbol: logSymbols3.error,
|
|
987
|
-
text: "Failed to copy static files"
|
|
988
|
-
});
|
|
989
|
-
}
|
|
990
|
-
console.error(
|
|
991
|
-
`Something went wrong while copying the file to ${pathToWhereEmailMarkupShouldBeDumped}/static, ${exception}`
|
|
992
|
-
);
|
|
993
|
-
process.exit(1);
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
if (spinner && !options.silent) {
|
|
997
|
-
spinner.succeed();
|
|
998
|
-
const fileTree = await tree(pathToWhereEmailMarkupShouldBeDumped, 4);
|
|
999
|
-
console.log(fileTree);
|
|
1000
|
-
spinner.stopAndPersist({
|
|
1001
|
-
symbol: logSymbols3.success,
|
|
1002
|
-
text: "Successfully exported emails"
|
|
1003
|
-
});
|
|
1004
|
-
}
|
|
1005
|
-
};
|
|
1006
|
-
|
|
1007
797
|
// src/cli/commands/build.ts
|
|
1008
|
-
import fs8 from "node:fs";
|
|
1009
|
-
import path10 from "node:path";
|
|
1010
|
-
import ora3 from "ora";
|
|
1011
|
-
import { spawn } from "node:child_process";
|
|
1012
|
-
import logSymbols4 from "log-symbols";
|
|
1013
798
|
var buildPreviewApp = (absoluteDirectory) => {
|
|
1014
799
|
return new Promise((resolve, reject) => {
|
|
1015
800
|
const nextBuild = spawn("npm", ["run", "build"], {
|
|
@@ -1066,8 +851,8 @@ module.exports = {
|
|
|
1066
851
|
webpackBuildWorker: true
|
|
1067
852
|
},
|
|
1068
853
|
}`;
|
|
1069
|
-
await
|
|
1070
|
-
|
|
854
|
+
await fs5.promises.writeFile(
|
|
855
|
+
path8.resolve(builtPreviewAppPath, "./next.config.js"),
|
|
1071
856
|
nextConfigContents,
|
|
1072
857
|
"utf8"
|
|
1073
858
|
);
|
|
@@ -1077,7 +862,7 @@ var getEmailSlugsFromEmailDirectory = (emailDirectory, emailsDirectoryAbsolutePa
|
|
|
1077
862
|
const slugs = [];
|
|
1078
863
|
emailDirectory.emailFilenames.forEach(
|
|
1079
864
|
(filename) => slugs.push(
|
|
1080
|
-
|
|
865
|
+
path8.join(directoryPathRelativeToEmailsDirectory, filename).split(path8.sep).filter((segment) => segment.length > 0)
|
|
1081
866
|
)
|
|
1082
867
|
);
|
|
1083
868
|
emailDirectory.subDirectories.forEach((directory) => {
|
|
@@ -1100,21 +885,21 @@ var forceSSGForEmailPreviews = async (emailsDirPath, builtPreviewAppPath) => {
|
|
|
1100
885
|
emailsDirPath
|
|
1101
886
|
).map((slug) => ({ slug }));
|
|
1102
887
|
const removeForceDynamic = async (filePath) => {
|
|
1103
|
-
const contents = await
|
|
1104
|
-
await
|
|
888
|
+
const contents = await fs5.promises.readFile(filePath, "utf8");
|
|
889
|
+
await fs5.promises.writeFile(
|
|
1105
890
|
filePath,
|
|
1106
891
|
contents.replace("export const dynamic = 'force-dynamic';", ""),
|
|
1107
892
|
"utf8"
|
|
1108
893
|
);
|
|
1109
894
|
};
|
|
1110
895
|
await removeForceDynamic(
|
|
1111
|
-
|
|
896
|
+
path8.resolve(builtPreviewAppPath, "./src/app/layout.tsx")
|
|
1112
897
|
);
|
|
1113
898
|
await removeForceDynamic(
|
|
1114
|
-
|
|
899
|
+
path8.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx")
|
|
1115
900
|
);
|
|
1116
|
-
await
|
|
1117
|
-
|
|
901
|
+
await fs5.promises.appendFile(
|
|
902
|
+
path8.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx"),
|
|
1118
903
|
`
|
|
1119
904
|
|
|
1120
905
|
export function generateStaticParams() {
|
|
@@ -1126,16 +911,16 @@ export function generateStaticParams() {
|
|
|
1126
911
|
);
|
|
1127
912
|
};
|
|
1128
913
|
var updatePackageJson = async (builtPreviewAppPath) => {
|
|
1129
|
-
const packageJsonPath =
|
|
914
|
+
const packageJsonPath = path8.resolve(builtPreviewAppPath, "./package.json");
|
|
1130
915
|
const packageJson = JSON.parse(
|
|
1131
|
-
await
|
|
916
|
+
await fs5.promises.readFile(packageJsonPath, "utf8")
|
|
1132
917
|
);
|
|
1133
918
|
packageJson.scripts.build = "next build";
|
|
1134
919
|
packageJson.scripts.start = "next start";
|
|
1135
920
|
packageJson.name = "preview-server";
|
|
1136
921
|
delete packageJson.devDependencies["@react-email/render"];
|
|
1137
922
|
delete packageJson.devDependencies["@react-email/components"];
|
|
1138
|
-
await
|
|
923
|
+
await fs5.promises.writeFile(
|
|
1139
924
|
packageJsonPath,
|
|
1140
925
|
JSON.stringify(packageJson),
|
|
1141
926
|
"utf8"
|
|
@@ -1166,41 +951,41 @@ var npmInstall = async (builtPreviewAppPath, packageManager) => {
|
|
|
1166
951
|
});
|
|
1167
952
|
});
|
|
1168
953
|
};
|
|
1169
|
-
var
|
|
954
|
+
var build = async ({
|
|
1170
955
|
dir: emailsDirRelativePath,
|
|
1171
956
|
packageManager
|
|
1172
957
|
}) => {
|
|
1173
958
|
try {
|
|
1174
|
-
const spinner =
|
|
959
|
+
const spinner = ora2({
|
|
1175
960
|
text: "Starting build process...",
|
|
1176
961
|
prefixText: " "
|
|
1177
962
|
}).start();
|
|
1178
963
|
registerSpinnerAutostopping(spinner);
|
|
1179
964
|
spinner.text = `Checking if ${emailsDirRelativePath} folder exists`;
|
|
1180
|
-
if (!
|
|
965
|
+
if (!fs5.existsSync(emailsDirRelativePath)) {
|
|
1181
966
|
process.exit(1);
|
|
1182
967
|
}
|
|
1183
|
-
const emailsDirPath =
|
|
1184
|
-
const staticPath =
|
|
1185
|
-
const builtPreviewAppPath =
|
|
1186
|
-
if (
|
|
968
|
+
const emailsDirPath = path8.join(process.cwd(), emailsDirRelativePath);
|
|
969
|
+
const staticPath = path8.join(emailsDirPath, "static");
|
|
970
|
+
const builtPreviewAppPath = path8.join(process.cwd(), ".react-email");
|
|
971
|
+
if (fs5.existsSync(builtPreviewAppPath)) {
|
|
1187
972
|
spinner.text = "Deleting pre-existing `.react-email` folder";
|
|
1188
|
-
await
|
|
973
|
+
await fs5.promises.rm(builtPreviewAppPath, { recursive: true });
|
|
1189
974
|
}
|
|
1190
975
|
spinner.text = "Copying preview app from CLI to `.react-email`";
|
|
1191
|
-
await
|
|
976
|
+
await fs5.promises.cp(cliPacakgeLocation, builtPreviewAppPath, {
|
|
1192
977
|
recursive: true,
|
|
1193
978
|
filter: (source) => {
|
|
1194
979
|
return !/(\/|\\)cli(\/|\\)?/.test(source) && !/(\/|\\)\.next(\/|\\)?/.test(source) && !/(\/|\\)\.turbo(\/|\\)?/.test(source) && !/(\/|\\)node_modules(\/|\\)?$/.test(source);
|
|
1195
980
|
}
|
|
1196
981
|
});
|
|
1197
|
-
if (
|
|
982
|
+
if (fs5.existsSync(staticPath)) {
|
|
1198
983
|
spinner.text = "Copying `static` folder into `.react-email/public/static`";
|
|
1199
|
-
const builtStaticDirectory =
|
|
984
|
+
const builtStaticDirectory = path8.resolve(
|
|
1200
985
|
builtPreviewAppPath,
|
|
1201
986
|
"./public/static"
|
|
1202
987
|
);
|
|
1203
|
-
await
|
|
988
|
+
await fs5.promises.cp(staticPath, builtStaticDirectory, {
|
|
1204
989
|
recursive: true
|
|
1205
990
|
});
|
|
1206
991
|
}
|
|
@@ -1217,7 +1002,7 @@ var build2 = async ({
|
|
|
1217
1002
|
await npmInstall(builtPreviewAppPath, packageManager);
|
|
1218
1003
|
spinner.stopAndPersist({
|
|
1219
1004
|
text: "Successfully prepared `.react-email` for `next build`",
|
|
1220
|
-
symbol:
|
|
1005
|
+
symbol: logSymbols3.success
|
|
1221
1006
|
});
|
|
1222
1007
|
await buildPreviewApp(builtPreviewAppPath);
|
|
1223
1008
|
} catch (error) {
|
|
@@ -1226,10 +1011,229 @@ var build2 = async ({
|
|
|
1226
1011
|
}
|
|
1227
1012
|
};
|
|
1228
1013
|
|
|
1014
|
+
// src/cli/commands/dev.ts
|
|
1015
|
+
import fs6 from "node:fs";
|
|
1016
|
+
var dev = async ({ dir: emailsDirRelativePath, port }) => {
|
|
1017
|
+
try {
|
|
1018
|
+
if (!fs6.existsSync(emailsDirRelativePath)) {
|
|
1019
|
+
console.error(`Missing ${emailsDirRelativePath} folder`);
|
|
1020
|
+
process.exit(1);
|
|
1021
|
+
}
|
|
1022
|
+
const devServer2 = await startDevServer(
|
|
1023
|
+
emailsDirRelativePath,
|
|
1024
|
+
emailsDirRelativePath,
|
|
1025
|
+
// defaults to ./emails/static for the static files that are served to the preview
|
|
1026
|
+
Number.parseInt(port)
|
|
1027
|
+
);
|
|
1028
|
+
await setupHotreloading(devServer2, emailsDirRelativePath);
|
|
1029
|
+
} catch (error) {
|
|
1030
|
+
console.log(error);
|
|
1031
|
+
process.exit(1);
|
|
1032
|
+
}
|
|
1033
|
+
};
|
|
1034
|
+
|
|
1035
|
+
// src/cli/commands/export.ts
|
|
1036
|
+
import fs8, { unlinkSync, writeFileSync } from "node:fs";
|
|
1037
|
+
import path10 from "node:path";
|
|
1038
|
+
import { build as build2 } from "esbuild";
|
|
1039
|
+
import { glob } from "glob";
|
|
1040
|
+
import logSymbols4 from "log-symbols";
|
|
1041
|
+
import normalize from "normalize-path";
|
|
1042
|
+
import ora3 from "ora";
|
|
1043
|
+
|
|
1044
|
+
// src/utils/esbuild/renderring-utilities-exporter.ts
|
|
1045
|
+
import { promises as fs7 } from "node:fs";
|
|
1046
|
+
import path9 from "node:path";
|
|
1047
|
+
|
|
1048
|
+
// src/utils/esbuild/escape-string-for-regex.ts
|
|
1049
|
+
function escapeStringForRegex(string) {
|
|
1050
|
+
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
// src/utils/esbuild/renderring-utilities-exporter.ts
|
|
1054
|
+
var renderingUtilitiesExporter = (emailTemplates) => ({
|
|
1055
|
+
name: "rendering-utilities-exporter",
|
|
1056
|
+
setup: (b) => {
|
|
1057
|
+
b.onLoad(
|
|
1058
|
+
{
|
|
1059
|
+
filter: new RegExp(
|
|
1060
|
+
emailTemplates.map((emailPath) => escapeStringForRegex(emailPath)).join("|")
|
|
1061
|
+
)
|
|
1062
|
+
},
|
|
1063
|
+
async ({ path: pathToFile }) => {
|
|
1064
|
+
return {
|
|
1065
|
+
contents: `${await fs7.readFile(pathToFile, "utf8")};
|
|
1066
|
+
export { render } from 'react-email-module-that-will-export-render'
|
|
1067
|
+
export { createElement as reactEmailCreateReactElement } from 'react';
|
|
1068
|
+
`,
|
|
1069
|
+
loader: path9.extname(pathToFile).slice(1)
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
1072
|
+
);
|
|
1073
|
+
b.onResolve(
|
|
1074
|
+
{ filter: /^react-email-module-that-will-export-render$/ },
|
|
1075
|
+
async (args) => {
|
|
1076
|
+
const options = {
|
|
1077
|
+
kind: "import-statement",
|
|
1078
|
+
importer: args.importer,
|
|
1079
|
+
resolveDir: args.resolveDir,
|
|
1080
|
+
namespace: args.namespace
|
|
1081
|
+
};
|
|
1082
|
+
let result = await b.resolve("@react-email/render", options);
|
|
1083
|
+
if (result.errors.length === 0) {
|
|
1084
|
+
return result;
|
|
1085
|
+
}
|
|
1086
|
+
result = await b.resolve("@react-email/components", options);
|
|
1087
|
+
if (result.errors.length > 0 && result.errors[0]) {
|
|
1088
|
+
result.errors[0].text = "Failed trying to import `render` from either `@react-email/render` or `@react-email/components` to be able to render your email template.\n Maybe you don't have either of them installed?";
|
|
1089
|
+
}
|
|
1090
|
+
return result;
|
|
1091
|
+
}
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1094
|
+
});
|
|
1095
|
+
|
|
1096
|
+
// src/cli/commands/export.ts
|
|
1097
|
+
var getEmailTemplatesFromDirectory = (emailDirectory) => {
|
|
1098
|
+
const templatePaths = [];
|
|
1099
|
+
emailDirectory.emailFilenames.forEach(
|
|
1100
|
+
(filename) => templatePaths.push(path10.join(emailDirectory.absolutePath, filename))
|
|
1101
|
+
);
|
|
1102
|
+
emailDirectory.subDirectories.forEach((directory) => {
|
|
1103
|
+
templatePaths.push(...getEmailTemplatesFromDirectory(directory));
|
|
1104
|
+
});
|
|
1105
|
+
return templatePaths;
|
|
1106
|
+
};
|
|
1107
|
+
var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirectoryPath, options) => {
|
|
1108
|
+
if (fs8.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
|
|
1109
|
+
fs8.rmSync(pathToWhereEmailMarkupShouldBeDumped, { recursive: true });
|
|
1110
|
+
}
|
|
1111
|
+
let spinner;
|
|
1112
|
+
if (!options.silent) {
|
|
1113
|
+
spinner = ora3("Preparing files...\n").start();
|
|
1114
|
+
registerSpinnerAutostopping(spinner);
|
|
1115
|
+
}
|
|
1116
|
+
const emailsDirectoryMetadata = await getEmailsDirectoryMetadata(
|
|
1117
|
+
path10.resolve(process.cwd(), emailsDirectoryPath),
|
|
1118
|
+
true
|
|
1119
|
+
);
|
|
1120
|
+
if (typeof emailsDirectoryMetadata === "undefined") {
|
|
1121
|
+
if (spinner) {
|
|
1122
|
+
spinner.stopAndPersist({
|
|
1123
|
+
symbol: logSymbols4.error,
|
|
1124
|
+
text: `Could not find the directory at ${emailsDirectoryPath}`
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
return;
|
|
1128
|
+
}
|
|
1129
|
+
const allTemplates = getEmailTemplatesFromDirectory(emailsDirectoryMetadata);
|
|
1130
|
+
try {
|
|
1131
|
+
await build2({
|
|
1132
|
+
bundle: true,
|
|
1133
|
+
entryPoints: allTemplates,
|
|
1134
|
+
plugins: [renderingUtilitiesExporter(allTemplates)],
|
|
1135
|
+
platform: "node",
|
|
1136
|
+
format: "cjs",
|
|
1137
|
+
loader: { ".js": "jsx" },
|
|
1138
|
+
outExtension: { ".js": ".cjs" },
|
|
1139
|
+
jsx: "transform",
|
|
1140
|
+
write: true,
|
|
1141
|
+
outdir: pathToWhereEmailMarkupShouldBeDumped
|
|
1142
|
+
});
|
|
1143
|
+
} catch (exception) {
|
|
1144
|
+
const buildFailure = exception;
|
|
1145
|
+
if (spinner) {
|
|
1146
|
+
spinner.stopAndPersist({
|
|
1147
|
+
symbol: logSymbols4.error,
|
|
1148
|
+
text: "Failed to build emails"
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
process.exit(1);
|
|
1152
|
+
}
|
|
1153
|
+
if (spinner) {
|
|
1154
|
+
spinner.succeed();
|
|
1155
|
+
}
|
|
1156
|
+
const allBuiltTemplates = glob.sync(
|
|
1157
|
+
normalize(`${pathToWhereEmailMarkupShouldBeDumped}/**/*.cjs`),
|
|
1158
|
+
{
|
|
1159
|
+
absolute: true
|
|
1160
|
+
}
|
|
1161
|
+
);
|
|
1162
|
+
for await (const template of allBuiltTemplates) {
|
|
1163
|
+
try {
|
|
1164
|
+
if (spinner) {
|
|
1165
|
+
spinner.text = `rendering ${template.split("/").pop()}`;
|
|
1166
|
+
spinner.render();
|
|
1167
|
+
}
|
|
1168
|
+
delete __require.cache[template];
|
|
1169
|
+
const emailModule = __require(template);
|
|
1170
|
+
const rendered = await emailModule.render(
|
|
1171
|
+
emailModule.reactEmailCreateReactElement(emailModule.default, {}),
|
|
1172
|
+
options
|
|
1173
|
+
);
|
|
1174
|
+
const htmlPath = template.replace(
|
|
1175
|
+
".cjs",
|
|
1176
|
+
options.plainText ? ".txt" : ".html"
|
|
1177
|
+
);
|
|
1178
|
+
writeFileSync(htmlPath, rendered);
|
|
1179
|
+
unlinkSync(template);
|
|
1180
|
+
} catch (exception) {
|
|
1181
|
+
if (spinner) {
|
|
1182
|
+
spinner.stopAndPersist({
|
|
1183
|
+
symbol: logSymbols4.error,
|
|
1184
|
+
text: `failed when rendering ${template.split("/").pop()}`
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
console.error(exception);
|
|
1188
|
+
process.exit(1);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
if (spinner) {
|
|
1192
|
+
spinner.succeed("Rendered all files");
|
|
1193
|
+
spinner.text = "Copying static files";
|
|
1194
|
+
spinner.render();
|
|
1195
|
+
}
|
|
1196
|
+
const staticDirectoryPath = path10.join(emailsDirectoryPath, "static");
|
|
1197
|
+
if (fs8.existsSync(staticDirectoryPath)) {
|
|
1198
|
+
const pathToDumpStaticFilesInto = path10.join(
|
|
1199
|
+
pathToWhereEmailMarkupShouldBeDumped,
|
|
1200
|
+
"static"
|
|
1201
|
+
);
|
|
1202
|
+
if (fs8.existsSync(pathToDumpStaticFilesInto))
|
|
1203
|
+
await fs8.promises.rm(pathToDumpStaticFilesInto, { recursive: true });
|
|
1204
|
+
try {
|
|
1205
|
+
await fs8.promises.cp(staticDirectoryPath, pathToDumpStaticFilesInto, {
|
|
1206
|
+
recursive: true
|
|
1207
|
+
});
|
|
1208
|
+
} catch (exception) {
|
|
1209
|
+
console.error(exception);
|
|
1210
|
+
if (spinner) {
|
|
1211
|
+
spinner.stopAndPersist({
|
|
1212
|
+
symbol: logSymbols4.error,
|
|
1213
|
+
text: "Failed to copy static files"
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
console.error(
|
|
1217
|
+
`Something went wrong while copying the file to ${pathToWhereEmailMarkupShouldBeDumped}/static, ${exception}`
|
|
1218
|
+
);
|
|
1219
|
+
process.exit(1);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
if (spinner && !options.silent) {
|
|
1223
|
+
spinner.succeed();
|
|
1224
|
+
const fileTree = await tree(pathToWhereEmailMarkupShouldBeDumped, 4);
|
|
1225
|
+
console.log(fileTree);
|
|
1226
|
+
spinner.stopAndPersist({
|
|
1227
|
+
symbol: logSymbols4.success,
|
|
1228
|
+
text: "Successfully exported emails"
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
};
|
|
1232
|
+
|
|
1229
1233
|
// src/cli/commands/start.ts
|
|
1234
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
1230
1235
|
import fs9 from "node:fs";
|
|
1231
1236
|
import path11 from "node:path";
|
|
1232
|
-
import { spawn as spawn2 } from "node:child_process";
|
|
1233
1237
|
var start = async () => {
|
|
1234
1238
|
try {
|
|
1235
1239
|
const usersProjectLocation = process.cwd();
|
|
@@ -1267,7 +1271,7 @@ program.command("build").description("Copies the preview app for onto .react-ema
|
|
|
1267
1271
|
"-p --packageManager <name>",
|
|
1268
1272
|
"Package name to use on installation on `.react-email`",
|
|
1269
1273
|
"npm"
|
|
1270
|
-
).action(
|
|
1274
|
+
).action(build);
|
|
1271
1275
|
program.command("start").description('Runs the built preview app that is inside of ".react-email"').action(start);
|
|
1272
1276
|
program.command("export").description("Build the templates to the `out` directory").option("--outDir <path>", "Output directory", "out").option("-p, --pretty", "Pretty print the output", false).option("-t, --plainText", "Set output format as plain text", false).option("-d, --dir <path>", "Directory with your email templates", "./emails").option(
|
|
1273
1277
|
"-s, --silent",
|