@blinkk/root 1.0.0-beta.3 → 1.0.0-beta.31
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/bin/root.js +3 -0
- package/dist/chunk-4NAXAI6M.js +1184 -0
- package/dist/chunk-4NAXAI6M.js.map +1 -0
- package/dist/{chunk-WVRC46JG.js → chunk-DXD5LKU3.js} +18 -18
- package/dist/chunk-DXD5LKU3.js.map +1 -0
- package/dist/{chunk-WTSNW7BB.js → chunk-HQXIHYDN.js} +1 -1
- package/dist/chunk-HQXIHYDN.js.map +1 -0
- package/dist/{chunk-DTEQ2AIW.js → chunk-QKBMWK5B.js} +1 -1
- package/dist/chunk-QKBMWK5B.js.map +1 -0
- package/dist/{chunk-LTSJAEBG.js → chunk-XGD3RBFM.js} +5 -4
- package/dist/chunk-XGD3RBFM.js.map +1 -0
- package/dist/cli.d.ts +13 -4
- package/dist/cli.js +11 -1101
- package/dist/cli.js.map +1 -1
- package/dist/core.d.ts +10 -7
- package/dist/core.js +13 -13
- package/dist/core.js.map +1 -1
- package/dist/functions.d.ts +11 -0
- package/dist/functions.js +24 -0
- package/dist/functions.js.map +1 -0
- package/dist/node.d.ts +1 -1
- package/dist/node.js +2 -2
- package/dist/render.d.ts +1 -1
- package/dist/render.js +426 -215
- package/dist/render.js.map +1 -1
- package/dist/{types-47b9b530.d.ts → types-51e89bc0.d.ts} +88 -33
- package/package.json +32 -4
- package/dist/chunk-DTEQ2AIW.js.map +0 -1
- package/dist/chunk-LTSJAEBG.js.map +0 -1
- package/dist/chunk-WTSNW7BB.js.map +0 -1
- package/dist/chunk-WVRC46JG.js.map +0 -1
package/dist/render.js
CHANGED
|
@@ -1,18 +1,341 @@
|
|
|
1
|
-
import {
|
|
2
|
-
htmlMinify,
|
|
3
|
-
htmlPretty,
|
|
4
|
-
parseTagNames
|
|
5
|
-
} from "./chunk-WVRC46JG.js";
|
|
6
1
|
import {
|
|
7
2
|
HTML_CONTEXT,
|
|
8
3
|
I18N_CONTEXT,
|
|
9
4
|
REQUEST_CONTEXT,
|
|
10
5
|
getTranslations
|
|
11
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-HQXIHYDN.js";
|
|
7
|
+
import {
|
|
8
|
+
htmlMinify,
|
|
9
|
+
htmlPretty,
|
|
10
|
+
parseTagNames
|
|
11
|
+
} from "./chunk-DXD5LKU3.js";
|
|
12
12
|
|
|
13
13
|
// src/render/render.tsx
|
|
14
14
|
import renderToString from "preact-render-to-string";
|
|
15
15
|
|
|
16
|
+
// src/core/pages/ErrorPage.tsx
|
|
17
|
+
import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
|
|
18
|
+
var STYLES = `
|
|
19
|
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
|
|
20
|
+
|
|
21
|
+
:root {
|
|
22
|
+
--font-family-text: "Inter", sans-serif;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
body {
|
|
26
|
+
font-family: var(--font-family-text);
|
|
27
|
+
background: #F5F5F5;
|
|
28
|
+
padding: 40px 16px;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.root {
|
|
32
|
+
max-width: 1200px;
|
|
33
|
+
margin: 0 auto;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.root.align-center {
|
|
37
|
+
text-align: center;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
h1.title {
|
|
41
|
+
margin-top: 0;
|
|
42
|
+
margin-bottom: 24px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
p.message {
|
|
46
|
+
margin-top: 0;
|
|
47
|
+
margin-bottom: 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.box {
|
|
51
|
+
font-size: 16px;
|
|
52
|
+
line-height: 1.5;
|
|
53
|
+
padding: 16px;
|
|
54
|
+
border-radius: 12px;
|
|
55
|
+
background: #ffffff;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
pre.box {
|
|
59
|
+
white-space: pre-wrap;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@media (min-width: 500px) {
|
|
63
|
+
body {
|
|
64
|
+
padding: 40px;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.box {
|
|
68
|
+
padding: 24px;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@media (min-width: 1024px) {
|
|
73
|
+
body {
|
|
74
|
+
padding: 100px;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
function ErrorPage(props) {
|
|
79
|
+
const { code, message } = props;
|
|
80
|
+
const title = props.title || code;
|
|
81
|
+
return /* @__PURE__ */ jsxs(Fragment, {
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ jsx("style", {
|
|
84
|
+
dangerouslySetInnerHTML: { __html: STYLES }
|
|
85
|
+
}),
|
|
86
|
+
/* @__PURE__ */ jsxs("div", {
|
|
87
|
+
className: `root align-${props.align || "left"}`,
|
|
88
|
+
children: [
|
|
89
|
+
/* @__PURE__ */ jsx("h1", {
|
|
90
|
+
className: "title",
|
|
91
|
+
children: title
|
|
92
|
+
}),
|
|
93
|
+
message && /* @__PURE__ */ jsx("p", {
|
|
94
|
+
className: "message",
|
|
95
|
+
children: message
|
|
96
|
+
}),
|
|
97
|
+
props.children
|
|
98
|
+
]
|
|
99
|
+
})
|
|
100
|
+
]
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/core/pages/DevErrorPage.tsx
|
|
105
|
+
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
106
|
+
function DevErrorPage(props) {
|
|
107
|
+
var _a;
|
|
108
|
+
const req = props.req;
|
|
109
|
+
const err = props.error;
|
|
110
|
+
const route = props.route;
|
|
111
|
+
const routeParams = props.routeParams;
|
|
112
|
+
let errMsg = String(err);
|
|
113
|
+
if (err && err.stack) {
|
|
114
|
+
errMsg = err.stack.replace(/\(.*node_modules/g, "(node_modules").replace(/at \/.*node_modules/g, "at node_modules");
|
|
115
|
+
if ((_a = req.rootConfig) == null ? void 0 : _a.rootDir) {
|
|
116
|
+
errMsg = errMsg.replaceAll(req.rootConfig.rootDir, "<root>");
|
|
117
|
+
}
|
|
118
|
+
if (process.env.HOME) {
|
|
119
|
+
errMsg = errMsg.replaceAll(process.env.HOME, "$HOME");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return /* @__PURE__ */ jsxs2(ErrorPage, {
|
|
123
|
+
code: 500,
|
|
124
|
+
title: "Something went wrong",
|
|
125
|
+
children: [
|
|
126
|
+
errMsg && /* @__PURE__ */ jsxs2(Fragment2, {
|
|
127
|
+
children: [
|
|
128
|
+
/* @__PURE__ */ jsx2("h2", {
|
|
129
|
+
children: "Error"
|
|
130
|
+
}),
|
|
131
|
+
/* @__PURE__ */ jsx2("pre", {
|
|
132
|
+
className: "box",
|
|
133
|
+
children: /* @__PURE__ */ jsx2("code", {
|
|
134
|
+
children: errMsg
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
]
|
|
138
|
+
}),
|
|
139
|
+
/* @__PURE__ */ jsx2("h2", {
|
|
140
|
+
children: "Debug Info"
|
|
141
|
+
}),
|
|
142
|
+
/* @__PURE__ */ jsx2("pre", {
|
|
143
|
+
className: "box",
|
|
144
|
+
children: /* @__PURE__ */ jsx2("code", {
|
|
145
|
+
children: `url: ${req.originalUrl}
|
|
146
|
+
route: ${(route == null ? void 0 : route.src) || "null"}
|
|
147
|
+
routeParams: ${routeParams && JSON.stringify(routeParams) || "null"}`
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
]
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/core/pages/DevNotFoundPage.tsx
|
|
155
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "preact/jsx-runtime";
|
|
156
|
+
function DevNotFoundPage(props) {
|
|
157
|
+
const req = props.req;
|
|
158
|
+
const routesListMap = {};
|
|
159
|
+
let srcMaxLength = 0;
|
|
160
|
+
Object.keys(props.sitemap).forEach((urlPath) => {
|
|
161
|
+
const route = props.sitemap[urlPath].route;
|
|
162
|
+
routesListMap[route.src] ??= [];
|
|
163
|
+
routesListMap[route.src].push({ route, urlPath });
|
|
164
|
+
if (route.src.length > srcMaxLength) {
|
|
165
|
+
srcMaxLength = route.src.length;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
const routeSrcs = Object.keys(routesListMap).sort(sortRouteFiles);
|
|
169
|
+
const lines = [];
|
|
170
|
+
routeSrcs.forEach((routeSrc) => {
|
|
171
|
+
const routeUrls = routesListMap[routeSrc].sort(sortRouteURLs);
|
|
172
|
+
routeUrls.forEach((routeUrl, i) => {
|
|
173
|
+
const urlPath = routeUrl.urlPath;
|
|
174
|
+
if (i === 0) {
|
|
175
|
+
lines.push(`${routeSrc.padEnd(srcMaxLength, " ")} => ${urlPath}`);
|
|
176
|
+
} else {
|
|
177
|
+
lines.push(`${"".padEnd(srcMaxLength, " ")} => ${urlPath}`);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
const routesListString = lines.join("\n");
|
|
182
|
+
return /* @__PURE__ */ jsxs3(ErrorPage, {
|
|
183
|
+
code: 404,
|
|
184
|
+
title: "Not found",
|
|
185
|
+
children: [
|
|
186
|
+
/* @__PURE__ */ jsx3("h2", {
|
|
187
|
+
children: "Routes"
|
|
188
|
+
}),
|
|
189
|
+
Object.keys(routesListMap).length > 0 ? /* @__PURE__ */ jsx3("pre", {
|
|
190
|
+
className: "box",
|
|
191
|
+
children: /* @__PURE__ */ jsx3("code", {
|
|
192
|
+
children: routesListString
|
|
193
|
+
})
|
|
194
|
+
}) : /* @__PURE__ */ jsxs3("div", {
|
|
195
|
+
className: "box",
|
|
196
|
+
children: [
|
|
197
|
+
"Add your first route at ",
|
|
198
|
+
/* @__PURE__ */ jsx3("code", {
|
|
199
|
+
children: "/routes/index.tsx"
|
|
200
|
+
})
|
|
201
|
+
]
|
|
202
|
+
}),
|
|
203
|
+
/* @__PURE__ */ jsx3("h2", {
|
|
204
|
+
children: "Debug Info"
|
|
205
|
+
}),
|
|
206
|
+
/* @__PURE__ */ jsx3("pre", {
|
|
207
|
+
className: "box",
|
|
208
|
+
children: /* @__PURE__ */ jsx3("code", {
|
|
209
|
+
children: `url: ${req.originalUrl}`
|
|
210
|
+
})
|
|
211
|
+
})
|
|
212
|
+
]
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
function sortRouteFiles(a, b) {
|
|
216
|
+
if (a === "routes/index.tsx") {
|
|
217
|
+
return -1;
|
|
218
|
+
}
|
|
219
|
+
if (b === "routes/index.tsx") {
|
|
220
|
+
return 1;
|
|
221
|
+
}
|
|
222
|
+
return a.localeCompare(b);
|
|
223
|
+
}
|
|
224
|
+
function sortRouteURLs(a, b) {
|
|
225
|
+
if (a.route.isDefaultLocale && !b.route.isDefaultLocale) {
|
|
226
|
+
return -1;
|
|
227
|
+
}
|
|
228
|
+
if (!a.route.isDefaultLocale && b.route.isDefaultLocale) {
|
|
229
|
+
return 1;
|
|
230
|
+
}
|
|
231
|
+
return a.urlPath.localeCompare(b.urlPath);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// src/render/accept-language.ts
|
|
235
|
+
var ACCEPT_LANG_RE = /((([a-zA-Z]+(-[a-zA-Z0-9]+){0,2})|\*)(;q=[0-1](\.[0-9]+)?)?)*/g;
|
|
236
|
+
function parseAcceptLanguage(value) {
|
|
237
|
+
const matches = String(value).match(ACCEPT_LANG_RE);
|
|
238
|
+
if (!matches) {
|
|
239
|
+
return [];
|
|
240
|
+
}
|
|
241
|
+
const results = [];
|
|
242
|
+
matches.forEach((m) => {
|
|
243
|
+
if (!m) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
const parts = m.split(";");
|
|
247
|
+
const ietf = parts[0].split("-");
|
|
248
|
+
const hasScript = ietf.length === 3;
|
|
249
|
+
results.push({
|
|
250
|
+
code: ietf[0],
|
|
251
|
+
script: hasScript ? ietf[1] : void 0,
|
|
252
|
+
region: hasScript ? ietf[2] : ietf[1],
|
|
253
|
+
quality: parts[1] ? parseFloat(parts[1].split("=")[1]) : 1
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
results.sort((a, b) => b.quality - a.quality);
|
|
257
|
+
return results;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/render/i18n-fallbacks.ts
|
|
261
|
+
var UNKNOWN_COUNTRY = "zz";
|
|
262
|
+
function getFallbackLocales(req) {
|
|
263
|
+
var _a, _b;
|
|
264
|
+
const hl = getFirstQueryParam(req, "hl");
|
|
265
|
+
const countryCode = getCountry(req);
|
|
266
|
+
if (isWebCrawler(req)) {
|
|
267
|
+
const defaultLocale = ((_b = (_a = req.rootConfig) == null ? void 0 : _a.i18n) == null ? void 0 : _b.defaultLocale) || "en";
|
|
268
|
+
if (hl && hl !== defaultLocale) {
|
|
269
|
+
return [hl, defaultLocale];
|
|
270
|
+
}
|
|
271
|
+
return [defaultLocale];
|
|
272
|
+
}
|
|
273
|
+
const locales = /* @__PURE__ */ new Set();
|
|
274
|
+
if (hl) {
|
|
275
|
+
const langCode = hl;
|
|
276
|
+
locales.add(`${langCode}_${countryCode}`);
|
|
277
|
+
locales.add(`${langCode}_ALL`);
|
|
278
|
+
locales.add(langCode);
|
|
279
|
+
}
|
|
280
|
+
const langs = getFallbackLanguages(req);
|
|
281
|
+
langs.forEach((langCode) => {
|
|
282
|
+
locales.add(`${langCode}_${countryCode}`);
|
|
283
|
+
});
|
|
284
|
+
locales.add(`ALL_${countryCode}`);
|
|
285
|
+
langs.forEach((langCode) => {
|
|
286
|
+
locales.add(`${langCode}_ALL`);
|
|
287
|
+
locales.add(langCode);
|
|
288
|
+
});
|
|
289
|
+
return Array.from(locales);
|
|
290
|
+
}
|
|
291
|
+
function getCountry(req) {
|
|
292
|
+
const normalize = (countryCode) => String(countryCode).toLowerCase();
|
|
293
|
+
const gl = getFirstQueryParam(req, "gl");
|
|
294
|
+
if (gl) {
|
|
295
|
+
return normalize(gl);
|
|
296
|
+
}
|
|
297
|
+
const gaeCountry = req.get("x-appengine-country");
|
|
298
|
+
if (gaeCountry) {
|
|
299
|
+
return normalize(gaeCountry);
|
|
300
|
+
}
|
|
301
|
+
return UNKNOWN_COUNTRY;
|
|
302
|
+
}
|
|
303
|
+
function getFallbackLanguages(req) {
|
|
304
|
+
const langs = /* @__PURE__ */ new Set();
|
|
305
|
+
const acceptLangHeader = req.get("accept-language") || "";
|
|
306
|
+
if (acceptLangHeader) {
|
|
307
|
+
parseAcceptLanguage(acceptLangHeader).forEach((lang) => {
|
|
308
|
+
if (lang.region) {
|
|
309
|
+
langs.add(`${lang.code}-${lang.region}`);
|
|
310
|
+
}
|
|
311
|
+
langs.add(lang.code);
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
langs.add("en");
|
|
315
|
+
return Array.from(langs);
|
|
316
|
+
}
|
|
317
|
+
function getFirstQueryParam(req, key) {
|
|
318
|
+
const val = req.query[key];
|
|
319
|
+
if (val === null || val === void 0) {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
if (Array.isArray(val)) {
|
|
323
|
+
if (val.length === 0) {
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
return String(val[0]);
|
|
327
|
+
}
|
|
328
|
+
return String(val);
|
|
329
|
+
}
|
|
330
|
+
function isWebCrawler(req) {
|
|
331
|
+
const userAgentHeader = req.get("User-Agent");
|
|
332
|
+
if (!userAgentHeader) {
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
const userAgent = userAgentHeader.toLowerCase();
|
|
336
|
+
return userAgent.includes("googlebot") || userAgent.includes("bingbot") || userAgent.includes("twitterbot");
|
|
337
|
+
}
|
|
338
|
+
|
|
16
339
|
// src/render/router.ts
|
|
17
340
|
import path from "node:path";
|
|
18
341
|
|
|
@@ -170,8 +493,9 @@ function getRoutes(config) {
|
|
|
170
493
|
src,
|
|
171
494
|
module: routes[modulePath],
|
|
172
495
|
locale: defaultLocale,
|
|
173
|
-
|
|
174
|
-
|
|
496
|
+
isDefaultLocale: true,
|
|
497
|
+
routePath: normalizeUrlPath(routePath),
|
|
498
|
+
localeRoutePath: normalizeUrlPath(localeRoutePath)
|
|
175
499
|
});
|
|
176
500
|
locales.forEach((locale) => {
|
|
177
501
|
const localePath = localeRoutePath.replace("[locale]", locale);
|
|
@@ -180,6 +504,7 @@ function getRoutes(config) {
|
|
|
180
504
|
src,
|
|
181
505
|
module: routes[modulePath],
|
|
182
506
|
locale,
|
|
507
|
+
isDefaultLocale: false,
|
|
183
508
|
routePath,
|
|
184
509
|
localeRoutePath
|
|
185
510
|
});
|
|
@@ -206,7 +531,7 @@ async function getAllPathsForRoute(urlPathFormat, route) {
|
|
|
206
531
|
);
|
|
207
532
|
} else {
|
|
208
533
|
urlPaths.push({
|
|
209
|
-
urlPath:
|
|
534
|
+
urlPath: normalizeUrlPath(urlPath),
|
|
210
535
|
params: pathParams.params || {}
|
|
211
536
|
});
|
|
212
537
|
}
|
|
@@ -218,7 +543,7 @@ async function getAllPathsForRoute(urlPathFormat, route) {
|
|
|
218
543
|
`path contains placeholders: ${urlPathFormat}, did you forget to define getStaticPaths()? more info: https://rootjs.dev/guide/routes#getStaticPaths`
|
|
219
544
|
);
|
|
220
545
|
} else {
|
|
221
|
-
urlPaths.push({ urlPath: urlPathFormat, params: {} });
|
|
546
|
+
urlPaths.push({ urlPath: normalizeUrlPath(urlPathFormat), params: {} });
|
|
222
547
|
}
|
|
223
548
|
return urlPaths;
|
|
224
549
|
}
|
|
@@ -235,6 +560,12 @@ function replaceParams(urlPathFormat, params) {
|
|
|
235
560
|
);
|
|
236
561
|
return urlPath;
|
|
237
562
|
}
|
|
563
|
+
function normalizeUrlPath(urlPath) {
|
|
564
|
+
if (urlPath !== "/" && urlPath.endsWith("/")) {
|
|
565
|
+
urlPath = urlPath.replace(/\/*$/g, "");
|
|
566
|
+
}
|
|
567
|
+
return urlPath;
|
|
568
|
+
}
|
|
238
569
|
function pathContainsPlaceholders(urlPath) {
|
|
239
570
|
const segments = urlPath.split("/");
|
|
240
571
|
return segments.some((segment) => {
|
|
@@ -242,186 +573,6 @@ function pathContainsPlaceholders(urlPath) {
|
|
|
242
573
|
});
|
|
243
574
|
}
|
|
244
575
|
|
|
245
|
-
// src/core/pages/ErrorPage.tsx
|
|
246
|
-
import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
|
|
247
|
-
var STYLES = `
|
|
248
|
-
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
|
|
249
|
-
|
|
250
|
-
:root {
|
|
251
|
-
--font-family-text: "Inter", sans-serif;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
body {
|
|
255
|
-
font-family: var(--font-family-text);
|
|
256
|
-
background: #F5F5F5;
|
|
257
|
-
padding: 40px 16px;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
.root {
|
|
261
|
-
max-width: 1200px;
|
|
262
|
-
margin: 0 auto;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
h1 {
|
|
266
|
-
margin-bottom: 40px;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
h2 {
|
|
270
|
-
margin-top: 30px;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
.box {
|
|
274
|
-
font-size: 16px;
|
|
275
|
-
line-height: 1.5;
|
|
276
|
-
padding: 16px;
|
|
277
|
-
border-radius: 12px;
|
|
278
|
-
background: #ffffff;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
pre.box {
|
|
282
|
-
white-space: pre-wrap;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
@media (min-width: 500px) {
|
|
286
|
-
body {
|
|
287
|
-
padding: 40px;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
.box {
|
|
291
|
-
padding: 24px;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
@media (min-width: 1024px) {
|
|
296
|
-
body {
|
|
297
|
-
padding: 100px;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
`;
|
|
301
|
-
function ErrorPage(props) {
|
|
302
|
-
const { code, message } = props;
|
|
303
|
-
const title = props.title ? `${code} | ${props.title}` : code;
|
|
304
|
-
return /* @__PURE__ */ jsxs(Fragment, {
|
|
305
|
-
children: [
|
|
306
|
-
/* @__PURE__ */ jsx("style", {
|
|
307
|
-
dangerouslySetInnerHTML: { __html: STYLES }
|
|
308
|
-
}),
|
|
309
|
-
/* @__PURE__ */ jsxs("div", {
|
|
310
|
-
className: "root",
|
|
311
|
-
children: [
|
|
312
|
-
/* @__PURE__ */ jsx("h1", {
|
|
313
|
-
children: title
|
|
314
|
-
}),
|
|
315
|
-
message && /* @__PURE__ */ jsx("p", {
|
|
316
|
-
children: message
|
|
317
|
-
}),
|
|
318
|
-
props.children
|
|
319
|
-
]
|
|
320
|
-
})
|
|
321
|
-
]
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// src/core/pages/DevNotFoundPage.tsx
|
|
326
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
327
|
-
function DevNotFoundPage(props) {
|
|
328
|
-
const req = props.req;
|
|
329
|
-
const routesList = [];
|
|
330
|
-
let urlMaxLength = 0;
|
|
331
|
-
Object.keys(props.sitemap).forEach((urlPath) => {
|
|
332
|
-
const route = props.sitemap[urlPath].route;
|
|
333
|
-
routesList.push(Object.assign({}, route, { urlPath }));
|
|
334
|
-
if (urlPath.length > urlMaxLength) {
|
|
335
|
-
urlMaxLength = urlPath.length;
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
const routesListString = routesList.map((route) => {
|
|
339
|
-
return `${route.urlPath.padEnd(urlMaxLength, " ")} => ${route.src}`;
|
|
340
|
-
}).join("\n");
|
|
341
|
-
return /* @__PURE__ */ jsxs2(ErrorPage, {
|
|
342
|
-
code: 404,
|
|
343
|
-
title: "Root.js",
|
|
344
|
-
children: [
|
|
345
|
-
/* @__PURE__ */ jsx2("h2", {
|
|
346
|
-
children: "Routes"
|
|
347
|
-
}),
|
|
348
|
-
routesList.length > 0 ? /* @__PURE__ */ jsx2("pre", {
|
|
349
|
-
className: "box",
|
|
350
|
-
children: /* @__PURE__ */ jsx2("code", {
|
|
351
|
-
children: routesListString
|
|
352
|
-
})
|
|
353
|
-
}) : /* @__PURE__ */ jsxs2("div", {
|
|
354
|
-
className: "box",
|
|
355
|
-
children: [
|
|
356
|
-
"Add your first route at ",
|
|
357
|
-
/* @__PURE__ */ jsx2("code", {
|
|
358
|
-
children: "/routes/index.tsx"
|
|
359
|
-
})
|
|
360
|
-
]
|
|
361
|
-
}),
|
|
362
|
-
/* @__PURE__ */ jsx2("h2", {
|
|
363
|
-
children: "Debug Info"
|
|
364
|
-
}),
|
|
365
|
-
/* @__PURE__ */ jsx2("pre", {
|
|
366
|
-
className: "box",
|
|
367
|
-
children: /* @__PURE__ */ jsx2("code", {
|
|
368
|
-
children: `url: ${req.originalUrl}`
|
|
369
|
-
})
|
|
370
|
-
})
|
|
371
|
-
]
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// src/core/pages/DevErrorPage.tsx
|
|
376
|
-
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "preact/jsx-runtime";
|
|
377
|
-
function DevErrorPage(props) {
|
|
378
|
-
var _a;
|
|
379
|
-
const req = props.req;
|
|
380
|
-
const err = props.error;
|
|
381
|
-
const route = props.route;
|
|
382
|
-
const routeParams = props.routeParams;
|
|
383
|
-
let errMsg = String(err);
|
|
384
|
-
if (err && err.stack) {
|
|
385
|
-
errMsg = err.stack.replace(/\(.*node_modules/g, "(node_modules").replace(/at \/.*node_modules/g, "at node_modules");
|
|
386
|
-
if ((_a = req.rootConfig) == null ? void 0 : _a.rootDir) {
|
|
387
|
-
errMsg = errMsg.replaceAll(req.rootConfig.rootDir, "<root>");
|
|
388
|
-
}
|
|
389
|
-
if (process.env.HOME) {
|
|
390
|
-
errMsg = errMsg.replaceAll(process.env.HOME, "$HOME");
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
return /* @__PURE__ */ jsxs3(ErrorPage, {
|
|
394
|
-
code: 500,
|
|
395
|
-
title: "Root.js",
|
|
396
|
-
children: [
|
|
397
|
-
errMsg && /* @__PURE__ */ jsxs3(Fragment2, {
|
|
398
|
-
children: [
|
|
399
|
-
/* @__PURE__ */ jsx3("h2", {
|
|
400
|
-
children: "Error"
|
|
401
|
-
}),
|
|
402
|
-
/* @__PURE__ */ jsx3("pre", {
|
|
403
|
-
className: "box",
|
|
404
|
-
children: /* @__PURE__ */ jsx3("code", {
|
|
405
|
-
children: errMsg
|
|
406
|
-
})
|
|
407
|
-
})
|
|
408
|
-
]
|
|
409
|
-
}),
|
|
410
|
-
/* @__PURE__ */ jsx3("h2", {
|
|
411
|
-
children: "Debug Info"
|
|
412
|
-
}),
|
|
413
|
-
/* @__PURE__ */ jsx3("pre", {
|
|
414
|
-
className: "box",
|
|
415
|
-
children: /* @__PURE__ */ jsx3("code", {
|
|
416
|
-
children: `url: ${req.originalUrl}
|
|
417
|
-
route: ${(route == null ? void 0 : route.src) || "null"}
|
|
418
|
-
routeParams: ${routeParams && JSON.stringify(routeParams) || "null"}`
|
|
419
|
-
})
|
|
420
|
-
})
|
|
421
|
-
]
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
|
|
425
576
|
// src/render/render.tsx
|
|
426
577
|
import { jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
|
|
427
578
|
var Renderer = class {
|
|
@@ -438,18 +589,28 @@ var Renderer = class {
|
|
|
438
589
|
next();
|
|
439
590
|
return;
|
|
440
591
|
}
|
|
592
|
+
if (route.locale) {
|
|
593
|
+
routeParams.$locale = route.locale;
|
|
594
|
+
}
|
|
595
|
+
const fallbackLocales = route.isDefaultLocale ? getFallbackLocales(req) : [route.locale];
|
|
441
596
|
const render404 = async () => {
|
|
442
597
|
next();
|
|
443
598
|
};
|
|
444
|
-
const render = async (props2) => {
|
|
599
|
+
const render = async (props2, options) => {
|
|
445
600
|
if (!route.module.default) {
|
|
446
601
|
console.error(`no default component exported in route: ${route.src}`);
|
|
447
602
|
render404();
|
|
448
603
|
return;
|
|
449
604
|
}
|
|
605
|
+
const currentPath = req.path;
|
|
606
|
+
const locale = (options == null ? void 0 : options.locale) || route.locale;
|
|
607
|
+
const translations = options == null ? void 0 : options.translations;
|
|
450
608
|
const output = await this.renderComponent(route.module.default, props2, {
|
|
609
|
+
currentPath,
|
|
451
610
|
route,
|
|
452
|
-
routeParams
|
|
611
|
+
routeParams,
|
|
612
|
+
locale,
|
|
613
|
+
translations
|
|
453
614
|
});
|
|
454
615
|
let html = output.html;
|
|
455
616
|
if (this.rootConfig.prettyHtml) {
|
|
@@ -458,7 +619,7 @@ var Renderer = class {
|
|
|
458
619
|
html = await htmlMinify(html, this.rootConfig.minifyHtmlOptions);
|
|
459
620
|
}
|
|
460
621
|
if (req.viteServer) {
|
|
461
|
-
html = await req.viteServer.transformIndexHtml(
|
|
622
|
+
html = await req.viteServer.transformIndexHtml(currentPath, html);
|
|
462
623
|
}
|
|
463
624
|
let statusCode = 200;
|
|
464
625
|
if (route.src === "routes/404.tsx") {
|
|
@@ -472,6 +633,7 @@ var Renderer = class {
|
|
|
472
633
|
const handlerContext = {
|
|
473
634
|
route,
|
|
474
635
|
params: routeParams,
|
|
636
|
+
i18nFallbackLocales: fallbackLocales,
|
|
475
637
|
render,
|
|
476
638
|
render404
|
|
477
639
|
};
|
|
@@ -494,10 +656,14 @@ var Renderer = class {
|
|
|
494
656
|
await render(props);
|
|
495
657
|
}
|
|
496
658
|
async renderComponent(Component, props, options) {
|
|
497
|
-
const { route, routeParams } = options;
|
|
498
|
-
const locale =
|
|
499
|
-
const translations =
|
|
659
|
+
const { currentPath, route, routeParams } = options;
|
|
660
|
+
const locale = options.locale;
|
|
661
|
+
const translations = {
|
|
662
|
+
...getTranslations(locale),
|
|
663
|
+
...options.translations || {}
|
|
664
|
+
};
|
|
500
665
|
const ctx = {
|
|
666
|
+
currentPath,
|
|
501
667
|
route,
|
|
502
668
|
props,
|
|
503
669
|
routeParams,
|
|
@@ -571,6 +737,9 @@ var Renderer = class {
|
|
|
571
737
|
}
|
|
572
738
|
async renderRoute(route, options) {
|
|
573
739
|
const routeParams = options.routeParams;
|
|
740
|
+
if (route.locale) {
|
|
741
|
+
routeParams.$locale = route.locale;
|
|
742
|
+
}
|
|
574
743
|
const Component = route.module.default;
|
|
575
744
|
if (!Component) {
|
|
576
745
|
throw new Error(
|
|
@@ -578,6 +747,8 @@ var Renderer = class {
|
|
|
578
747
|
);
|
|
579
748
|
}
|
|
580
749
|
let props = {};
|
|
750
|
+
let locale = route.locale;
|
|
751
|
+
let translations = void 0;
|
|
581
752
|
if (route.module.getStaticProps) {
|
|
582
753
|
const propsData = await route.module.getStaticProps({
|
|
583
754
|
rootConfig: this.rootConfig,
|
|
@@ -589,8 +760,25 @@ var Renderer = class {
|
|
|
589
760
|
if (propsData.props) {
|
|
590
761
|
props = propsData.props;
|
|
591
762
|
}
|
|
763
|
+
if (propsData.locale) {
|
|
764
|
+
locale = propsData.locale;
|
|
765
|
+
}
|
|
766
|
+
if (propsData.translations) {
|
|
767
|
+
translations = propsData.translations;
|
|
768
|
+
}
|
|
592
769
|
}
|
|
593
|
-
|
|
770
|
+
const routePath = route.isDefaultLocale ? route.routePath : route.localeRoutePath;
|
|
771
|
+
const currentPath = replaceParams(routePath, {
|
|
772
|
+
...routeParams,
|
|
773
|
+
locale
|
|
774
|
+
});
|
|
775
|
+
return this.renderComponent(Component, props, {
|
|
776
|
+
currentPath,
|
|
777
|
+
route,
|
|
778
|
+
routeParams,
|
|
779
|
+
locale,
|
|
780
|
+
translations
|
|
781
|
+
});
|
|
594
782
|
}
|
|
595
783
|
async getSitemap() {
|
|
596
784
|
const sitemap = {};
|
|
@@ -631,44 +819,67 @@ var Renderer = class {
|
|
|
631
819
|
${renderToString(page)}
|
|
632
820
|
`;
|
|
633
821
|
}
|
|
634
|
-
async render404() {
|
|
822
|
+
async render404(options) {
|
|
823
|
+
const currentPath = (options == null ? void 0 : options.currentPath) || "/404";
|
|
635
824
|
const [route, routeParams] = this.routes.get("/404");
|
|
636
825
|
if (route && route.src === "routes/404.tsx" && route.module.default) {
|
|
637
826
|
const Component = route.module.default;
|
|
638
|
-
return this.renderComponent(
|
|
827
|
+
return this.renderComponent(
|
|
828
|
+
Component,
|
|
829
|
+
{},
|
|
830
|
+
{ currentPath, route, routeParams, locale: "en" }
|
|
831
|
+
);
|
|
639
832
|
}
|
|
640
|
-
const mainHtml = renderToString(
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
833
|
+
const mainHtml = renderToString(
|
|
834
|
+
/* @__PURE__ */ jsx4(ErrorPage, {
|
|
835
|
+
code: 404,
|
|
836
|
+
title: "Not found",
|
|
837
|
+
message: "Double-check the URL entered and try again.",
|
|
838
|
+
align: "center"
|
|
839
|
+
})
|
|
840
|
+
);
|
|
644
841
|
const html = await this.renderHtml(mainHtml, {
|
|
645
|
-
headComponents: [
|
|
646
|
-
|
|
647
|
-
|
|
842
|
+
headComponents: [
|
|
843
|
+
/* @__PURE__ */ jsx4("title", {
|
|
844
|
+
children: "404 Not Found"
|
|
845
|
+
}),
|
|
846
|
+
/* @__PURE__ */ jsx4("meta", {
|
|
847
|
+
name: "viewport",
|
|
848
|
+
content: "width=device-width, initial-scale=1.0"
|
|
849
|
+
})
|
|
850
|
+
]
|
|
648
851
|
});
|
|
649
852
|
return { html };
|
|
650
853
|
}
|
|
651
|
-
async renderError(err) {
|
|
854
|
+
async renderError(err, options) {
|
|
855
|
+
const currentPath = (options == null ? void 0 : options.currentPath) || "/500";
|
|
652
856
|
const [route, routeParams] = this.routes.get("/500");
|
|
653
857
|
if (route && route.src === "routes/500.tsx" && route.module.default) {
|
|
654
858
|
const Component = route.module.default;
|
|
655
859
|
return this.renderComponent(
|
|
656
860
|
Component,
|
|
657
861
|
{ error: err },
|
|
658
|
-
{ route, routeParams }
|
|
862
|
+
{ currentPath, route, routeParams, locale: "en" }
|
|
659
863
|
);
|
|
660
864
|
}
|
|
661
865
|
const mainHtml = renderToString(
|
|
662
866
|
/* @__PURE__ */ jsx4(ErrorPage, {
|
|
663
867
|
code: 500,
|
|
664
|
-
title: "
|
|
665
|
-
message: "An unknown error occurred."
|
|
868
|
+
title: "Something went wrong",
|
|
869
|
+
message: "An unknown error occurred.",
|
|
870
|
+
align: "center"
|
|
666
871
|
})
|
|
667
872
|
);
|
|
668
873
|
const html = await this.renderHtml(mainHtml, {
|
|
669
|
-
headComponents: [
|
|
670
|
-
|
|
671
|
-
|
|
874
|
+
headComponents: [
|
|
875
|
+
/* @__PURE__ */ jsx4("title", {
|
|
876
|
+
children: "500 Error"
|
|
877
|
+
}),
|
|
878
|
+
/* @__PURE__ */ jsx4("meta", {
|
|
879
|
+
name: "viewport",
|
|
880
|
+
content: "width=device-width, initial-scale=1.0"
|
|
881
|
+
})
|
|
882
|
+
]
|
|
672
883
|
});
|
|
673
884
|
return { html };
|
|
674
885
|
}
|
|
@@ -682,7 +893,7 @@ ${renderToString(page)}
|
|
|
682
893
|
);
|
|
683
894
|
const html = await this.renderHtml(mainHtml, {
|
|
684
895
|
headComponents: [/* @__PURE__ */ jsx4("title", {
|
|
685
|
-
children: "404 | Root.js"
|
|
896
|
+
children: "404 Not found | Root.js"
|
|
686
897
|
})]
|
|
687
898
|
});
|
|
688
899
|
return { html };
|
|
@@ -699,7 +910,7 @@ ${renderToString(page)}
|
|
|
699
910
|
);
|
|
700
911
|
const html = await this.renderHtml(mainHtml, {
|
|
701
912
|
headComponents: [/* @__PURE__ */ jsx4("title", {
|
|
702
|
-
children: "500 | Root.js"
|
|
913
|
+
children: "500 Error | Root.js"
|
|
703
914
|
})]
|
|
704
915
|
});
|
|
705
916
|
return { html };
|