react-email 4.1.0-canary.4 → 4.1.0-canary.5
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 +40 -0
- package/dist/cli/index.mjs +190 -166
- package/dist/preview/.next/BUILD_ID +1 -1
- package/dist/preview/.next/app-build-manifest.json +32 -32
- package/dist/preview/.next/build-manifest.json +14 -14
- package/dist/preview/.next/diagnostics/framework.json +1 -1
- 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 +3 -3
- package/dist/preview/.next/required-server-files.json +8 -7
- package/dist/preview/.next/server/app/_not-found/page.js +1 -1
- package/dist/preview/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/dist/preview/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/preview/.next/server/app/favicon.ico/route.js +1 -1
- package/dist/preview/.next/server/app/favicon.ico/route.js.nft.json +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 +188 -128
- 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/134.js +6 -0
- package/dist/preview/.next/server/chunks/235.js +15 -0
- package/dist/preview/.next/server/chunks/300.js +1 -0
- package/dist/preview/.next/server/chunks/343.js +20 -0
- package/dist/preview/.next/server/chunks/428.js +14 -0
- package/dist/preview/.next/server/chunks/963.js +1 -0
- package/dist/preview/.next/server/middleware-build-manifest.js +1 -1
- package/dist/preview/.next/server/next-font-manifest.js +1 -1
- package/dist/preview/.next/server/next-font-manifest.json +1 -1
- package/dist/preview/.next/server/pages/500.html +1 -1
- package/dist/preview/.next/server/pages/_app.js +1 -1
- package/dist/preview/.next/server/pages/_app.js.nft.json +1 -1
- package/dist/preview/.next/server/pages/_document.js +1 -1
- package/dist/preview/.next/server/pages/_document.js.nft.json +1 -1
- package/dist/preview/.next/server/pages/_error.js +1 -1
- package/dist/preview/.next/server/pages/_error.js.nft.json +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/static/chunks/107-3043079e7cb8bcae.js +1 -0
- package/dist/preview/.next/static/chunks/293-297b1eb2241f9a70.js +1 -0
- package/dist/preview/.next/static/chunks/3bd82e28-cda2c00a924937c5.js +1 -0
- package/dist/preview/.next/static/chunks/45-1021fac82f766268.js +1 -0
- package/dist/preview/.next/static/chunks/484-e1100258e8f13026.js +1 -0
- package/dist/preview/.next/static/chunks/589-817d8691661d370e.js +1 -0
- package/dist/preview/.next/static/chunks/902-c34acb56733e0ce1.js +1 -0
- package/dist/preview/.next/static/chunks/app/_not-found/page-4cbc7dce3ad33336.js +1 -0
- package/dist/preview/.next/static/chunks/app/layout-ae0864a2f95fa465.js +1 -0
- package/dist/preview/.next/static/chunks/app/page-65fd67d48528e2ba.js +1 -0
- package/dist/preview/.next/static/chunks/app/preview/[...slug]/page-8aac52e1ccbb9d9b.js +1 -0
- package/dist/preview/.next/static/chunks/f33a14d2-ec7c5f0b91818561.js +6 -0
- package/dist/preview/.next/static/chunks/framework-b887e9fc751a9906.js +1 -0
- package/dist/preview/.next/static/chunks/main-9a03e7ba8acb1900.js +1 -0
- package/dist/preview/.next/static/chunks/main-app-dbd8e1ec12eabb66.js +1 -0
- package/dist/preview/.next/static/chunks/pages/_app-542a93a5a214e1c0.js +1 -0
- package/dist/preview/.next/static/chunks/pages/_error-d5fe1b1612642f76.js +1 -0
- package/dist/preview/.next/static/chunks/webpack-31c45daa2bd82a7b.js +1 -0
- package/dist/preview/.next/static/css/6f42d128f111d7fa.css +3 -0
- package/dist/preview/.next/static/{JZPm9ao1byHQqJdt3oG1X → zs2-dZFPht_M4xAoOGgCM}/_buildManifest.js +1 -1
- package/dist/preview/.next/trace +28 -27
- package/package.json +41 -42
- package/src/actions/email-validation/check-compatibility.ts +1 -1
- package/src/actions/email-validation/check-images.spec.tsx +1 -1
- package/src/actions/email-validation/check-links.spec.tsx +1 -1
- package/src/actions/email-validation/quick-fetch.ts +1 -1
- package/src/actions/render-email-by-path.tsx +2 -2
- package/src/app/preview/[...slug]/preview.tsx +1 -1
- package/src/components/sidebar/file-tree-directory-children.tsx +7 -2
- package/src/components/toolbar.tsx +1 -0
- package/src/contexts/emails.tsx +1 -3
- package/src/contexts/fragment-identifier.tsx +3 -1
- package/src/contexts/preview.tsx +1 -3
- package/src/hooks/use-email-rendering-result.ts +1 -1
- package/src/hooks/use-hot-reload.ts +1 -1
- package/src/utils/__snapshots__/get-email-component.spec.ts.snap +1 -1
- package/src/utils/caniemail/ast/get-object-variables.ts +1 -1
- package/src/utils/caniemail/tailwind/generate-tailwind-rules.ts +1 -1
- package/src/utils/caniemail/tailwind/get-tailwind-config.ts +1 -1
- package/src/utils/caniemail/tailwind/get-tailwind-metadata.ts +1 -1
- package/src/utils/get-email-component.ts +1 -1
- package/src/utils/get-emails-directory-metadata.ts +24 -13
- package/src/utils/index.ts +2 -2
- package/src/utils/run-bundled-code.ts +1 -1
- package/tailwind.config.ts +2 -1
- package/tsconfig.json +1 -1
- package/dist/cli/index.d.mts +0 -1
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +0 -1325
- package/dist/preview/.next/server/chunks/362.js +0 -1
- package/dist/preview/.next/server/chunks/395.js +0 -1
- package/dist/preview/.next/server/chunks/574.js +0 -6
- package/dist/preview/.next/server/chunks/735.js +0 -13
- package/dist/preview/.next/server/chunks/840.js +0 -14
- package/dist/preview/.next/server/chunks/886.js +0 -8
- package/dist/preview/.next/static/chunks/246-e7336e2929971f63.js +0 -1
- package/dist/preview/.next/static/chunks/270-688096d43c717256.js +0 -1
- package/dist/preview/.next/static/chunks/539-6e9405ecdc007bb7.js +0 -1
- package/dist/preview/.next/static/chunks/587-11b31fa1b8f77a29.js +0 -1
- package/dist/preview/.next/static/chunks/782947c8-c6cfd05e68542601.js +0 -1
- package/dist/preview/.next/static/chunks/803-db74f262c4755323.js +0 -1
- package/dist/preview/.next/static/chunks/853-a01d49f63a859f3d.js +0 -1
- package/dist/preview/.next/static/chunks/afa401a5-55858bf5265319eb.js +0 -6
- package/dist/preview/.next/static/chunks/app/_not-found/page-85e83b2d4bd569a2.js +0 -1
- package/dist/preview/.next/static/chunks/app/layout-58e02c2c8b197b04.js +0 -1
- package/dist/preview/.next/static/chunks/app/page-dd13899a1b8e35f9.js +0 -1
- package/dist/preview/.next/static/chunks/app/preview/[...slug]/page-94fd27d6538e2c16.js +0 -1
- package/dist/preview/.next/static/chunks/framework-b5f555f62da46ed9.js +0 -1
- package/dist/preview/.next/static/chunks/main-a839e2fbd78a08fa.js +0 -1
- package/dist/preview/.next/static/chunks/main-app-2cfbaf0185a1cd0e.js +0 -1
- package/dist/preview/.next/static/chunks/pages/_app-ee26b5d329c4bb79.js +0 -1
- package/dist/preview/.next/static/chunks/pages/_error-90cb3f6367e28bcd.js +0 -1
- package/dist/preview/.next/static/chunks/webpack-6755bde10ea8daa8.js +0 -1
- package/dist/preview/.next/static/css/67e57230289273a9.css +0 -3
- /package/dist/preview/.next/static/{JZPm9ao1byHQqJdt3oG1X → zs2-dZFPht_M4xAoOGgCM}/_ssgManifest.js +0 -0
package/dist/cli/index.mjs
CHANGED
|
@@ -1,11 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
-
}) : x)(function(x) {
|
|
5
|
-
if (typeof require !== "undefined")
|
|
6
|
-
return require.apply(this, arguments);
|
|
7
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
-
});
|
|
9
2
|
|
|
10
3
|
// src/cli/index.ts
|
|
11
4
|
import { program } from "commander";
|
|
@@ -13,13 +6,14 @@ import { program } from "commander";
|
|
|
13
6
|
// package.json
|
|
14
7
|
var package_default = {
|
|
15
8
|
name: "react-email",
|
|
16
|
-
version: "4.1.0-canary.
|
|
9
|
+
version: "4.1.0-canary.5",
|
|
17
10
|
description: "A live preview of your emails right in your browser.",
|
|
18
11
|
bin: {
|
|
19
|
-
email: "./dist/cli/index.
|
|
12
|
+
email: "./dist/cli/index.mjs"
|
|
20
13
|
},
|
|
21
14
|
scripts: {
|
|
22
|
-
build: "tsup-node && node ./scripts/build-preview-server.mjs
|
|
15
|
+
build: "tsup-node && node ./scripts/build-preview-server.mjs",
|
|
16
|
+
postbuild: "pnpm install --frozen-lockfile",
|
|
23
17
|
"caniemail:fetch": "node ./scripts/fill-caniemail-data.mjs",
|
|
24
18
|
clean: "rm -rf dist",
|
|
25
19
|
dev: "tsup-node --watch",
|
|
@@ -33,75 +27,76 @@ var package_default = {
|
|
|
33
27
|
url: "https://github.com/resend/react-email.git",
|
|
34
28
|
directory: "packages/react-email"
|
|
35
29
|
},
|
|
36
|
-
keywords: [
|
|
30
|
+
keywords: [
|
|
31
|
+
"react",
|
|
32
|
+
"email"
|
|
33
|
+
],
|
|
37
34
|
engines: {
|
|
38
35
|
node: ">=18.0.0"
|
|
39
36
|
},
|
|
40
37
|
dependencies: {
|
|
41
|
-
"@babel/parser": "^7.
|
|
42
|
-
"@babel/traverse": "^7.
|
|
43
|
-
chalk: "^
|
|
38
|
+
"@babel/parser": "^7.27.0",
|
|
39
|
+
"@babel/traverse": "^7.27.0",
|
|
40
|
+
chalk: "^5.0.0",
|
|
44
41
|
chokidar: "^4.0.3",
|
|
45
|
-
commander: "^
|
|
42
|
+
commander: "^13.0.0",
|
|
46
43
|
debounce: "^2.0.0",
|
|
47
44
|
esbuild: "^0.25.0",
|
|
48
|
-
glob: "^
|
|
49
|
-
"log-symbols": "^
|
|
50
|
-
"mime-types": "^
|
|
51
|
-
next: "^15.
|
|
45
|
+
glob: "^11.0.0",
|
|
46
|
+
"log-symbols": "^7.0.0",
|
|
47
|
+
"mime-types": "^3.0.0",
|
|
48
|
+
next: "^15.3.1",
|
|
52
49
|
"normalize-path": "^3.0.0",
|
|
53
|
-
ora: "^
|
|
50
|
+
ora: "^8.0.0",
|
|
54
51
|
"socket.io": "^4.8.1"
|
|
55
52
|
},
|
|
56
53
|
devDependencies: {
|
|
57
54
|
"@babel/core": "7.26.10",
|
|
58
|
-
"@lottiefiles/dotlottie-react": "0.
|
|
59
|
-
"@radix-ui/colors": "
|
|
60
|
-
"@radix-ui/react-collapsible": "1.1.
|
|
61
|
-
"@radix-ui/react-dropdown-menu": "2.1.
|
|
62
|
-
"@radix-ui/react-popover": "1.1.
|
|
63
|
-
"@radix-ui/react-slot": "1.
|
|
64
|
-
"@radix-ui/react-tabs": "1.1.
|
|
65
|
-
"@radix-ui/react-toggle-group": "1.1.
|
|
66
|
-
"@radix-ui/react-tooltip": "1.
|
|
55
|
+
"@lottiefiles/dotlottie-react": "0.13.3",
|
|
56
|
+
"@radix-ui/colors": "3.0.0",
|
|
57
|
+
"@radix-ui/react-collapsible": "1.1.7",
|
|
58
|
+
"@radix-ui/react-dropdown-menu": "2.1.10",
|
|
59
|
+
"@radix-ui/react-popover": "1.1.10",
|
|
60
|
+
"@radix-ui/react-slot": "1.2.0",
|
|
61
|
+
"@radix-ui/react-tabs": "1.1.7",
|
|
62
|
+
"@radix-ui/react-toggle-group": "1.1.6",
|
|
63
|
+
"@radix-ui/react-tooltip": "1.2.3",
|
|
67
64
|
"@react-email/components": "workspace:*",
|
|
68
|
-
"@swc/core": "1.
|
|
65
|
+
"@swc/core": "1.11.21",
|
|
69
66
|
"@types/babel__core": "7.20.5",
|
|
70
|
-
"@types/babel__traverse": "
|
|
67
|
+
"@types/babel__traverse": "7.20.7",
|
|
71
68
|
"@types/fs-extra": "11.0.1",
|
|
72
69
|
"@types/mime-types": "2.1.4",
|
|
73
|
-
"@types/node": "22.
|
|
70
|
+
"@types/node": "22.14.1",
|
|
74
71
|
"@types/normalize-path": "3.0.2",
|
|
75
72
|
"@types/react": "19.0.10",
|
|
76
73
|
"@types/react-dom": "19.0.4",
|
|
77
74
|
"@types/webpack": "5.28.5",
|
|
78
|
-
|
|
79
|
-
autoprefixer: "10.4.20",
|
|
75
|
+
autoprefixer: "10.4.21",
|
|
80
76
|
clsx: "2.1.1",
|
|
81
|
-
"framer-motion": "12.
|
|
77
|
+
"framer-motion": "12.7.5",
|
|
82
78
|
jiti: "2.4.2",
|
|
83
79
|
json5: "2.2.3",
|
|
84
80
|
"module-punycode": "npm:punycode@2.3.1",
|
|
85
|
-
"node-html-parser": "
|
|
86
|
-
postcss: "8.
|
|
87
|
-
"prettier-plugin-tailwindcss": "0.6.6",
|
|
81
|
+
"node-html-parser": "7.0.1",
|
|
82
|
+
postcss: "8.5.3",
|
|
88
83
|
"pretty-bytes": "6.1.1",
|
|
89
|
-
"prism-react-renderer": "2.1
|
|
84
|
+
"prism-react-renderer": "2.4.1",
|
|
90
85
|
react: "19.0.0",
|
|
91
86
|
"react-dom": "19.0.0",
|
|
92
|
-
sharp: "0.
|
|
93
|
-
"socket.io-client": "4.8.
|
|
94
|
-
sonner: "
|
|
95
|
-
"source-map-js": "1.
|
|
87
|
+
sharp: "0.34.1",
|
|
88
|
+
"socket.io-client": "4.8.1",
|
|
89
|
+
sonner: "2.0.3",
|
|
90
|
+
"source-map-js": "1.2.1",
|
|
96
91
|
spamc: "0.0.5",
|
|
97
|
-
"stacktrace-parser": "0.1.
|
|
98
|
-
"tailwind-merge": "
|
|
92
|
+
"stacktrace-parser": "0.1.11",
|
|
93
|
+
"tailwind-merge": "3.2.0",
|
|
99
94
|
tailwindcss: "3.4.0",
|
|
100
|
-
tsup: "
|
|
101
|
-
tsx: "4.
|
|
102
|
-
typescript: "5.8.
|
|
95
|
+
tsup: "8.4.0",
|
|
96
|
+
tsx: "4.19.3",
|
|
97
|
+
typescript: "5.8.3",
|
|
103
98
|
"use-debounce": "10.0.4",
|
|
104
|
-
zod: "3.24.
|
|
99
|
+
zod: "3.24.3"
|
|
105
100
|
}
|
|
106
101
|
};
|
|
107
102
|
|
|
@@ -115,17 +110,26 @@ import ora2 from "ora";
|
|
|
115
110
|
// src/utils/get-emails-directory-metadata.ts
|
|
116
111
|
import fs from "node:fs";
|
|
117
112
|
import path from "node:path";
|
|
118
|
-
var isFileAnEmail = (fullPath) => {
|
|
119
|
-
|
|
120
|
-
|
|
113
|
+
var isFileAnEmail = async (fullPath) => {
|
|
114
|
+
let fileHandle;
|
|
115
|
+
try {
|
|
116
|
+
fileHandle = await fs.promises.open(fullPath, "r");
|
|
117
|
+
} catch (exception) {
|
|
118
|
+
console.warn(exception);
|
|
121
119
|
return false;
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
}
|
|
121
|
+
const stat = await fileHandle.stat();
|
|
122
|
+
if (stat.isDirectory()) {
|
|
123
|
+
await fileHandle.close();
|
|
124
124
|
return false;
|
|
125
|
-
|
|
125
|
+
}
|
|
126
|
+
const { ext } = path.parse(fullPath);
|
|
127
|
+
if (![".js", ".tsx", ".jsx"].includes(ext)) {
|
|
128
|
+
await fileHandle.close();
|
|
126
129
|
return false;
|
|
127
130
|
}
|
|
128
|
-
const fileContents =
|
|
131
|
+
const fileContents = await fileHandle.readFile("utf8");
|
|
132
|
+
await fileHandle.close();
|
|
129
133
|
const hasES6DefaultExport = /\bexport\s+default\b/gm.test(fileContents);
|
|
130
134
|
const hasCommonJSExport = /\bmodule\.exports\s*=/gm.test(fileContents);
|
|
131
135
|
const hasNamedExport = /\bexport\s+\{[^}]*\bdefault\b[^}]*\}/gm.test(
|
|
@@ -148,14 +152,16 @@ var mergeDirectoriesWithSubDirectories = (emailsDirectoryMetadata) => {
|
|
|
148
152
|
return currentResultingMergedDirectory;
|
|
149
153
|
};
|
|
150
154
|
var getEmailsDirectoryMetadata = async (absolutePathToEmailsDirectory, keepFileExtensions = false, isSubDirectory = false, baseDirectoryPath = absolutePathToEmailsDirectory) => {
|
|
151
|
-
if (!fs.existsSync(absolutePathToEmailsDirectory))
|
|
152
|
-
return;
|
|
155
|
+
if (!fs.existsSync(absolutePathToEmailsDirectory)) return;
|
|
153
156
|
const dirents = await fs.promises.readdir(absolutePathToEmailsDirectory, {
|
|
154
157
|
withFileTypes: true
|
|
155
158
|
});
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
+
const isEmailPredicates = await Promise.all(
|
|
160
|
+
dirents.map(
|
|
161
|
+
(dirent) => isFileAnEmail(path.join(absolutePathToEmailsDirectory, dirent.name))
|
|
162
|
+
)
|
|
163
|
+
);
|
|
164
|
+
const emailFilenames = dirents.filter((_, i) => isEmailPredicates[i]).map(
|
|
159
165
|
(dirent) => keepFileExtensions ? dirent.name : dirent.name.replace(path.extname(dirent.name), "")
|
|
160
166
|
);
|
|
161
167
|
const subDirectories = await Promise.all(
|
|
@@ -212,76 +218,19 @@ var registerSpinnerAutostopping = (spinner) => {
|
|
|
212
218
|
spinners.add(spinner);
|
|
213
219
|
};
|
|
214
220
|
|
|
215
|
-
// src/cli/utils/tree.ts
|
|
216
|
-
import { promises as fs2 } from "node:fs";
|
|
217
|
-
import os from "node:os";
|
|
218
|
-
import path2 from "node:path";
|
|
219
|
-
var SYMBOLS = {
|
|
220
|
-
BRANCH: "\u251C\u2500\u2500 ",
|
|
221
|
-
EMPTY: "",
|
|
222
|
-
INDENT: " ",
|
|
223
|
-
LAST_BRANCH: "\u2514\u2500\u2500 ",
|
|
224
|
-
VERTICAL: "\u2502 "
|
|
225
|
-
};
|
|
226
|
-
var getTreeLines = async (dirPath, depth, currentDepth = 0) => {
|
|
227
|
-
const base = process.cwd();
|
|
228
|
-
const dirFullpath = path2.resolve(base, dirPath);
|
|
229
|
-
const dirname = path2.basename(dirFullpath);
|
|
230
|
-
let lines = [dirname];
|
|
231
|
-
const dirStat = await fs2.stat(dirFullpath);
|
|
232
|
-
if (dirStat.isDirectory() && currentDepth < depth) {
|
|
233
|
-
const childDirents = await fs2.readdir(dirFullpath, { withFileTypes: true });
|
|
234
|
-
childDirents.sort((a, b) => {
|
|
235
|
-
if (a.isDirectory() && b.isFile()) {
|
|
236
|
-
return -1;
|
|
237
|
-
}
|
|
238
|
-
if (a.isFile() && b.isDirectory()) {
|
|
239
|
-
return 1;
|
|
240
|
-
}
|
|
241
|
-
return b.name > a.name ? -1 : 1;
|
|
242
|
-
});
|
|
243
|
-
for (let i = 0; i < childDirents.length; i++) {
|
|
244
|
-
const dirent = childDirents[i];
|
|
245
|
-
const isLast = i === childDirents.length - 1;
|
|
246
|
-
const branchingSymbol = isLast ? SYMBOLS.LAST_BRANCH : SYMBOLS.BRANCH;
|
|
247
|
-
const verticalSymbol = isLast ? SYMBOLS.INDENT : SYMBOLS.VERTICAL;
|
|
248
|
-
if (dirent.isFile()) {
|
|
249
|
-
lines.push(`${branchingSymbol}${dirent.name}`);
|
|
250
|
-
} else {
|
|
251
|
-
const pathToDirectory = path2.join(dirFullpath, dirent.name);
|
|
252
|
-
const treeLinesForSubDirectory = await getTreeLines(
|
|
253
|
-
pathToDirectory,
|
|
254
|
-
depth,
|
|
255
|
-
currentDepth + 1
|
|
256
|
-
);
|
|
257
|
-
lines = lines.concat(
|
|
258
|
-
treeLinesForSubDirectory.map(
|
|
259
|
-
(line, index) => index === 0 ? `${branchingSymbol}${line}` : `${verticalSymbol}${line}`
|
|
260
|
-
)
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
return lines;
|
|
266
|
-
};
|
|
267
|
-
var tree = async (dirPath, depth) => {
|
|
268
|
-
const lines = await getTreeLines(dirPath, depth);
|
|
269
|
-
return lines.join(os.EOL);
|
|
270
|
-
};
|
|
271
|
-
|
|
272
221
|
// src/cli/utils/preview/hot-reloading/setup-hot-reloading.ts
|
|
273
|
-
import
|
|
222
|
+
import path6 from "node:path";
|
|
274
223
|
import { watch } from "chokidar";
|
|
275
224
|
import debounce from "debounce";
|
|
276
225
|
import { Server as SocketServer } from "socket.io";
|
|
277
226
|
|
|
278
227
|
// src/cli/utils/preview/hot-reloading/create-dependency-graph.ts
|
|
279
|
-
import {
|
|
280
|
-
import
|
|
228
|
+
import { existsSync as existsSync2, promises as fs3, statSync } from "node:fs";
|
|
229
|
+
import path5 from "node:path";
|
|
281
230
|
|
|
282
231
|
// src/cli/utils/preview/start-dev-server.ts
|
|
283
232
|
import http from "node:http";
|
|
284
|
-
import
|
|
233
|
+
import path4 from "node:path";
|
|
285
234
|
import url from "node:url";
|
|
286
235
|
import chalk from "chalk";
|
|
287
236
|
import logSymbols2 from "log-symbols";
|
|
@@ -289,28 +238,33 @@ import next from "next";
|
|
|
289
238
|
import ora from "ora";
|
|
290
239
|
|
|
291
240
|
// src/cli/utils/preview/get-env-variables-for-preview-app.ts
|
|
292
|
-
import
|
|
241
|
+
import path2 from "node:path";
|
|
293
242
|
var getEnvVariablesForPreviewApp = (relativePathToEmailsDirectory, cwd) => {
|
|
294
243
|
return {
|
|
295
244
|
EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
|
|
296
|
-
EMAILS_DIR_ABSOLUTE_PATH:
|
|
245
|
+
EMAILS_DIR_ABSOLUTE_PATH: path2.resolve(cwd, relativePathToEmailsDirectory),
|
|
297
246
|
USER_PROJECT_LOCATION: cwd,
|
|
298
247
|
NEXT_PUBLIC_IS_PREVIEW_DEVELOPMENT: isDev ? "true" : "false"
|
|
299
248
|
};
|
|
300
249
|
};
|
|
301
250
|
|
|
302
251
|
// src/cli/utils/preview/serve-static-file.ts
|
|
303
|
-
import { promises as
|
|
304
|
-
import
|
|
252
|
+
import { existsSync, promises as fs2 } from "node:fs";
|
|
253
|
+
import path3 from "node:path";
|
|
305
254
|
import { lookup } from "mime-types";
|
|
306
255
|
var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
|
|
307
|
-
const
|
|
308
|
-
const
|
|
309
|
-
const
|
|
310
|
-
const fileAbsolutePath =
|
|
256
|
+
const pathname = parsedUrl.pathname.replace("/static", "./static");
|
|
257
|
+
const ext = path3.parse(pathname).ext;
|
|
258
|
+
const staticBaseDir = path3.resolve(process.cwd(), staticDirRelativePath);
|
|
259
|
+
const fileAbsolutePath = path3.resolve(staticBaseDir, pathname);
|
|
260
|
+
if (!fileAbsolutePath.startsWith(staticBaseDir)) {
|
|
261
|
+
res.statusCode = 403;
|
|
262
|
+
res.end();
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
311
265
|
try {
|
|
312
|
-
const fileHandle = await
|
|
313
|
-
const fileData = await
|
|
266
|
+
const fileHandle = await fs2.open(fileAbsolutePath, "r");
|
|
267
|
+
const fileData = await fs2.readFile(fileHandle);
|
|
314
268
|
res.setHeader("Content-type", lookup(ext) || "text/plain");
|
|
315
269
|
res.end(fileData);
|
|
316
270
|
fileHandle.close();
|
|
@@ -346,9 +300,11 @@ var safeAsyncServerListen = (server, port) => {
|
|
|
346
300
|
});
|
|
347
301
|
});
|
|
348
302
|
};
|
|
349
|
-
var
|
|
350
|
-
var
|
|
351
|
-
var
|
|
303
|
+
var filename = url.fileURLToPath(import.meta.url);
|
|
304
|
+
var dirname = path4.dirname(filename);
|
|
305
|
+
var isDev = !filename.endsWith(path4.join("cli", "index.mjs"));
|
|
306
|
+
var cliPackageLocation = isDev ? path4.resolve(dirname, "../../../..") : path4.resolve(dirname, "../..");
|
|
307
|
+
var previewServerLocation = isDev ? path4.resolve(dirname, "../../../..") : path4.resolve(dirname, "../preview");
|
|
352
308
|
var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, port) => {
|
|
353
309
|
devServer = http.createServer((req, res) => {
|
|
354
310
|
if (!req.url) {
|
|
@@ -415,7 +371,7 @@ var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, po
|
|
|
415
371
|
...process.env,
|
|
416
372
|
...getEnvVariablesForPreviewApp(
|
|
417
373
|
// If we don't do normalization here, stuff like https://github.com/resend/react-email/issues/1354 happens.
|
|
418
|
-
|
|
374
|
+
path4.normalize(emailsDirRelativePath),
|
|
419
375
|
process.cwd()
|
|
420
376
|
)
|
|
421
377
|
};
|
|
@@ -475,7 +431,8 @@ process.on(
|
|
|
475
431
|
|
|
476
432
|
// src/cli/utils/preview/hot-reloading/get-imported-modules.ts
|
|
477
433
|
import { parse } from "@babel/parser";
|
|
478
|
-
import
|
|
434
|
+
import traverseModule from "@babel/traverse";
|
|
435
|
+
var traverse = traverseModule.default;
|
|
479
436
|
var getImportedModules = (contents) => {
|
|
480
437
|
const importedPaths = [];
|
|
481
438
|
const parsedContents = parse(contents, {
|
|
@@ -496,6 +453,9 @@ var getImportedModules = (contents) => {
|
|
|
496
453
|
importedPaths.push(node.source.value);
|
|
497
454
|
}
|
|
498
455
|
},
|
|
456
|
+
TSExternalModuleReference({ node }) {
|
|
457
|
+
importedPaths.push(node.expression.value);
|
|
458
|
+
},
|
|
499
459
|
CallExpression({ node }) {
|
|
500
460
|
if ("name" in node.callee && node.callee.name === "require") {
|
|
501
461
|
if (node.arguments.length === 1) {
|
|
@@ -513,9 +473,9 @@ var getImportedModules = (contents) => {
|
|
|
513
473
|
// src/cli/utils/preview/hot-reloading/create-dependency-graph.ts
|
|
514
474
|
var readAllFilesInsideDirectory = async (directory) => {
|
|
515
475
|
let allFilePaths = [];
|
|
516
|
-
const topLevelDirents = await
|
|
476
|
+
const topLevelDirents = await fs3.readdir(directory, { withFileTypes: true });
|
|
517
477
|
for await (const dirent of topLevelDirents) {
|
|
518
|
-
const pathToDirent =
|
|
478
|
+
const pathToDirent = path5.join(directory, dirent.name);
|
|
519
479
|
if (dirent.isDirectory()) {
|
|
520
480
|
allFilePaths = allFilePaths.concat(
|
|
521
481
|
await readAllFilesInsideDirectory(pathToDirent)
|
|
@@ -527,7 +487,7 @@ var readAllFilesInsideDirectory = async (directory) => {
|
|
|
527
487
|
return allFilePaths;
|
|
528
488
|
};
|
|
529
489
|
var isJavascriptModule = (filePath) => {
|
|
530
|
-
const extensionName =
|
|
490
|
+
const extensionName = path5.extname(filePath);
|
|
531
491
|
return [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"].includes(extensionName);
|
|
532
492
|
};
|
|
533
493
|
var checkFileExtensionsUntilItExists = (pathWithoutExtension) => {
|
|
@@ -565,15 +525,15 @@ var createDependencyGraph = async (directory) => {
|
|
|
565
525
|
])
|
|
566
526
|
);
|
|
567
527
|
const getDependencyPaths = async (filePath) => {
|
|
568
|
-
const contents = await
|
|
528
|
+
const contents = await fs3.readFile(filePath, "utf8");
|
|
569
529
|
const importedPaths = isJavascriptModule(filePath) ? getImportedModules(contents) : [];
|
|
570
530
|
const importedPathsRelativeToDirectory = importedPaths.map(
|
|
571
531
|
(dependencyPath) => {
|
|
572
532
|
const isModulePath = !dependencyPath.startsWith(".");
|
|
573
|
-
if (isModulePath ||
|
|
533
|
+
if (isModulePath || path5.isAbsolute(dependencyPath)) {
|
|
574
534
|
return dependencyPath;
|
|
575
535
|
}
|
|
576
|
-
let pathToDependencyFromDirectory =
|
|
536
|
+
let pathToDependencyFromDirectory = path5.resolve(
|
|
577
537
|
/*
|
|
578
538
|
path.resolve resolves paths differently from what imports on javascript do.
|
|
579
539
|
|
|
@@ -581,7 +541,7 @@ var createDependencyGraph = async (directory) => {
|
|
|
581
541
|
would end up going into /path/to/email.tsx/other-email instead of /path/to/other-email which is the
|
|
582
542
|
one the import is meant to go to
|
|
583
543
|
*/
|
|
584
|
-
|
|
544
|
+
path5.dirname(filePath),
|
|
585
545
|
dependencyPath
|
|
586
546
|
);
|
|
587
547
|
let isDirectory = false;
|
|
@@ -603,7 +563,7 @@ var createDependencyGraph = async (directory) => {
|
|
|
603
563
|
}
|
|
604
564
|
}
|
|
605
565
|
if (!isJavascriptModule(pathToDependencyFromDirectory)) {
|
|
606
|
-
const pathWithExtension =
|
|
566
|
+
const pathWithExtension = path5.extname(pathToDependencyFromDirectory).length > 0 ? pathToDependencyFromDirectory : checkFileExtensionsUntilItExists(pathToDependencyFromDirectory);
|
|
607
567
|
if (pathWithExtension) {
|
|
608
568
|
pathToDependencyFromDirectory = pathWithExtension;
|
|
609
569
|
} else if (isDev) {
|
|
@@ -616,10 +576,10 @@ var createDependencyGraph = async (directory) => {
|
|
|
616
576
|
}
|
|
617
577
|
);
|
|
618
578
|
const moduleDependencies = importedPathsRelativeToDirectory.filter(
|
|
619
|
-
(dependencyPath) => !dependencyPath.startsWith(".") && !
|
|
579
|
+
(dependencyPath) => !dependencyPath.startsWith(".") && !path5.isAbsolute(dependencyPath)
|
|
620
580
|
);
|
|
621
581
|
const nonNodeModuleImportPathsRelativeToDirectory = importedPathsRelativeToDirectory.filter(
|
|
622
|
-
(dependencyPath) => dependencyPath.startsWith(".") ||
|
|
582
|
+
(dependencyPath) => dependencyPath.startsWith(".") || path5.isAbsolute(dependencyPath)
|
|
623
583
|
);
|
|
624
584
|
return {
|
|
625
585
|
dependencyPaths: nonNodeModuleImportPathsRelativeToDirectory,
|
|
@@ -638,8 +598,7 @@ var createDependencyGraph = async (directory) => {
|
|
|
638
598
|
const { moduleDependencies, dependencyPaths: newDependencyPaths } = await getDependencyPaths(moduleFilePath);
|
|
639
599
|
graph[moduleFilePath].moduleDependencies = moduleDependencies;
|
|
640
600
|
for (const dependencyPath of graph[moduleFilePath].dependencyPaths) {
|
|
641
|
-
if (newDependencyPaths.includes(dependencyPath))
|
|
642
|
-
continue;
|
|
601
|
+
if (newDependencyPaths.includes(dependencyPath)) continue;
|
|
643
602
|
const dependencyModule = graph[dependencyPath];
|
|
644
603
|
if (dependencyModule !== void 0) {
|
|
645
604
|
dependencyModule.dependentPaths = dependencyModule.dependentPaths.filter(
|
|
@@ -751,14 +710,14 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
751
710
|
changes.filter(
|
|
752
711
|
(change) => (
|
|
753
712
|
// Ensures only changes inside the emails directory are emitted
|
|
754
|
-
|
|
713
|
+
path6.resolve(absolutePathToEmailsDirectory, change.filename).startsWith(absolutePathToEmailsDirectory)
|
|
755
714
|
)
|
|
756
715
|
)
|
|
757
716
|
);
|
|
758
717
|
});
|
|
759
718
|
changes = [];
|
|
760
719
|
}, 150);
|
|
761
|
-
const absolutePathToEmailsDirectory =
|
|
720
|
+
const absolutePathToEmailsDirectory = path6.resolve(
|
|
762
721
|
process.cwd(),
|
|
763
722
|
emailDirRelativePath
|
|
764
723
|
);
|
|
@@ -768,7 +727,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
768
727
|
cwd: absolutePathToEmailsDirectory
|
|
769
728
|
});
|
|
770
729
|
const getFilesOutsideEmailsDirectory = () => Object.keys(dependencyGraph).filter(
|
|
771
|
-
(p) =>
|
|
730
|
+
(p) => path6.relative(absolutePathToEmailsDirectory, p).startsWith("..")
|
|
772
731
|
);
|
|
773
732
|
let filesOutsideEmailsDirectory = getFilesOutsideEmailsDirectory();
|
|
774
733
|
for (const p of filesOutsideEmailsDirectory) {
|
|
@@ -780,11 +739,11 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
780
739
|
process.on("SIGINT", exit);
|
|
781
740
|
process.on("uncaughtException", exit);
|
|
782
741
|
watcher.on("all", async (event, relativePathToChangeTarget) => {
|
|
783
|
-
const file = relativePathToChangeTarget.split(
|
|
742
|
+
const file = relativePathToChangeTarget.split(path6.sep);
|
|
784
743
|
if (file.length === 0) {
|
|
785
744
|
return;
|
|
786
745
|
}
|
|
787
|
-
const pathToChangeTarget =
|
|
746
|
+
const pathToChangeTarget = path6.resolve(
|
|
788
747
|
absolutePathToEmailsDirectory,
|
|
789
748
|
relativePathToChangeTarget
|
|
790
749
|
);
|
|
@@ -808,7 +767,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
808
767
|
for (const dependentPath of resolveDependentsOf(pathToChangeTarget)) {
|
|
809
768
|
changes.push({
|
|
810
769
|
event: "change",
|
|
811
|
-
filename:
|
|
770
|
+
filename: path6.relative(absolutePathToEmailsDirectory, dependentPath)
|
|
812
771
|
});
|
|
813
772
|
}
|
|
814
773
|
reload();
|
|
@@ -816,6 +775,63 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
816
775
|
return watcher;
|
|
817
776
|
};
|
|
818
777
|
|
|
778
|
+
// src/cli/utils/tree.ts
|
|
779
|
+
import { promises as fs4 } from "node:fs";
|
|
780
|
+
import os from "node:os";
|
|
781
|
+
import path7 from "node:path";
|
|
782
|
+
var SYMBOLS = {
|
|
783
|
+
BRANCH: "\u251C\u2500\u2500 ",
|
|
784
|
+
EMPTY: "",
|
|
785
|
+
INDENT: " ",
|
|
786
|
+
LAST_BRANCH: "\u2514\u2500\u2500 ",
|
|
787
|
+
VERTICAL: "\u2502 "
|
|
788
|
+
};
|
|
789
|
+
var getTreeLines = async (dirPath, depth, currentDepth = 0) => {
|
|
790
|
+
const base = process.cwd();
|
|
791
|
+
const dirFullpath = path7.resolve(base, dirPath);
|
|
792
|
+
const dirname2 = path7.basename(dirFullpath);
|
|
793
|
+
let lines = [dirname2];
|
|
794
|
+
const dirStat = await fs4.stat(dirFullpath);
|
|
795
|
+
if (dirStat.isDirectory() && currentDepth < depth) {
|
|
796
|
+
const childDirents = await fs4.readdir(dirFullpath, { withFileTypes: true });
|
|
797
|
+
childDirents.sort((a, b) => {
|
|
798
|
+
if (a.isDirectory() && b.isFile()) {
|
|
799
|
+
return -1;
|
|
800
|
+
}
|
|
801
|
+
if (a.isFile() && b.isDirectory()) {
|
|
802
|
+
return 1;
|
|
803
|
+
}
|
|
804
|
+
return b.name > a.name ? -1 : 1;
|
|
805
|
+
});
|
|
806
|
+
for (let i = 0; i < childDirents.length; i++) {
|
|
807
|
+
const dirent = childDirents[i];
|
|
808
|
+
const isLast = i === childDirents.length - 1;
|
|
809
|
+
const branchingSymbol = isLast ? SYMBOLS.LAST_BRANCH : SYMBOLS.BRANCH;
|
|
810
|
+
const verticalSymbol = isLast ? SYMBOLS.INDENT : SYMBOLS.VERTICAL;
|
|
811
|
+
if (dirent.isFile()) {
|
|
812
|
+
lines.push(`${branchingSymbol}${dirent.name}`);
|
|
813
|
+
} else {
|
|
814
|
+
const pathToDirectory = path7.join(dirFullpath, dirent.name);
|
|
815
|
+
const treeLinesForSubDirectory = await getTreeLines(
|
|
816
|
+
pathToDirectory,
|
|
817
|
+
depth,
|
|
818
|
+
currentDepth + 1
|
|
819
|
+
);
|
|
820
|
+
lines = lines.concat(
|
|
821
|
+
treeLinesForSubDirectory.map(
|
|
822
|
+
(line, index) => index === 0 ? `${branchingSymbol}${line}` : `${verticalSymbol}${line}`
|
|
823
|
+
)
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
return lines;
|
|
829
|
+
};
|
|
830
|
+
var tree = async (dirPath, depth) => {
|
|
831
|
+
const lines = await getTreeLines(dirPath, depth);
|
|
832
|
+
return lines.join(os.EOL);
|
|
833
|
+
};
|
|
834
|
+
|
|
819
835
|
// src/cli/commands/build.ts
|
|
820
836
|
var buildPreviewApp = (absoluteDirectory) => {
|
|
821
837
|
return new Promise((resolve, reject) => {
|
|
@@ -883,8 +899,8 @@ var getEmailSlugsFromEmailDirectory = (emailDirectory, emailsDirectoryAbsolutePa
|
|
|
883
899
|
const directoryPathRelativeToEmailsDirectory = emailDirectory.absolutePath.replace(emailsDirectoryAbsolutePath, "").trim();
|
|
884
900
|
const slugs = [];
|
|
885
901
|
emailDirectory.emailFilenames.forEach(
|
|
886
|
-
(
|
|
887
|
-
path8.join(directoryPathRelativeToEmailsDirectory,
|
|
902
|
+
(filename3) => slugs.push(
|
|
903
|
+
path8.join(directoryPathRelativeToEmailsDirectory, filename3).split(path8.sep).filter((segment) => segment.length > 0)
|
|
888
904
|
)
|
|
889
905
|
);
|
|
890
906
|
emailDirectory.subDirectories.forEach((directory) => {
|
|
@@ -939,6 +955,7 @@ var updatePackageJson = async (builtPreviewAppPath) => {
|
|
|
939
955
|
);
|
|
940
956
|
packageJson.scripts.build = "next build";
|
|
941
957
|
packageJson.scripts.start = "next start";
|
|
958
|
+
delete packageJson.scripts.postbuild;
|
|
942
959
|
packageJson.name = "preview-server";
|
|
943
960
|
delete packageJson.devDependencies["@react-email/render"];
|
|
944
961
|
delete packageJson.devDependencies["@react-email/components"];
|
|
@@ -1061,7 +1078,9 @@ var dev = async ({ dir: emailsDirRelativePath, port }) => {
|
|
|
1061
1078
|
|
|
1062
1079
|
// src/cli/commands/export.ts
|
|
1063
1080
|
import fs8, { unlinkSync, writeFileSync } from "node:fs";
|
|
1081
|
+
import { createRequire } from "node:module";
|
|
1064
1082
|
import path10 from "node:path";
|
|
1083
|
+
import url2 from "node:url";
|
|
1065
1084
|
import { build as build2 } from "esbuild";
|
|
1066
1085
|
import { glob } from "glob";
|
|
1067
1086
|
import logSymbols4 from "log-symbols";
|
|
@@ -1124,13 +1143,15 @@ var renderingUtilitiesExporter = (emailTemplates) => ({
|
|
|
1124
1143
|
var getEmailTemplatesFromDirectory = (emailDirectory) => {
|
|
1125
1144
|
const templatePaths = [];
|
|
1126
1145
|
emailDirectory.emailFilenames.forEach(
|
|
1127
|
-
(
|
|
1146
|
+
(filename3) => templatePaths.push(path10.join(emailDirectory.absolutePath, filename3))
|
|
1128
1147
|
);
|
|
1129
1148
|
emailDirectory.subDirectories.forEach((directory) => {
|
|
1130
1149
|
templatePaths.push(...getEmailTemplatesFromDirectory(directory));
|
|
1131
1150
|
});
|
|
1132
1151
|
return templatePaths;
|
|
1133
1152
|
};
|
|
1153
|
+
var filename2 = url2.fileURLToPath(import.meta.url);
|
|
1154
|
+
var require2 = createRequire(filename2);
|
|
1134
1155
|
var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirectoryPath, options) => {
|
|
1135
1156
|
if (fs8.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
|
|
1136
1157
|
fs8.rmSync(pathToWhereEmailMarkupShouldBeDumped, { recursive: true });
|
|
@@ -1158,23 +1179,26 @@ var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirecto
|
|
|
1158
1179
|
await build2({
|
|
1159
1180
|
bundle: true,
|
|
1160
1181
|
entryPoints: allTemplates,
|
|
1161
|
-
plugins: [renderingUtilitiesExporter(allTemplates)],
|
|
1162
|
-
platform: "node",
|
|
1163
1182
|
format: "cjs",
|
|
1183
|
+
jsx: "transform",
|
|
1164
1184
|
loader: { ".js": "jsx" },
|
|
1185
|
+
logLevel: "silent",
|
|
1165
1186
|
outExtension: { ".js": ".cjs" },
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1187
|
+
outdir: pathToWhereEmailMarkupShouldBeDumped,
|
|
1188
|
+
platform: "node",
|
|
1189
|
+
plugins: [renderingUtilitiesExporter(allTemplates)],
|
|
1190
|
+
write: true
|
|
1169
1191
|
});
|
|
1170
1192
|
} catch (exception) {
|
|
1171
|
-
const buildFailure = exception;
|
|
1172
1193
|
if (spinner) {
|
|
1173
1194
|
spinner.stopAndPersist({
|
|
1174
1195
|
symbol: logSymbols4.error,
|
|
1175
1196
|
text: "Failed to build emails"
|
|
1176
1197
|
});
|
|
1177
1198
|
}
|
|
1199
|
+
const buildFailure = exception;
|
|
1200
|
+
console.error(`
|
|
1201
|
+
${buildFailure.message}`);
|
|
1178
1202
|
process.exit(1);
|
|
1179
1203
|
}
|
|
1180
1204
|
if (spinner) {
|
|
@@ -1192,8 +1216,8 @@ var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirecto
|
|
|
1192
1216
|
spinner.text = `rendering ${template.split("/").pop()}`;
|
|
1193
1217
|
spinner.render();
|
|
1194
1218
|
}
|
|
1195
|
-
delete
|
|
1196
|
-
const emailModule =
|
|
1219
|
+
delete require2.cache[template];
|
|
1220
|
+
const emailModule = require2(template);
|
|
1197
1221
|
const rendered = await emailModule.render(
|
|
1198
1222
|
emailModule.reactEmailCreateReactElement(emailModule.default, {}),
|
|
1199
1223
|
options
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
zs2-dZFPht_M4xAoOGgCM
|