@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/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-WTSNW7BB.js";
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
- routePath,
174
- localeRoutePath
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: replaceParams(urlPathFormat, pathParams.params),
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(req.originalUrl, html);
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 = route.locale;
499
- const translations = getTranslations(locale);
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
- return this.renderComponent(Component, props, { route, routeParams });
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(Component, {}, { route, routeParams });
827
+ return this.renderComponent(
828
+ Component,
829
+ {},
830
+ { currentPath, route, routeParams, locale: "en" }
831
+ );
639
832
  }
640
- const mainHtml = renderToString(/* @__PURE__ */ jsx4(ErrorPage, {
641
- code: 404,
642
- title: "Not Found"
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: [/* @__PURE__ */ jsx4("title", {
646
- children: "404"
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: "Error",
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: [/* @__PURE__ */ jsx4("title", {
670
- children: "500"
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 };