reroute-js 0.45.11 → 0.46.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/README.md +100 -2
- package/_/blog/src/client/routes/blog/[layout].tsx +45 -13
- package/_/blog/src/client/routes/blog/content/pt-BR/1-hello-world.tsx +27 -0
- package/_/blog/src/client/routes/index.tsx +4 -4
- package/_/search/src/client/routes/docs/content/content-collections.md +18 -0
- package/cli/bin.d.ts +2 -2
- package/cli/bin.js +1175 -431
- package/cli/bin.js.map +33 -24
- package/cli/index.d.ts +2 -2
- package/cli/index.js +5 -5
- package/cli/index.js.map +1 -1
- package/cli/src/cli.d.ts +2 -2
- package/cli/src/commands/analyze.d.ts +2 -2
- package/cli/src/commands/build.d.ts +2 -2
- package/cli/src/commands/dev.d.ts +2 -2
- package/cli/src/commands/gen.d.ts +2 -2
- package/cli/src/commands/gen.d.ts.map +1 -1
- package/cli/src/commands/index.d.ts +2 -2
- package/cli/src/commands/init.d.ts +2 -2
- package/cli/src/commands/lib/assets.d.ts +2 -2
- package/cli/src/commands/lib/bundler.d.ts +2 -2
- package/cli/src/commands/lib/command.d.ts +2 -2
- package/cli/src/commands/lib/env.d.ts +2 -2
- package/cli/src/commands/lib/index.d.ts +2 -2
- package/cli/src/commands/lib/log.d.ts +2 -2
- package/cli/src/commands/lib/markdown/availability.d.ts +2 -2
- package/cli/src/commands/lib/markdown/index.d.ts +2 -2
- package/cli/src/commands/lib/markdown/processor.d.ts +2 -2
- package/cli/src/commands/lib/production.d.ts +2 -2
- package/cli/src/commands/lib/server.d.ts +2 -2
- package/cli/src/commands/lib/streaming/analyzer.d.ts +2 -2
- package/cli/src/commands/lib/streaming/suspense.d.ts +2 -2
- package/cli/src/commands/lib/tailwind.d.ts +2 -2
- package/cli/src/commands/lib/terminal-ui.d.ts +2 -2
- package/cli/src/commands/lib/version.d.ts +2 -2
- package/cli/src/commands/og.d.ts +2 -2
- package/cli/src/commands/start.d.ts +2 -2
- package/cli/src/index.d.ts +2 -2
- package/core/index.d.ts +2 -2
- package/core/index.js +827 -192
- package/core/index.js.map +32 -23
- package/core/src/bundler/hash.d.ts +2 -2
- package/core/src/bundler/index.d.ts +2 -2
- package/core/src/config.d.ts +6 -3
- package/core/src/config.d.ts.map +1 -1
- package/core/src/content/discovery.d.ts +2 -2
- package/core/src/content/index.d.ts +2 -2
- package/core/src/content/metadata.d.ts +2 -2
- package/core/src/i18n/catalog.d.ts +17 -0
- package/core/src/i18n/catalog.d.ts.map +1 -0
- package/core/src/i18n/discover.d.ts +19 -0
- package/core/src/i18n/discover.d.ts.map +1 -0
- package/core/src/i18n/index.d.ts +17 -0
- package/core/src/i18n/index.d.ts.map +1 -0
- package/core/src/i18n/messages.d.ts +18 -0
- package/core/src/i18n/messages.d.ts.map +1 -0
- package/core/src/i18n/negotiate.d.ts +18 -0
- package/core/src/i18n/negotiate.d.ts.map +1 -0
- package/core/src/i18n/pathname.d.ts +34 -0
- package/core/src/i18n/pathname.d.ts.map +1 -0
- package/core/src/i18n/resolve.d.ts +22 -0
- package/core/src/i18n/resolve.d.ts.map +1 -0
- package/core/src/i18n/types.d.ts +68 -0
- package/core/src/i18n/types.d.ts.map +1 -0
- package/core/src/index.d.ts +3 -2
- package/core/src/index.d.ts.map +1 -1
- package/core/src/llms/extractor.d.ts +2 -2
- package/core/src/llms/formatter.d.ts +2 -2
- package/core/src/llms/full-generator.d.ts +2 -2
- package/core/src/llms/index-generator.d.ts +2 -2
- package/core/src/llms/index.d.ts +2 -2
- package/core/src/og/discovery.d.ts +2 -2
- package/core/src/og/discovery.d.ts.map +1 -1
- package/core/src/og/index.d.ts +2 -2
- package/core/src/og/meta.d.ts +2 -2
- package/core/src/og/render.d.ts +2 -2
- package/core/src/og/types.d.ts +2 -2
- package/core/src/robots/discovery.d.ts +2 -2
- package/core/src/robots/generator.d.ts +2 -2
- package/core/src/robots/index.d.ts +2 -2
- package/core/src/robots/policies.d.ts +2 -2
- package/core/src/rss/discovery.d.ts +4 -2
- package/core/src/rss/discovery.d.ts.map +1 -1
- package/core/src/rss/generator.d.ts +2 -2
- package/core/src/rss/index.d.ts +2 -2
- package/core/src/sitemap/discovery.d.ts +7 -2
- package/core/src/sitemap/discovery.d.ts.map +1 -1
- package/core/src/sitemap/generator.d.ts +2 -2
- package/core/src/sitemap/generator.d.ts.map +1 -1
- package/core/src/sitemap/index.d.ts +2 -2
- package/core/src/ssr/index.d.ts +2 -2
- package/core/src/ssr/lib/cache.d.ts +2 -2
- package/core/src/ssr/lib/cleanup.d.ts +2 -2
- package/core/src/ssr/lib/collections.d.ts +2 -2
- package/core/src/ssr/lib/compression.d.ts +2 -2
- package/core/src/ssr/lib/compute/content.d.ts +2 -9
- package/core/src/ssr/lib/compute/content.d.ts.map +1 -1
- package/core/src/ssr/lib/compute/index.d.ts +2 -2
- package/core/src/ssr/lib/compute/index.d.ts.map +1 -1
- package/core/src/ssr/lib/compute/layouts.d.ts +2 -2
- package/core/src/ssr/lib/compute/routes.d.ts +2 -2
- package/core/src/ssr/lib/compute/routes.d.ts.map +1 -1
- package/core/src/ssr/lib/content-path.d.ts +22 -0
- package/core/src/ssr/lib/content-path.d.ts.map +1 -0
- package/core/src/ssr/lib/data.d.ts +2 -2
- package/core/src/ssr/lib/data.d.ts.map +1 -1
- package/core/src/ssr/lib/html.d.ts +2 -2
- package/core/src/ssr/lib/imports.d.ts +2 -2
- package/core/src/ssr/lib/index.d.ts +3 -2
- package/core/src/ssr/lib/index.d.ts.map +1 -1
- package/core/src/ssr/lib/layouts.d.ts +2 -2
- package/core/src/ssr/lib/metadata.d.ts +2 -2
- package/core/src/ssr/lib/metadata.d.ts.map +1 -1
- package/core/src/ssr/lib/mime.d.ts +2 -2
- package/core/src/ssr/lib/modules.d.ts +4 -4
- package/core/src/ssr/lib/modules.d.ts.map +1 -1
- package/core/src/ssr/lib/path.d.ts +2 -2
- package/core/src/ssr/lib/preload.d.ts +2 -2
- package/core/src/ssr/lib/preload.d.ts.map +1 -1
- package/core/src/ssr/lib/route-match.d.ts +20 -0
- package/core/src/ssr/lib/route-match.d.ts.map +1 -0
- package/core/src/ssr/lib/scripts/collections.d.ts +2 -2
- package/core/src/ssr/lib/scripts/data.d.ts +3 -3
- package/core/src/ssr/lib/scripts/data.d.ts.map +1 -1
- package/core/src/ssr/lib/scripts/escape.d.ts +2 -2
- package/core/src/ssr/lib/scripts/feeds.d.ts +2 -2
- package/core/src/ssr/lib/scripts/index.d.ts +2 -2
- package/core/src/ssr/lib/seed.d.ts +2 -2
- package/core/src/ssr/lib/seed.d.ts.map +1 -1
- package/core/src/ssr/lib/serialize.d.ts +2 -2
- package/core/src/ssr/lib/setup.d.ts +3 -3
- package/core/src/ssr/lib/setup.d.ts.map +1 -1
- package/core/src/ssr/lib/styles.d.ts +2 -2
- package/core/src/ssr/lib/template.d.ts +2 -2
- package/core/src/ssr/lib/types.d.ts +2 -2
- package/core/src/ssr/render.d.ts +4 -2
- package/core/src/ssr/render.d.ts.map +1 -1
- package/core/src/ssr/stream.d.ts +4 -2
- package/core/src/ssr/stream.d.ts.map +1 -1
- package/elysia/index.d.ts +2 -2
- package/elysia/index.js +1072 -276
- package/elysia/index.js.map +37 -27
- package/elysia/src/index.d.ts +2 -2
- package/elysia/src/libs/assets.d.ts +2 -2
- package/elysia/src/libs/cache.d.ts +2 -2
- package/elysia/src/libs/caching.d.ts +2 -2
- package/elysia/src/libs/http.d.ts +2 -2
- package/elysia/src/libs/i18n.d.ts +26 -0
- package/elysia/src/libs/i18n.d.ts.map +1 -0
- package/elysia/src/libs/image.d.ts +2 -2
- package/elysia/src/libs/index.d.ts +2 -2
- package/elysia/src/libs/llms.d.ts +2 -2
- package/elysia/src/libs/response.d.ts +2 -2
- package/elysia/src/libs/serving.d.ts +2 -2
- package/elysia/src/plugin.d.ts +2 -2
- package/elysia/src/routes/artifacts.d.ts +2 -2
- package/elysia/src/routes/content.d.ts +2 -2
- package/elysia/src/routes/image.d.ts +2 -2
- package/elysia/src/routes/index.d.ts +2 -2
- package/elysia/src/routes/internal.d.ts +2 -2
- package/elysia/src/routes/llms.d.ts +2 -2
- package/elysia/src/routes/og.d.ts +2 -2
- package/elysia/src/routes/og.d.ts.map +1 -1
- package/elysia/src/routes/redirects.d.ts +2 -2
- package/elysia/src/routes/robots.d.ts +2 -2
- package/elysia/src/routes/rss.d.ts +2 -2
- package/elysia/src/routes/rss.d.ts.map +1 -1
- package/elysia/src/routes/search.d.ts +2 -2
- package/elysia/src/routes/search.d.ts.map +1 -1
- package/elysia/src/routes/sitemap.d.ts +2 -2
- package/elysia/src/routes/ssr.d.ts +2 -2
- package/elysia/src/routes/ssr.d.ts.map +1 -1
- package/elysia/src/routes/static.d.ts +2 -2
- package/elysia/src/types.d.ts +2 -2
- package/package.json +7 -6
- package/react/index.d.ts +2 -2
- package/react/index.js +565 -171
- package/react/index.js.map +12 -10
- package/react/src/components/ClientOnly.d.ts +2 -2
- package/react/src/components/ContentRoute.d.ts +3 -3
- package/react/src/components/ContentRoute.d.ts.map +1 -1
- package/react/src/components/Image.d.ts +2 -2
- package/react/src/components/LazyRoute.d.ts +2 -2
- package/react/src/components/Link.d.ts +2 -2
- package/react/src/components/Link.d.ts.map +1 -1
- package/react/src/components/Markdown.d.ts +2 -2
- package/react/src/components/Outlet.d.ts +2 -2
- package/react/src/components/index.d.ts +2 -2
- package/react/src/hooks/index.d.ts +2 -2
- package/react/src/hooks/useContent.d.ts +2 -2
- package/react/src/hooks/useContent.d.ts.map +1 -1
- package/react/src/hooks/useData.d.ts +2 -2
- package/react/src/hooks/useFeed.d.ts +2 -2
- package/react/src/hooks/useLayoutData.d.ts +2 -2
- package/react/src/hooks/useLlms.d.ts +2 -2
- package/react/src/hooks/useNavigate.d.ts +2 -2
- package/react/src/hooks/useParams.d.ts +2 -2
- package/react/src/hooks/useRouter.d.ts +2 -2
- package/react/src/hooks/useSearch.d.ts +2 -2
- package/react/src/hooks/useSearch.d.ts.map +1 -1
- package/react/src/hooks/useSearchParams.d.ts +2 -2
- package/react/src/hooks/useToc.d.ts +2 -2
- package/react/src/i18n/LocaleProvider.d.ts +49 -0
- package/react/src/i18n/LocaleProvider.d.ts.map +1 -0
- package/react/src/i18n/helpers.d.ts +24 -0
- package/react/src/i18n/helpers.d.ts.map +1 -0
- package/react/src/i18n/index.d.ts +13 -0
- package/react/src/i18n/index.d.ts.map +1 -0
- package/react/src/index.d.ts +3 -2
- package/react/src/index.d.ts.map +1 -1
- package/react/src/lib/collection.d.ts +2 -2
- package/react/src/lib/content.d.ts +4 -3
- package/react/src/lib/content.d.ts.map +1 -1
- package/react/src/lib/head.d.ts +2 -2
- package/react/src/lib/index.d.ts +2 -2
- package/react/src/lib/lazy-route.d.ts +2 -2
- package/react/src/lib/route-loader.d.ts +2 -2
- package/react/src/providers/ContentProvider.d.ts +3 -3
- package/react/src/providers/ContentProvider.d.ts.map +1 -1
- package/react/src/providers/RerouteProvider.d.ts +8 -6
- package/react/src/providers/RerouteProvider.d.ts.map +1 -1
- package/react/src/providers/RouterProvider.d.ts +2 -2
- package/react/src/providers/index.d.ts +2 -2
- package/react/src/types/any.d.ts +2 -2
- package/react/src/types/index.d.ts +2 -2
- package/react/src/types/router.d.ts +2 -2
- package/telemetry/react.d.ts +2 -2
- package/telemetry/react.js +8 -4
- package/telemetry/react.js.map +2 -2
- package/telemetry/server.d.ts +2 -2
- package/telemetry/server.js +60 -5
- package/telemetry/server.js.map +22 -17
- package/telemetry/src/react/api.d.ts +2 -2
- package/telemetry/src/react/context.d.ts +2 -2
- package/telemetry/src/react/index.d.ts +2 -2
- package/telemetry/src/react/telemetry.d.ts +2 -2
- package/telemetry/src/server/context.d.ts +2 -2
- package/telemetry/src/server/headers/extractor.d.ts +2 -2
- package/telemetry/src/server/headers/index.d.ts +2 -2
- package/telemetry/src/server/headers/presets.d.ts +2 -2
- package/telemetry/src/server/index.d.ts +2 -2
- package/telemetry/src/server/instrumentation.d.ts +2 -2
- package/telemetry/src/server/plugin.d.ts +2 -2
- package/telemetry/src/server/sourcemap.d.ts +2 -2
package/core/index.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* reroute-js v0.
|
|
2
|
+
* reroute-js v0.46.0
|
|
3
3
|
*
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @copyright 2026 stewones <hi@stewan.io>
|
|
6
|
-
* @see https://github.com/
|
|
6
|
+
* @see https://github.com/Intenseloop/reroute
|
|
7
7
|
*
|
|
8
8
|
* Built with Bun <3
|
|
9
9
|
*/
|
|
10
10
|
import { createRequire } from "node:module";
|
|
11
11
|
var __defProp = Object.defineProperty;
|
|
12
|
+
var __returnValue = (v) => v;
|
|
13
|
+
function __exportSetter(name, newValue) {
|
|
14
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
15
|
+
}
|
|
12
16
|
var __export = (target, all) => {
|
|
13
17
|
for (var name in all)
|
|
14
18
|
__defProp(target, name, {
|
|
15
19
|
get: all[name],
|
|
16
20
|
enumerable: true,
|
|
17
21
|
configurable: true,
|
|
18
|
-
set: (
|
|
22
|
+
set: __exportSetter.bind(all, name)
|
|
19
23
|
});
|
|
20
24
|
};
|
|
21
25
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
@@ -196,6 +200,364 @@ var init_content = __esm(() => {
|
|
|
196
200
|
init_metadata();
|
|
197
201
|
});
|
|
198
202
|
|
|
203
|
+
// packages/core/src/i18n/catalog.ts
|
|
204
|
+
function getMessage(catalog, key) {
|
|
205
|
+
if (!(catalog && key))
|
|
206
|
+
return;
|
|
207
|
+
const parts = key.split(".");
|
|
208
|
+
let current = catalog;
|
|
209
|
+
for (const part of parts) {
|
|
210
|
+
if (current == null || typeof current === "string")
|
|
211
|
+
return;
|
|
212
|
+
current = current[part];
|
|
213
|
+
}
|
|
214
|
+
return typeof current === "string" ? current : undefined;
|
|
215
|
+
}
|
|
216
|
+
function lookupMessage(catalogs, locale, defaultLocale, key) {
|
|
217
|
+
return getMessage(catalogs[locale], key) ?? (locale !== defaultLocale ? getMessage(catalogs[defaultLocale], key) : undefined);
|
|
218
|
+
}
|
|
219
|
+
var init_catalog = () => {};
|
|
220
|
+
|
|
221
|
+
// packages/core/src/i18n/discover.ts
|
|
222
|
+
import { readdir as readdir2 } from "node:fs/promises";
|
|
223
|
+
import { join as join2 } from "node:path";
|
|
224
|
+
async function loadCatalog(filePath) {
|
|
225
|
+
try {
|
|
226
|
+
const text = await Bun.file(filePath).text();
|
|
227
|
+
return JSON.parse(text);
|
|
228
|
+
} catch {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async function loadLocaleCatalogs(absDir) {
|
|
233
|
+
const entries = await readdir2(absDir, { withFileTypes: true });
|
|
234
|
+
const catalogs = {};
|
|
235
|
+
const locales = [];
|
|
236
|
+
for (const entry of entries) {
|
|
237
|
+
if (!(entry.isFile() && entry.name.endsWith(".json")))
|
|
238
|
+
continue;
|
|
239
|
+
const locale = entry.name.slice(0, -".json".length);
|
|
240
|
+
if (!locale)
|
|
241
|
+
continue;
|
|
242
|
+
const catalog = await loadCatalog(join2(absDir, entry.name));
|
|
243
|
+
if (!catalog)
|
|
244
|
+
continue;
|
|
245
|
+
catalogs[locale] = catalog;
|
|
246
|
+
locales.push(locale);
|
|
247
|
+
}
|
|
248
|
+
return { catalogs, locales };
|
|
249
|
+
}
|
|
250
|
+
function sortLocales(locales, defaultLocale) {
|
|
251
|
+
locales.sort((a, b) => {
|
|
252
|
+
if (a === defaultLocale)
|
|
253
|
+
return -1;
|
|
254
|
+
if (b === defaultLocale)
|
|
255
|
+
return 1;
|
|
256
|
+
return a.localeCompare(b);
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
async function discoverI18n(cwd, options = {}) {
|
|
260
|
+
const localesDir = options.localesDir ?? DEFAULT_LOCALES_DIR;
|
|
261
|
+
const defaultLocale = options.defaultLocale ?? DEFAULT_LOCALE;
|
|
262
|
+
const cookie = options.cookie ?? DEFAULT_COOKIE;
|
|
263
|
+
const redirectContentOnNegotiate = options.redirectContentOnNegotiate ?? true;
|
|
264
|
+
const absDir = join2(cwd, localesDir);
|
|
265
|
+
const disabled = {
|
|
266
|
+
enabled: false,
|
|
267
|
+
defaultLocale,
|
|
268
|
+
locales: [],
|
|
269
|
+
localesDir,
|
|
270
|
+
cookie,
|
|
271
|
+
redirectContentOnNegotiate,
|
|
272
|
+
catalogs: {}
|
|
273
|
+
};
|
|
274
|
+
let catalogs;
|
|
275
|
+
let locales;
|
|
276
|
+
try {
|
|
277
|
+
({ catalogs, locales } = await loadLocaleCatalogs(absDir));
|
|
278
|
+
} catch {
|
|
279
|
+
return disabled;
|
|
280
|
+
}
|
|
281
|
+
if (locales.length === 0) {
|
|
282
|
+
return disabled;
|
|
283
|
+
}
|
|
284
|
+
sortLocales(locales, defaultLocale);
|
|
285
|
+
if (!catalogs[defaultLocale]) {
|
|
286
|
+
console.warn(`[reroute/i18n] defaultLocale "${defaultLocale}" has no catalog; using "${locales[0]}"`);
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
enabled: true,
|
|
290
|
+
defaultLocale: catalogs[defaultLocale] ? defaultLocale : locales[0],
|
|
291
|
+
locales,
|
|
292
|
+
localesDir,
|
|
293
|
+
cookie,
|
|
294
|
+
redirectContentOnNegotiate,
|
|
295
|
+
catalogs
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
var DEFAULT_LOCALE = "en-US", DEFAULT_LOCALES_DIR = "locales", DEFAULT_COOKIE = "reroute-locale";
|
|
299
|
+
var init_discover = () => {};
|
|
300
|
+
|
|
301
|
+
// packages/core/src/i18n/messages.ts
|
|
302
|
+
import { IntlMessageFormat } from "intl-messageformat";
|
|
303
|
+
function formatMessage(message, locale, values) {
|
|
304
|
+
if (!values || Object.keys(values).length === 0) {
|
|
305
|
+
if (!/\{[^}]+\}/.test(message))
|
|
306
|
+
return message;
|
|
307
|
+
}
|
|
308
|
+
const cacheKey = `${locale}\x00${message}`;
|
|
309
|
+
let formatter = formatterCache.get(cacheKey);
|
|
310
|
+
if (!formatter) {
|
|
311
|
+
formatter = new IntlMessageFormat(message, locale);
|
|
312
|
+
formatterCache.set(cacheKey, formatter);
|
|
313
|
+
}
|
|
314
|
+
try {
|
|
315
|
+
const result = formatter.format(values);
|
|
316
|
+
return typeof result === "string" ? result : String(result);
|
|
317
|
+
} catch {
|
|
318
|
+
return message;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function createTranslator(catalogs, locale, defaultLocale) {
|
|
322
|
+
return (key, values) => {
|
|
323
|
+
const message = lookupMessage(catalogs, locale, defaultLocale, key);
|
|
324
|
+
if (message == null)
|
|
325
|
+
return key;
|
|
326
|
+
return formatMessage(message, locale, values);
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
var formatterCache;
|
|
330
|
+
var init_messages = __esm(() => {
|
|
331
|
+
init_catalog();
|
|
332
|
+
formatterCache = new Map;
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// packages/core/src/i18n/negotiate.ts
|
|
336
|
+
function negotiateLocale(acceptLanguage, availableLocales, defaultLocale) {
|
|
337
|
+
if (!availableLocales.length)
|
|
338
|
+
return defaultLocale;
|
|
339
|
+
if (!acceptLanguage)
|
|
340
|
+
return defaultLocale;
|
|
341
|
+
const availableLower = new Map(availableLocales.map((l) => [l.toLowerCase(), l]));
|
|
342
|
+
const byLang = new Map;
|
|
343
|
+
for (const locale of availableLocales) {
|
|
344
|
+
const lang = locale.split("-")[0].toLowerCase();
|
|
345
|
+
if (!byLang.has(lang))
|
|
346
|
+
byLang.set(lang, locale);
|
|
347
|
+
}
|
|
348
|
+
const ranges = acceptLanguage.split(",").map((part) => {
|
|
349
|
+
const [tag, ...params] = part.trim().split(";");
|
|
350
|
+
let q = 1;
|
|
351
|
+
for (const p of params) {
|
|
352
|
+
const [k, v] = p.trim().split("=");
|
|
353
|
+
if (k === "q" && v)
|
|
354
|
+
q = Number.parseFloat(v) || 0;
|
|
355
|
+
}
|
|
356
|
+
return { tag: tag.trim().toLowerCase(), q };
|
|
357
|
+
}).filter((r) => r.tag && r.q > 0).sort((a, b) => b.q - a.q);
|
|
358
|
+
for (const { tag } of ranges) {
|
|
359
|
+
if (tag === "*")
|
|
360
|
+
return defaultLocale;
|
|
361
|
+
const exact = availableLower.get(tag);
|
|
362
|
+
if (exact)
|
|
363
|
+
return exact;
|
|
364
|
+
const langOnly = byLang.get(tag.split("-")[0]);
|
|
365
|
+
if (langOnly)
|
|
366
|
+
return langOnly;
|
|
367
|
+
}
|
|
368
|
+
return defaultLocale;
|
|
369
|
+
}
|
|
370
|
+
function parseCookieValue(cookieHeader, name) {
|
|
371
|
+
if (!cookieHeader)
|
|
372
|
+
return;
|
|
373
|
+
const parts = cookieHeader.split(";");
|
|
374
|
+
for (const part of parts) {
|
|
375
|
+
const idx = part.indexOf("=");
|
|
376
|
+
if (idx === -1)
|
|
377
|
+
continue;
|
|
378
|
+
const key = part.slice(0, idx).trim();
|
|
379
|
+
if (key === name) {
|
|
380
|
+
return decodeURIComponent(part.slice(idx + 1).trim());
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
function buildLocaleCookie(name, locale, maxAgeSeconds = 60 * 60 * 24 * 365) {
|
|
386
|
+
return `${name}=${encodeURIComponent(locale)}; Path=/; Max-Age=${maxAgeSeconds}; SameSite=Lax`;
|
|
387
|
+
}
|
|
388
|
+
var init_negotiate = () => {};
|
|
389
|
+
|
|
390
|
+
// packages/core/src/i18n/pathname.ts
|
|
391
|
+
var exports_pathname = {};
|
|
392
|
+
__export(exports_pathname, {
|
|
393
|
+
toOgLocale: () => toOgLocale,
|
|
394
|
+
parseContentPath: () => parseContentPath,
|
|
395
|
+
normalizePathname: () => normalizePathname,
|
|
396
|
+
looksLikeLocale: () => looksLikeLocale,
|
|
397
|
+
localizeHref: () => localizeHref,
|
|
398
|
+
localizeContentHref: () => localizeContentHref,
|
|
399
|
+
hreflangTags: () => hreflangTags,
|
|
400
|
+
contentKey: () => contentKey
|
|
401
|
+
});
|
|
402
|
+
function looksLikeLocale(segment) {
|
|
403
|
+
return /^[a-z]{2}(?:-[A-Za-z0-9]{2,8})*$/i.test(segment);
|
|
404
|
+
}
|
|
405
|
+
function normalizePathname(pathname) {
|
|
406
|
+
const pathOnly = pathname.split("?")[0].split("#")[0];
|
|
407
|
+
if (!pathOnly || pathOnly === "/")
|
|
408
|
+
return "/";
|
|
409
|
+
return pathOnly.startsWith("/") ? pathOnly : `/${pathOnly}`;
|
|
410
|
+
}
|
|
411
|
+
function parseContentPath(pathname, availableLocales = [], collections) {
|
|
412
|
+
const normalized = normalizePathname(pathname);
|
|
413
|
+
const parts = normalized.split("/").filter(Boolean);
|
|
414
|
+
if (parts.length < 2)
|
|
415
|
+
return;
|
|
416
|
+
const [collection, second, third] = parts;
|
|
417
|
+
if (collections && !collections.includes(collection)) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const localeSet = new Set(availableLocales.map((l) => l.toLowerCase()));
|
|
421
|
+
if (parts.length >= 3 && third) {
|
|
422
|
+
const secondIsLocale = localeSet.size > 0 ? localeSet.has(second.toLowerCase()) : looksLikeLocale(second);
|
|
423
|
+
if (secondIsLocale) {
|
|
424
|
+
const locale = availableLocales.find((l) => l.toLowerCase() === second.toLowerCase()) || second;
|
|
425
|
+
return {
|
|
426
|
+
collection,
|
|
427
|
+
name: third,
|
|
428
|
+
locale,
|
|
429
|
+
routingPathname: `/${collection}/${third}`,
|
|
430
|
+
pathname: normalized
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return {
|
|
435
|
+
collection,
|
|
436
|
+
name: second,
|
|
437
|
+
routingPathname: `/${collection}/${second}`,
|
|
438
|
+
pathname: normalized
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
function localizeContentHref(collection, name, locale, defaultLocale) {
|
|
442
|
+
if (!locale || locale === defaultLocale) {
|
|
443
|
+
return `/${collection}/${name}`;
|
|
444
|
+
}
|
|
445
|
+
return `/${collection}/${locale}/${name}`;
|
|
446
|
+
}
|
|
447
|
+
function localizeHref(to, locale, defaultLocale, availableLocales = [], collections) {
|
|
448
|
+
try {
|
|
449
|
+
const url = new URL(to, "http://local");
|
|
450
|
+
const parsed = parseContentPath(url.pathname, availableLocales, collections);
|
|
451
|
+
if (!parsed)
|
|
452
|
+
return to;
|
|
453
|
+
url.pathname = localizeContentHref(parsed.collection, parsed.name, locale, defaultLocale);
|
|
454
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
455
|
+
} catch {
|
|
456
|
+
return to;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
function contentKey(collection, name, locale, defaultLocale = "en-US") {
|
|
460
|
+
if (locale && locale !== defaultLocale) {
|
|
461
|
+
return `${collection}:${name}:${locale}`;
|
|
462
|
+
}
|
|
463
|
+
return `${collection}:${name}`;
|
|
464
|
+
}
|
|
465
|
+
function toOgLocale(locale) {
|
|
466
|
+
return locale.replace(/-/g, "_");
|
|
467
|
+
}
|
|
468
|
+
function hreflangTags(baseUrl, collection, name, locales, defaultLocale) {
|
|
469
|
+
const base = baseUrl.replace(/\/$/, "");
|
|
470
|
+
const tags = [];
|
|
471
|
+
for (const locale of locales) {
|
|
472
|
+
const path = localizeContentHref(collection, name, locale, defaultLocale);
|
|
473
|
+
tags.push(`<link rel="alternate" hreflang="${locale}" href="${base}${path}" />`);
|
|
474
|
+
}
|
|
475
|
+
const defaultPath = localizeContentHref(collection, name, defaultLocale, defaultLocale);
|
|
476
|
+
tags.push(`<link rel="alternate" hreflang="x-default" href="${base}${defaultPath}" />`);
|
|
477
|
+
return tags.join(`
|
|
478
|
+
`);
|
|
479
|
+
}
|
|
480
|
+
var init_pathname = () => {};
|
|
481
|
+
|
|
482
|
+
// packages/core/src/i18n/resolve.ts
|
|
483
|
+
function resolveLocale(input) {
|
|
484
|
+
const {
|
|
485
|
+
pathname,
|
|
486
|
+
cookieHeader,
|
|
487
|
+
acceptLanguage,
|
|
488
|
+
availableLocales,
|
|
489
|
+
defaultLocale,
|
|
490
|
+
cookieName = DEFAULT_COOKIE,
|
|
491
|
+
collections
|
|
492
|
+
} = input;
|
|
493
|
+
const parsed = parseContentPath(pathname, availableLocales, collections);
|
|
494
|
+
const availableLower = new Set(availableLocales.map((l) => l.toLowerCase()));
|
|
495
|
+
const isAvailable = (locale) => !!locale && availableLower.has(locale.toLowerCase());
|
|
496
|
+
if (parsed?.locale && isAvailable(parsed.locale)) {
|
|
497
|
+
const locale = availableLocales.find((l) => l.toLowerCase() === parsed.locale?.toLowerCase()) || parsed.locale;
|
|
498
|
+
if (locale === defaultLocale && parsed.pathname !== parsed.routingPathname) {
|
|
499
|
+
return {
|
|
500
|
+
locale,
|
|
501
|
+
routingPathname: parsed.routingPathname,
|
|
502
|
+
fromPath: true,
|
|
503
|
+
redirectTo: parsed.routingPathname,
|
|
504
|
+
parsed: { ...parsed, locale }
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
return {
|
|
508
|
+
locale,
|
|
509
|
+
routingPathname: parsed.routingPathname,
|
|
510
|
+
fromPath: true,
|
|
511
|
+
parsed: { ...parsed, locale }
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
const routingPathname = parsed?.routingPathname ?? pathname.split("?")[0];
|
|
515
|
+
const cookieLocale = parseCookieValue(cookieHeader, cookieName);
|
|
516
|
+
if (isAvailable(cookieLocale)) {
|
|
517
|
+
const locale = availableLocales.find((l) => l.toLowerCase() === cookieLocale.toLowerCase()) || cookieLocale;
|
|
518
|
+
return {
|
|
519
|
+
locale,
|
|
520
|
+
routingPathname,
|
|
521
|
+
fromPath: false,
|
|
522
|
+
parsed: parsed ? { ...parsed, locale: undefined } : undefined
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
const negotiated = negotiateLocale(acceptLanguage, availableLocales, defaultLocale);
|
|
526
|
+
return {
|
|
527
|
+
locale: negotiated,
|
|
528
|
+
routingPathname,
|
|
529
|
+
fromPath: false,
|
|
530
|
+
parsed: parsed ? { ...parsed, locale: undefined } : undefined
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
function contentNegotiateRedirect(resolution, defaultLocale, enabled) {
|
|
534
|
+
if (!enabled)
|
|
535
|
+
return;
|
|
536
|
+
if (resolution.fromPath)
|
|
537
|
+
return;
|
|
538
|
+
if (resolution.locale === defaultLocale)
|
|
539
|
+
return;
|
|
540
|
+
const parsed = resolution.parsed;
|
|
541
|
+
if (!parsed)
|
|
542
|
+
return;
|
|
543
|
+
return localizeContentHref(parsed.collection, parsed.name, resolution.locale, defaultLocale);
|
|
544
|
+
}
|
|
545
|
+
var init_resolve = __esm(() => {
|
|
546
|
+
init_discover();
|
|
547
|
+
init_negotiate();
|
|
548
|
+
init_pathname();
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
// packages/core/src/i18n/index.ts
|
|
552
|
+
var init_i18n = __esm(() => {
|
|
553
|
+
init_catalog();
|
|
554
|
+
init_discover();
|
|
555
|
+
init_messages();
|
|
556
|
+
init_negotiate();
|
|
557
|
+
init_pathname();
|
|
558
|
+
init_resolve();
|
|
559
|
+
});
|
|
560
|
+
|
|
199
561
|
// packages/telemetry/src/server/context.ts
|
|
200
562
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
201
563
|
var contextStorage;
|
|
@@ -790,6 +1152,148 @@ function compressStreamIfAccepted(stream, contentType, _acceptEncoding) {
|
|
|
790
1152
|
}
|
|
791
1153
|
var init_compression = () => {};
|
|
792
1154
|
|
|
1155
|
+
// packages/core/src/ssr/lib/route-match.ts
|
|
1156
|
+
function getPatternParts(pattern) {
|
|
1157
|
+
return pattern.split("/").filter(Boolean);
|
|
1158
|
+
}
|
|
1159
|
+
function isDynamicPatternPart(patternPart) {
|
|
1160
|
+
return patternPart.startsWith(":");
|
|
1161
|
+
}
|
|
1162
|
+
function isCatchAllPatternPart(patternPart) {
|
|
1163
|
+
return patternPart.startsWith(":...");
|
|
1164
|
+
}
|
|
1165
|
+
function isCatchAllParamName(paramName) {
|
|
1166
|
+
return paramName.startsWith("...");
|
|
1167
|
+
}
|
|
1168
|
+
function getPatternPartSpecificity(patternPart) {
|
|
1169
|
+
if (isCatchAllPatternPart(patternPart)) {
|
|
1170
|
+
return 2;
|
|
1171
|
+
}
|
|
1172
|
+
if (isDynamicPatternPart(patternPart)) {
|
|
1173
|
+
return 1;
|
|
1174
|
+
}
|
|
1175
|
+
return 0;
|
|
1176
|
+
}
|
|
1177
|
+
function compareRouteSpecificity(a, b) {
|
|
1178
|
+
const aPatternParts = getPatternParts(a.pattern);
|
|
1179
|
+
const bPatternParts = getPatternParts(b.pattern);
|
|
1180
|
+
const aDepth = aPatternParts.length;
|
|
1181
|
+
const bDepth = bPatternParts.length;
|
|
1182
|
+
if (aDepth !== bDepth) {
|
|
1183
|
+
return bDepth - aDepth;
|
|
1184
|
+
}
|
|
1185
|
+
for (let i = 0;i < aPatternParts.length; i++) {
|
|
1186
|
+
const aSpecificity = getPatternPartSpecificity(aPatternParts[i]);
|
|
1187
|
+
const bSpecificity = getPatternPartSpecificity(bPatternParts[i]);
|
|
1188
|
+
if (aSpecificity !== bSpecificity) {
|
|
1189
|
+
return aSpecificity - bSpecificity;
|
|
1190
|
+
}
|
|
1191
|
+
if (aSpecificity === 0 && aPatternParts[i] !== bPatternParts[i]) {
|
|
1192
|
+
return aPatternParts[i].localeCompare(bPatternParts[i]);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
return a.pattern.localeCompare(b.pattern);
|
|
1196
|
+
}
|
|
1197
|
+
function matchCatchAllParam(paramName, patternIndex, patternLength, pathnameParts, pathnameIndex, params) {
|
|
1198
|
+
if (patternIndex !== patternLength - 1 || pathnameIndex >= pathnameParts.length) {
|
|
1199
|
+
return false;
|
|
1200
|
+
}
|
|
1201
|
+
params[paramName.slice(3)] = pathnameParts.slice(pathnameIndex).join("/");
|
|
1202
|
+
return true;
|
|
1203
|
+
}
|
|
1204
|
+
function matchDynamicParam(paramName, pathnameParts, pathnameIndex, params) {
|
|
1205
|
+
const pathnamePart = pathnameParts[pathnameIndex];
|
|
1206
|
+
if (pathnamePart === undefined) {
|
|
1207
|
+
return null;
|
|
1208
|
+
}
|
|
1209
|
+
params[paramName] = pathnamePart;
|
|
1210
|
+
return pathnameIndex + 1;
|
|
1211
|
+
}
|
|
1212
|
+
function matchPatternPart(patternPart, patternIndex, patternLength, pathnameParts, pathnameIndex, params) {
|
|
1213
|
+
if (isDynamicPatternPart(patternPart)) {
|
|
1214
|
+
const paramName = patternPart.slice(1);
|
|
1215
|
+
if (isCatchAllParamName(paramName)) {
|
|
1216
|
+
return matchCatchAllParam(paramName, patternIndex, patternLength, pathnameParts, pathnameIndex, params) ? "catch-all" : null;
|
|
1217
|
+
}
|
|
1218
|
+
return matchDynamicParam(paramName, pathnameParts, pathnameIndex, params);
|
|
1219
|
+
}
|
|
1220
|
+
if (patternPart !== pathnameParts[pathnameIndex]) {
|
|
1221
|
+
return null;
|
|
1222
|
+
}
|
|
1223
|
+
return pathnameIndex + 1;
|
|
1224
|
+
}
|
|
1225
|
+
function matchRoutePattern(pattern, pathname) {
|
|
1226
|
+
const patternParts = getPatternParts(pattern);
|
|
1227
|
+
const pathnameParts = pathname.split("/").filter(Boolean);
|
|
1228
|
+
const params = {};
|
|
1229
|
+
let pathnameIndex = 0;
|
|
1230
|
+
for (let i = 0;i < patternParts.length; i++) {
|
|
1231
|
+
const nextPathnameIndex = matchPatternPart(patternParts[i], i, patternParts.length, pathnameParts, pathnameIndex, params);
|
|
1232
|
+
if (nextPathnameIndex === null) {
|
|
1233
|
+
return null;
|
|
1234
|
+
}
|
|
1235
|
+
if (nextPathnameIndex === "catch-all") {
|
|
1236
|
+
return params;
|
|
1237
|
+
}
|
|
1238
|
+
pathnameIndex = nextPathnameIndex;
|
|
1239
|
+
}
|
|
1240
|
+
return pathnameIndex === pathnameParts.length ? params : null;
|
|
1241
|
+
}
|
|
1242
|
+
function matchRoutes(routes, pathname) {
|
|
1243
|
+
for (const route of routes) {
|
|
1244
|
+
const params = matchRoutePattern(route.pattern, pathname);
|
|
1245
|
+
if (params) {
|
|
1246
|
+
return { route, params };
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
return null;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
// packages/core/src/ssr/lib/content-path.ts
|
|
1253
|
+
var exports_content_path = {};
|
|
1254
|
+
__export(exports_content_path, {
|
|
1255
|
+
resolveContentPathParts: () => resolveContentPathParts
|
|
1256
|
+
});
|
|
1257
|
+
function resolveContentPathParts(pathname) {
|
|
1258
|
+
const pathOnly = pathname.split("?")[0].split("#")[0];
|
|
1259
|
+
const parts = pathOnly.split("/").filter(Boolean);
|
|
1260
|
+
if (parts.length < 2)
|
|
1261
|
+
return null;
|
|
1262
|
+
const g = globalThis;
|
|
1263
|
+
const locales = g.__REROUTE_I18N__?.locales || [];
|
|
1264
|
+
const defaultLocale = g.__REROUTE_I18N__?.defaultLocale || "en-US";
|
|
1265
|
+
const parsed = parseContentPath(pathOnly, locales);
|
|
1266
|
+
if (parsed) {
|
|
1267
|
+
const locale = parsed.locale || defaultLocale;
|
|
1268
|
+
return {
|
|
1269
|
+
collection: parsed.collection,
|
|
1270
|
+
name: parsed.name,
|
|
1271
|
+
locale: parsed.locale,
|
|
1272
|
+
key: contentKey(parsed.collection, parsed.name, locale, defaultLocale),
|
|
1273
|
+
routingPathname: parsed.routingPathname
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
if (parts.length >= 3 && looksLikeLocale(parts[1])) {
|
|
1277
|
+
const locale = parts[1];
|
|
1278
|
+
return {
|
|
1279
|
+
collection: parts[0],
|
|
1280
|
+
name: parts[2],
|
|
1281
|
+
locale,
|
|
1282
|
+
key: contentKey(parts[0], parts[2], locale, defaultLocale),
|
|
1283
|
+
routingPathname: `/${parts[0]}/${parts[2]}`
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
return {
|
|
1287
|
+
collection: parts[0],
|
|
1288
|
+
name: parts[1],
|
|
1289
|
+
key: `${parts[0]}:${parts[1]}`,
|
|
1290
|
+
routingPathname: `/${parts[0]}/${parts[1]}`
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
var init_content_path = __esm(() => {
|
|
1294
|
+
init_pathname();
|
|
1295
|
+
});
|
|
1296
|
+
|
|
793
1297
|
// packages/core/src/ssr/lib/compute/content.ts
|
|
794
1298
|
function checkStatusCache(statusCacheKey, maxAgeMs) {
|
|
795
1299
|
if (maxAgeMs <= 0)
|
|
@@ -842,6 +1346,14 @@ async function handleNonStreamingMode(ssrData, pathname, task, cacheKey, statusC
|
|
|
842
1346
|
}
|
|
843
1347
|
return result;
|
|
844
1348
|
}
|
|
1349
|
+
async function runContentDataTask(streaming, ssrData, pathname, task, set, cacheKey, statusCacheKey, maxAgeMs, pendingTasks) {
|
|
1350
|
+
if (streaming) {
|
|
1351
|
+
handleStreamingMode(ssrData, pathname, task, set, cacheKey, statusCacheKey, maxAgeMs, pendingTasks);
|
|
1352
|
+
} else {
|
|
1353
|
+
await handleNonStreamingMode(ssrData, pathname, task, cacheKey, statusCacheKey, maxAgeMs);
|
|
1354
|
+
}
|
|
1355
|
+
return set.status !== 200 ? set.status : undefined;
|
|
1356
|
+
}
|
|
845
1357
|
async function computeContentData(pathname, options, searchParams, sharedSsrData) {
|
|
846
1358
|
const streaming = options.streaming === true;
|
|
847
1359
|
const ssrData = streaming && sharedSsrData ? sharedSsrData : {};
|
|
@@ -851,18 +1363,20 @@ async function computeContentData(pathname, options, searchParams, sharedSsrData
|
|
|
851
1363
|
const maxAge = options.maxAge || 0;
|
|
852
1364
|
const maxAgeMs = maxAge * 1000;
|
|
853
1365
|
try {
|
|
854
|
-
const
|
|
855
|
-
if (
|
|
1366
|
+
const resolved = resolveContentPathParts(pathname);
|
|
1367
|
+
if (!resolved) {
|
|
856
1368
|
return { data: ssrData, pendingTasks };
|
|
857
1369
|
}
|
|
1370
|
+
const parts = [resolved.collection, resolved.name];
|
|
1371
|
+
if (resolved.locale)
|
|
1372
|
+
parts.splice(1, 0, resolved.locale);
|
|
858
1373
|
const g = globalThis;
|
|
859
|
-
const
|
|
860
|
-
const exp = g.__REROUTE_SSR_EXPORTS__?.[key];
|
|
1374
|
+
const exp = g.__REROUTE_SSR_EXPORTS__?.[resolved.key];
|
|
861
1375
|
const dataFn = exp?.ssr?.data;
|
|
862
1376
|
if (typeof dataFn !== "function") {
|
|
863
1377
|
return { data: ssrData, pendingTasks };
|
|
864
1378
|
}
|
|
865
|
-
const cacheKey = `content:${pathname}:${
|
|
1379
|
+
const cacheKey = `content:${pathname}:${resolved.name}:${resolved.locale || ""}`;
|
|
866
1380
|
const statusCacheKey = `status:${cacheKey}`;
|
|
867
1381
|
const cachedStatus = checkStatusCache(statusCacheKey, maxAgeMs);
|
|
868
1382
|
if (cachedStatus && cachedStatus !== 200) {
|
|
@@ -875,22 +1389,13 @@ async function computeContentData(pathname, options, searchParams, sharedSsrData
|
|
|
875
1389
|
}
|
|
876
1390
|
const set = { status: 200 };
|
|
877
1391
|
const task = createDataTask(dataFn, pathname, parts, searchParams, set, options.headers);
|
|
878
|
-
|
|
879
|
-
handleStreamingMode(ssrData, pathname, task, set, cacheKey, statusCacheKey, maxAgeMs, pendingTasks);
|
|
880
|
-
if (set.status !== 200) {
|
|
881
|
-
statusOverride = set.status;
|
|
882
|
-
}
|
|
883
|
-
} else {
|
|
884
|
-
await handleNonStreamingMode(ssrData, pathname, task, cacheKey, statusCacheKey, maxAgeMs);
|
|
885
|
-
if (set.status !== 200) {
|
|
886
|
-
statusOverride = set.status;
|
|
887
|
-
}
|
|
888
|
-
}
|
|
1392
|
+
statusOverride = await runContentDataTask(streaming, ssrData, pathname, task, set, cacheKey, statusCacheKey, maxAgeMs, pendingTasks) ?? statusOverride;
|
|
889
1393
|
} catch {}
|
|
890
1394
|
return { data: ssrData, error, statusOverride, pendingTasks };
|
|
891
1395
|
}
|
|
892
1396
|
var init_content2 = __esm(() => {
|
|
893
1397
|
init_cache();
|
|
1398
|
+
init_content_path();
|
|
894
1399
|
init_imports();
|
|
895
1400
|
});
|
|
896
1401
|
|
|
@@ -1089,7 +1594,8 @@ async function computeRouteData(pathname, clientDir, _cwd, isWatchMode, options,
|
|
|
1089
1594
|
}).catch(() => {}));
|
|
1090
1595
|
};
|
|
1091
1596
|
try {
|
|
1092
|
-
const
|
|
1597
|
+
const resolved = resolveContentPathParts(pathname);
|
|
1598
|
+
const pathnameOnly = (resolved?.routingPathname || pathname).split("?")[0];
|
|
1093
1599
|
const match = typeof routesModule?.matchRoute === "function" ? routesModule.matchRoute(pathnameOnly) : null;
|
|
1094
1600
|
const route = match?.route;
|
|
1095
1601
|
const params = match?.params || {};
|
|
@@ -1252,44 +1758,18 @@ function handleFlattenedResult(entries, set, ctx, cache, setError, setStatus) {
|
|
|
1252
1758
|
}
|
|
1253
1759
|
var init_routes = __esm(() => {
|
|
1254
1760
|
init_cache();
|
|
1761
|
+
init_content_path();
|
|
1255
1762
|
init_imports();
|
|
1256
1763
|
});
|
|
1257
1764
|
|
|
1258
1765
|
// packages/core/src/ssr/lib/compute/index.ts
|
|
1259
|
-
function matchPatternUtil(pattern, pathname) {
|
|
1260
|
-
const patternParts = pattern.split("/").filter(Boolean);
|
|
1261
|
-
const pathnameParts = pathname.split("/").filter(Boolean);
|
|
1262
|
-
if (patternParts.length !== pathnameParts.length) {
|
|
1263
|
-
return null;
|
|
1264
|
-
}
|
|
1265
|
-
const params = {};
|
|
1266
|
-
for (let i = 0;i < patternParts.length; i++) {
|
|
1267
|
-
const patternPart = patternParts[i];
|
|
1268
|
-
const pathnamePart = pathnameParts[i];
|
|
1269
|
-
if (patternPart.startsWith(":")) {
|
|
1270
|
-
params[patternPart.slice(1)] = pathnamePart;
|
|
1271
|
-
} else if (patternPart !== pathnamePart) {
|
|
1272
|
-
return null;
|
|
1273
|
-
}
|
|
1274
|
-
}
|
|
1275
|
-
return params;
|
|
1276
|
-
}
|
|
1277
1766
|
function createBundledRoutesModule(bundledRoutes, bundledLayouts) {
|
|
1278
1767
|
const bundledNotFoundRoutes = globalThis.__REROUTE_NOT_FOUND_ROUTES__;
|
|
1279
1768
|
return {
|
|
1280
1769
|
routes: bundledRoutes,
|
|
1281
1770
|
layouts: bundledLayouts,
|
|
1282
1771
|
notFoundRoutes: bundledNotFoundRoutes,
|
|
1283
|
-
matchRoute: (pathname) =>
|
|
1284
|
-
for (const route of bundledRoutes) {
|
|
1285
|
-
const pattern = String(route?.pattern || "");
|
|
1286
|
-
const match = matchPatternUtil(pattern, pathname);
|
|
1287
|
-
if (match) {
|
|
1288
|
-
return { route, params: match };
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
return null;
|
|
1292
|
-
}
|
|
1772
|
+
matchRoute: (pathname) => matchRoutes(bundledRoutes, pathname)
|
|
1293
1773
|
};
|
|
1294
1774
|
}
|
|
1295
1775
|
async function loadRoutesModule(cwd, isWatchMode) {
|
|
@@ -1371,33 +1851,31 @@ var init_compute = __esm(() => {
|
|
|
1371
1851
|
});
|
|
1372
1852
|
|
|
1373
1853
|
// packages/core/src/ssr/lib/modules.ts
|
|
1374
|
-
import { readdir as
|
|
1854
|
+
import { readdir as readdir3, stat as stat3 } from "node:fs/promises";
|
|
1375
1855
|
async function importContentModuleForPath(pathname, clientDir, cwd, isWatchMode) {
|
|
1376
1856
|
try {
|
|
1377
|
-
const
|
|
1378
|
-
|
|
1379
|
-
if (parts.length < 2)
|
|
1857
|
+
const resolved = resolveContentPathParts(pathname);
|
|
1858
|
+
if (!resolved)
|
|
1380
1859
|
return null;
|
|
1381
|
-
const collection =
|
|
1382
|
-
const
|
|
1383
|
-
const registryModule = await tryRegistryImport(collection, name, cwd, isWatchMode);
|
|
1860
|
+
const { collection, name, locale } = resolved;
|
|
1861
|
+
const registryModule = await tryRegistryImport(collection, name, cwd, isWatchMode, locale);
|
|
1384
1862
|
if (registryModule)
|
|
1385
1863
|
return registryModule;
|
|
1386
1864
|
const chunkModule = await tryChunkImport(collection, name, cwd, isWatchMode);
|
|
1387
1865
|
if (chunkModule)
|
|
1388
1866
|
return chunkModule;
|
|
1389
|
-
const sourceModule = await trySourceImport(collection, name, clientDir, isWatchMode);
|
|
1867
|
+
const sourceModule = await trySourceImport(collection, name, clientDir, isWatchMode, locale);
|
|
1390
1868
|
if (sourceModule)
|
|
1391
1869
|
return sourceModule;
|
|
1392
1870
|
} catch {}
|
|
1393
1871
|
return null;
|
|
1394
1872
|
}
|
|
1395
|
-
async function tryRegistryImport(collection, name, cwd, isWatchMode) {
|
|
1873
|
+
async function tryRegistryImport(collection, name, cwd, isWatchMode, locale) {
|
|
1396
1874
|
try {
|
|
1397
1875
|
const registryPath = join(cwd, ".reroute", "content.ts");
|
|
1398
1876
|
const reg = await dynamicImport(registryPath, isWatchMode);
|
|
1399
1877
|
const get = reg?.getContentEntry;
|
|
1400
|
-
const entry = typeof get === "function" ? get(collection, name) : undefined;
|
|
1878
|
+
const entry = typeof get === "function" ? get(collection, name, locale) : undefined;
|
|
1401
1879
|
const moduleUrl = entry?.module;
|
|
1402
1880
|
if (!moduleUrl?.endsWith(".js"))
|
|
1403
1881
|
return null;
|
|
@@ -1423,7 +1901,7 @@ async function tryRegistryImport(collection, name, cwd, isWatchMode) {
|
|
|
1423
1901
|
async function tryChunkImport(collection, name, cwd, isWatchMode) {
|
|
1424
1902
|
try {
|
|
1425
1903
|
const chunkDir = join(cwd, ".reroute", "chunks", collection);
|
|
1426
|
-
const files = await
|
|
1904
|
+
const files = await readdir3(chunkDir);
|
|
1427
1905
|
const matches = files.filter((n) => n.startsWith(`${name}.`) && n.endsWith(".js"));
|
|
1428
1906
|
if (!matches.length)
|
|
1429
1907
|
return null;
|
|
@@ -1443,23 +1921,23 @@ async function tryChunkImport(collection, name, cwd, isWatchMode) {
|
|
|
1443
1921
|
} catch {}
|
|
1444
1922
|
return null;
|
|
1445
1923
|
}
|
|
1446
|
-
async function trySourceImport(collection, name, clientDir, isWatchMode) {
|
|
1924
|
+
async function trySourceImport(collection, name, clientDir, isWatchMode, locale) {
|
|
1447
1925
|
try {
|
|
1448
|
-
const
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
if (await Bun.file(srcTsx).exists()) {
|
|
1452
|
-
absSrc = srcTsx;
|
|
1453
|
-
} else if (await Bun.file(srcTs).exists()) {
|
|
1454
|
-
absSrc = srcTs;
|
|
1926
|
+
const candidates = [];
|
|
1927
|
+
if (locale) {
|
|
1928
|
+
candidates.push(join(clientDir, "routes", collection, "content", locale, `${name}.tsx`), join(clientDir, "routes", collection, "content", locale, `${name}.ts`));
|
|
1455
1929
|
}
|
|
1456
|
-
|
|
1457
|
-
|
|
1930
|
+
candidates.push(join(clientDir, "routes", collection, "content", `${name}.tsx`), join(clientDir, "routes", collection, "content", `${name}.ts`));
|
|
1931
|
+
for (const absSrc of candidates) {
|
|
1932
|
+
if (await Bun.file(absSrc).exists()) {
|
|
1933
|
+
return await dynamicImport(absSrc, isWatchMode);
|
|
1934
|
+
}
|
|
1458
1935
|
}
|
|
1459
1936
|
} catch {}
|
|
1460
1937
|
return null;
|
|
1461
1938
|
}
|
|
1462
1939
|
var init_modules = __esm(() => {
|
|
1940
|
+
init_content_path();
|
|
1463
1941
|
init_imports();
|
|
1464
1942
|
});
|
|
1465
1943
|
|
|
@@ -1490,14 +1968,11 @@ function touchModule(key) {
|
|
|
1490
1968
|
}
|
|
1491
1969
|
async function seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode) {
|
|
1492
1970
|
try {
|
|
1493
|
-
const
|
|
1494
|
-
|
|
1495
|
-
if (parts.length < 2) {
|
|
1971
|
+
const resolved = resolveContentPathParts(pathname);
|
|
1972
|
+
if (!resolved) {
|
|
1496
1973
|
return;
|
|
1497
1974
|
}
|
|
1498
|
-
const
|
|
1499
|
-
const name = parts[1];
|
|
1500
|
-
const key = `${collection}:${name}`;
|
|
1975
|
+
const { key } = resolved;
|
|
1501
1976
|
const mod = await importContentModuleForPath(pathname, clientDir, cwd, isWatchMode);
|
|
1502
1977
|
if (!mod) {
|
|
1503
1978
|
return;
|
|
@@ -1517,42 +1992,25 @@ async function seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode) {
|
|
|
1517
1992
|
}
|
|
1518
1993
|
var MAX_SSR_MODULES = 200, moduleAccessOrder;
|
|
1519
1994
|
var init_seed = __esm(() => {
|
|
1995
|
+
init_content_path();
|
|
1520
1996
|
init_modules();
|
|
1521
1997
|
moduleAccessOrder = [];
|
|
1522
1998
|
});
|
|
1523
1999
|
|
|
1524
2000
|
// packages/core/src/ssr/lib/data.ts
|
|
1525
|
-
function matchPattern(pattern, pathname) {
|
|
1526
|
-
const patternParts = pattern.split("/").filter(Boolean);
|
|
1527
|
-
const pathnameParts = pathname.split("/").filter(Boolean);
|
|
1528
|
-
if (patternParts.length !== pathnameParts.length) {
|
|
1529
|
-
return null;
|
|
1530
|
-
}
|
|
1531
|
-
const params = {};
|
|
1532
|
-
for (let i = 0;i < patternParts.length; i++) {
|
|
1533
|
-
const patternPart = patternParts[i];
|
|
1534
|
-
const pathnamePart = pathnameParts[i];
|
|
1535
|
-
if (patternPart.startsWith(":")) {
|
|
1536
|
-
params[patternPart.slice(1)] = pathnamePart;
|
|
1537
|
-
} else if (patternPart !== pathnamePart) {
|
|
1538
|
-
return null;
|
|
1539
|
-
}
|
|
1540
|
-
}
|
|
1541
|
-
return params;
|
|
1542
|
-
}
|
|
1543
2001
|
function loadContentData(pathname, searchParams) {
|
|
1544
2002
|
try {
|
|
1545
|
-
const
|
|
1546
|
-
if (
|
|
2003
|
+
const resolved = resolveContentPathParts(pathname);
|
|
2004
|
+
if (!resolved)
|
|
1547
2005
|
return null;
|
|
1548
|
-
const key =
|
|
2006
|
+
const key = resolved.key;
|
|
1549
2007
|
const g = globalThis;
|
|
1550
2008
|
const exp = g.__REROUTE_SSR_EXPORTS__?.[key];
|
|
1551
2009
|
const dataFn = exp?.ssr?.data;
|
|
1552
2010
|
if (typeof dataFn === "function") {
|
|
1553
2011
|
const rawResult = dataFn({
|
|
1554
2012
|
pathname,
|
|
1555
|
-
params: { name:
|
|
2013
|
+
params: { name: resolved.name },
|
|
1556
2014
|
searchParams
|
|
1557
2015
|
});
|
|
1558
2016
|
const result = processDataResult(rawResult, pathname, pathname);
|
|
@@ -1574,16 +2032,7 @@ async function loadRouteDataInternal(pathname, clientDir, cwd, isWatchMode, sear
|
|
|
1574
2032
|
routes = m?.routes;
|
|
1575
2033
|
matchRouteFn = m?.matchRoute;
|
|
1576
2034
|
} else {
|
|
1577
|
-
matchRouteFn = (pathname2) =>
|
|
1578
|
-
for (const route of routes || []) {
|
|
1579
|
-
const pattern = String(route?.pattern || "");
|
|
1580
|
-
const match2 = matchPattern(pattern, pathname2);
|
|
1581
|
-
if (match2) {
|
|
1582
|
-
return { route, params: match2 };
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
|
-
return null;
|
|
1586
|
-
};
|
|
2035
|
+
matchRouteFn = (pathname2) => matchRoutes(routes || [], pathname2);
|
|
1587
2036
|
}
|
|
1588
2037
|
const pathnameOnly = pathname.split("?")[0];
|
|
1589
2038
|
const match = typeof matchRouteFn === "function" ? matchRouteFn(pathnameOnly) : null;
|
|
@@ -1724,6 +2173,7 @@ function createLazyMarker(pathname, key) {
|
|
|
1724
2173
|
};
|
|
1725
2174
|
}
|
|
1726
2175
|
var init_data = __esm(() => {
|
|
2176
|
+
init_content_path();
|
|
1727
2177
|
init_imports();
|
|
1728
2178
|
init_seed();
|
|
1729
2179
|
});
|
|
@@ -1924,18 +2374,53 @@ function replaceAppRoot(html, appHtml, appId) {
|
|
|
1924
2374
|
var init_html = () => {};
|
|
1925
2375
|
|
|
1926
2376
|
// packages/core/src/og/discovery.ts
|
|
2377
|
+
import { readdir as readdir4 } from "node:fs/promises";
|
|
1927
2378
|
import { pathToFileURL as pathToFileURL4 } from "node:url";
|
|
2379
|
+
function isCatchAllRouteDirectory(name) {
|
|
2380
|
+
return CATCH_ALL_ROUTE_DIRECTORY.test(name);
|
|
2381
|
+
}
|
|
2382
|
+
async function listDynamicRouteDirectories(baseDir) {
|
|
2383
|
+
try {
|
|
2384
|
+
const entries = await readdir4(baseDir, { withFileTypes: true });
|
|
2385
|
+
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => DYNAMIC_ROUTE_DIRECTORY.test(name)).sort((a, b) => {
|
|
2386
|
+
const aIsCatchAll = isCatchAllRouteDirectory(a);
|
|
2387
|
+
const bIsCatchAll = isCatchAllRouteDirectory(b);
|
|
2388
|
+
if (aIsCatchAll !== bIsCatchAll) {
|
|
2389
|
+
return Number(aIsCatchAll) - Number(bIsCatchAll);
|
|
2390
|
+
}
|
|
2391
|
+
return a.localeCompare(b);
|
|
2392
|
+
});
|
|
2393
|
+
} catch {
|
|
2394
|
+
return [];
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
async function collectOGCandidatePaths(currentDir, parts, depth, pathsToTry, allowPartialFallback) {
|
|
2398
|
+
if (depth === parts.length) {
|
|
2399
|
+
pathsToTry.push(join(currentDir, "[og].tsx"));
|
|
2400
|
+
return;
|
|
2401
|
+
}
|
|
2402
|
+
const literalDir = join(currentDir, parts[depth]);
|
|
2403
|
+
try {
|
|
2404
|
+
await readdir4(literalDir);
|
|
2405
|
+
await collectOGCandidatePaths(literalDir, parts, depth + 1, pathsToTry, true);
|
|
2406
|
+
} catch {}
|
|
2407
|
+
const dynamicDirs = await listDynamicRouteDirectories(currentDir);
|
|
2408
|
+
for (const dynamicDir of dynamicDirs) {
|
|
2409
|
+
if (isCatchAllRouteDirectory(dynamicDir)) {
|
|
2410
|
+
pathsToTry.push(join(currentDir, dynamicDir, "[og].tsx"));
|
|
2411
|
+
continue;
|
|
2412
|
+
}
|
|
2413
|
+
await collectOGCandidatePaths(join(currentDir, dynamicDir), parts, depth + 1, pathsToTry, false);
|
|
2414
|
+
}
|
|
2415
|
+
if (allowPartialFallback) {
|
|
2416
|
+
pathsToTry.push(join(currentDir, "[og].tsx"));
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
1928
2419
|
async function findOGImageForPath(pathname, clientDir) {
|
|
1929
2420
|
const parts = pathname.split("/").filter(Boolean).filter((p) => !p.startsWith("__reroute"));
|
|
1930
2421
|
const routesDir = join(clientDir, "routes");
|
|
1931
2422
|
const pathsToTry = [];
|
|
1932
|
-
|
|
1933
|
-
for (let i = parts.length;i > 0; i--) {
|
|
1934
|
-
const dirPath = join(routesDir, ...parts.slice(0, i), "[og].tsx");
|
|
1935
|
-
pathsToTry.push(dirPath);
|
|
1936
|
-
}
|
|
1937
|
-
}
|
|
1938
|
-
pathsToTry.push(join(routesDir, "[og].tsx"));
|
|
2423
|
+
await collectOGCandidatePaths(routesDir, parts, 0, pathsToTry, true);
|
|
1939
2424
|
const uniquePaths = [...new Set(pathsToTry)];
|
|
1940
2425
|
for (const path of uniquePaths) {
|
|
1941
2426
|
try {
|
|
@@ -1959,28 +2444,28 @@ async function loadOGImageComponent(ogPath, isWatchMode) {
|
|
|
1959
2444
|
function extractParamsFromPath(pathname, ogPath, clientDir) {
|
|
1960
2445
|
const params = {};
|
|
1961
2446
|
const ogDir = ogPath.replace(/\/\[og\]\.tsx$/, "");
|
|
1962
|
-
const
|
|
1963
|
-
const relativePath = ogDir.replace(
|
|
2447
|
+
const routesDir = join(clientDir, "routes");
|
|
2448
|
+
const relativePath = ogDir.replace(routesDir, "").split("/").filter(Boolean);
|
|
1964
2449
|
const pathnameParts = pathname.split("/").filter(Boolean);
|
|
1965
2450
|
for (let i = 0;i < relativePath.length && i < pathnameParts.length; i++) {
|
|
1966
2451
|
const part = relativePath[i];
|
|
1967
|
-
const
|
|
1968
|
-
if (
|
|
1969
|
-
|
|
1970
|
-
|
|
2452
|
+
const catchAllMatch = part.match(/^\[\.\.\.([^\]]+)\]$/);
|
|
2453
|
+
if (catchAllMatch) {
|
|
2454
|
+
params[catchAllMatch[1]] = pathnameParts.slice(i).join("/");
|
|
2455
|
+
break;
|
|
1971
2456
|
}
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
const match = lastRelativePart.match(/^\[([^\]]+)\]$/);
|
|
1976
|
-
if (match) {
|
|
1977
|
-
const paramName = match[1];
|
|
1978
|
-
params[paramName] = pathnameParts[relativePath.length - 1];
|
|
2457
|
+
const dynamicMatch = part.match(/^\[([^\]]+)\]$/);
|
|
2458
|
+
if (dynamicMatch) {
|
|
2459
|
+
params[dynamicMatch[1]] = pathnameParts[i];
|
|
1979
2460
|
}
|
|
1980
2461
|
}
|
|
1981
2462
|
return params;
|
|
1982
2463
|
}
|
|
1983
|
-
var
|
|
2464
|
+
var CATCH_ALL_ROUTE_DIRECTORY, DYNAMIC_ROUTE_DIRECTORY;
|
|
2465
|
+
var init_discovery2 = __esm(() => {
|
|
2466
|
+
CATCH_ALL_ROUTE_DIRECTORY = /^\[\.\.\.([^\]]+)\]$/;
|
|
2467
|
+
DYNAMIC_ROUTE_DIRECTORY = /^\[(?:\.\.\.)?[^\]]+\]$/;
|
|
2468
|
+
});
|
|
1984
2469
|
|
|
1985
2470
|
// packages/core/src/og/meta.ts
|
|
1986
2471
|
async function generateOGImageMetaTags(pathname, clientDir, ogConfig) {
|
|
@@ -2071,7 +2556,9 @@ async function extractPageMetadata(pathname, clientDir, cwd, isWatchMode, curren
|
|
|
2071
2556
|
let perPageHead = "";
|
|
2072
2557
|
let pageLang;
|
|
2073
2558
|
let statusOverride = currentStatusOverride;
|
|
2074
|
-
|
|
2559
|
+
const resolved = resolveContentPathParts(pathname);
|
|
2560
|
+
const routingPathname = resolved?.routingPathname || pathname;
|
|
2561
|
+
await extractLayoutMetadata(routingPathname, clientDir, cwd, isWatchMode, (head) => {
|
|
2075
2562
|
perPageHead += head;
|
|
2076
2563
|
}, (lang) => {
|
|
2077
2564
|
if (!pageLang)
|
|
@@ -2106,8 +2593,8 @@ ${ogMetaTags}`;
|
|
|
2106
2593
|
perPageHead += head;
|
|
2107
2594
|
}, (lang) => {
|
|
2108
2595
|
pageLang = lang;
|
|
2109
|
-
}, ogConfig, titleSuffix);
|
|
2110
|
-
const routeResult = await extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, statusOverride, ssrData, ogConfig, titleSuffix);
|
|
2596
|
+
}, ogConfig, titleSuffix, baseUrl);
|
|
2597
|
+
const routeResult = await extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, statusOverride, ssrData, ogConfig, titleSuffix, routingPathname);
|
|
2111
2598
|
perPageHead += routeResult.head;
|
|
2112
2599
|
if (routeResult.lang)
|
|
2113
2600
|
pageLang = routeResult.lang;
|
|
@@ -2147,14 +2634,42 @@ async function extractLayoutMetadata(pathname, clientDir, cwd, isWatchMode, addH
|
|
|
2147
2634
|
}
|
|
2148
2635
|
} catch {}
|
|
2149
2636
|
}
|
|
2150
|
-
function
|
|
2637
|
+
function resolveContentLocales(collection, name, fallbackLocales) {
|
|
2638
|
+
const g = globalThis;
|
|
2639
|
+
const byCollection = g.__REROUTE_COLLECTIONS__;
|
|
2640
|
+
const items = byCollection?.[collection] || [];
|
|
2641
|
+
const localesForEntry = [
|
|
2642
|
+
...new Set(items.filter((it) => it.name === name && it.locale).map((it) => String(it.locale)))
|
|
2643
|
+
];
|
|
2644
|
+
return localesForEntry.length > 0 ? localesForEntry : fallbackLocales;
|
|
2645
|
+
}
|
|
2646
|
+
function addContentI18nHead(addHead, baseUrl, collection, name, locales, defaultLocale, activeLocale) {
|
|
2647
|
+
if (locales.length > 1) {
|
|
2648
|
+
addHead(`
|
|
2649
|
+
${hreflangTags(baseUrl, collection, name, locales, defaultLocale)}`);
|
|
2650
|
+
}
|
|
2651
|
+
addHead(`
|
|
2652
|
+
<meta property="og:locale" content="${toOgLocale(activeLocale)}" />`);
|
|
2653
|
+
for (const loc of locales) {
|
|
2654
|
+
if (loc === activeLocale)
|
|
2655
|
+
continue;
|
|
2656
|
+
addHead(`
|
|
2657
|
+
<meta property="og:locale:alternate" content="${toOgLocale(loc)}" />`);
|
|
2658
|
+
}
|
|
2659
|
+
const canonicalPath = localizeContentHref(collection, name, activeLocale, defaultLocale);
|
|
2660
|
+
const base = baseUrl.replace(/\/$/, "");
|
|
2661
|
+
addHead(`
|
|
2662
|
+
<link rel="canonical" href="${base}${canonicalPath}" />`);
|
|
2663
|
+
addHead(`
|
|
2664
|
+
<meta property="og:url" content="${base}${canonicalPath}" />`);
|
|
2665
|
+
}
|
|
2666
|
+
function extractContentMetadata(pathname, addHead, setLang, ogConfig, titleSuffix, baseUrl) {
|
|
2151
2667
|
try {
|
|
2152
|
-
const
|
|
2153
|
-
if (
|
|
2668
|
+
const resolved = resolveContentPathParts(pathname);
|
|
2669
|
+
if (!resolved)
|
|
2154
2670
|
return;
|
|
2155
|
-
const key = `${parts[0]}:${parts[1]}`;
|
|
2156
2671
|
const g = globalThis;
|
|
2157
|
-
const exp = g.__REROUTE_SSR_EXPORTS__?.[key];
|
|
2672
|
+
const exp = g.__REROUTE_SSR_EXPORTS__?.[resolved.key];
|
|
2158
2673
|
const meta = exp?.meta;
|
|
2159
2674
|
const ssr = exp?.ssr;
|
|
2160
2675
|
addHead(buildHeadFromMeta(meta, ogConfig, titleSuffix));
|
|
@@ -2165,15 +2680,20 @@ ${ssrHead}`);
|
|
|
2165
2680
|
const lang = extractSSRLang(ssr);
|
|
2166
2681
|
if (lang)
|
|
2167
2682
|
setLang(lang);
|
|
2683
|
+
const i18n = g.__REROUTE_I18N__;
|
|
2684
|
+
if (i18n?.enabled && baseUrl && i18n.locales && i18n.locales.length > 1) {
|
|
2685
|
+
const locales = resolveContentLocales(resolved.collection, resolved.name, i18n.locales);
|
|
2686
|
+
addContentI18nHead(addHead, baseUrl, resolved.collection, resolved.name, locales, i18n.defaultLocale || "en-US", i18n.locale || i18n.defaultLocale || "en-US");
|
|
2687
|
+
}
|
|
2168
2688
|
} catch {}
|
|
2169
2689
|
}
|
|
2170
2690
|
function getContentMetaFromExports(pathname) {
|
|
2171
2691
|
try {
|
|
2172
|
-
const
|
|
2173
|
-
if (
|
|
2692
|
+
const resolved = resolveContentPathParts(pathname);
|
|
2693
|
+
if (!resolved)
|
|
2174
2694
|
return;
|
|
2175
|
-
const slug =
|
|
2176
|
-
const key =
|
|
2695
|
+
const slug = resolved.name;
|
|
2696
|
+
const key = resolved.key;
|
|
2177
2697
|
const g = globalThis;
|
|
2178
2698
|
const exp = g.__REROUTE_SSR_EXPORTS__?.[key];
|
|
2179
2699
|
const meta = exp?.meta;
|
|
@@ -2187,9 +2707,10 @@ function getContentMetaFromExports(pathname) {
|
|
|
2187
2707
|
return;
|
|
2188
2708
|
}
|
|
2189
2709
|
}
|
|
2190
|
-
async function extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode, statusOverride, ssrData, ogConfig, titleSuffix) {
|
|
2710
|
+
async function extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode, statusOverride, ssrData, ogConfig, titleSuffix, routingPathname) {
|
|
2191
2711
|
const pathnameOnly = pathname.split("?")[0];
|
|
2192
|
-
const
|
|
2712
|
+
const matchPath = (routingPathname || pathname).split("?")[0];
|
|
2713
|
+
const match = typeof m.matchRoute === "function" ? m.matchRoute(matchPath) : null;
|
|
2193
2714
|
const r = match?.route;
|
|
2194
2715
|
if (!r) {
|
|
2195
2716
|
return { head: "", statusOverride: statusOverride || 404 };
|
|
@@ -2229,7 +2750,7 @@ ${ssrHead}`;
|
|
|
2229
2750
|
}
|
|
2230
2751
|
return { head: "", statusOverride };
|
|
2231
2752
|
}
|
|
2232
|
-
async function extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, currentStatusOverride, ssrData, ogConfig, titleSuffix) {
|
|
2753
|
+
async function extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, currentStatusOverride, ssrData, ogConfig, titleSuffix, routingPathname) {
|
|
2233
2754
|
let head = "";
|
|
2234
2755
|
let lang;
|
|
2235
2756
|
let statusOverride = currentStatusOverride;
|
|
@@ -2239,14 +2760,14 @@ async function extractRouteMetadata(pathname, clientDir, cwd, isWatchMode, curre
|
|
|
2239
2760
|
if (!m) {
|
|
2240
2761
|
return { head, lang, statusOverride: statusOverride || 404 };
|
|
2241
2762
|
}
|
|
2242
|
-
const
|
|
2243
|
-
const match = typeof m.matchRoute === "function" ? m.matchRoute(
|
|
2763
|
+
const matchPath = (routingPathname || pathname).split("?")[0];
|
|
2764
|
+
const match = typeof m.matchRoute === "function" ? m.matchRoute(matchPath) : null;
|
|
2244
2765
|
const r = match?.route;
|
|
2245
2766
|
if (!r) {
|
|
2246
2767
|
statusOverride = statusOverride || 404;
|
|
2247
2768
|
}
|
|
2248
2769
|
if (r && typeof r.path === "string") {
|
|
2249
|
-
const result = await extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode, statusOverride, ssrData, ogConfig, titleSuffix);
|
|
2770
|
+
const result = await extractMatchedRouteMetadata(pathname, clientDir, m, isWatchMode, statusOverride, ssrData, ogConfig, titleSuffix, routingPathname);
|
|
2250
2771
|
head = result.head;
|
|
2251
2772
|
lang = result.lang;
|
|
2252
2773
|
statusOverride = result.statusOverride;
|
|
@@ -2421,34 +2942,34 @@ function applyTitleSuffixToHead(headContent, titleSuffix) {
|
|
|
2421
2942
|
}
|
|
2422
2943
|
var init_metadata2 = __esm(() => {
|
|
2423
2944
|
init_metadata();
|
|
2945
|
+
init_pathname();
|
|
2424
2946
|
init_meta();
|
|
2425
2947
|
init_compute();
|
|
2948
|
+
init_content_path();
|
|
2426
2949
|
init_imports();
|
|
2427
2950
|
});
|
|
2428
2951
|
|
|
2429
2952
|
// packages/core/src/ssr/lib/preload.ts
|
|
2430
|
-
import { readdir as
|
|
2953
|
+
import { readdir as readdir5, stat as stat4 } from "node:fs/promises";
|
|
2431
2954
|
async function preloadContentModule(pathname, clientDir, cwd, isWatchMode) {
|
|
2432
2955
|
let extraHead = "";
|
|
2433
2956
|
let hydrationScript = "";
|
|
2434
2957
|
let statusOverride;
|
|
2435
2958
|
try {
|
|
2436
|
-
const
|
|
2437
|
-
const
|
|
2438
|
-
if (
|
|
2959
|
+
const { resolveContentPathParts: resolveContentPathParts2 } = await Promise.resolve().then(() => (init_content_path(), exports_content_path));
|
|
2960
|
+
const resolved = resolveContentPathParts2(pathname);
|
|
2961
|
+
if (!resolved) {
|
|
2439
2962
|
return { extraHead, hydrationScript };
|
|
2440
2963
|
}
|
|
2441
|
-
const collection =
|
|
2442
|
-
const name = parts[1];
|
|
2964
|
+
const { collection, name, key, locale } = resolved;
|
|
2443
2965
|
if (!await isContentCollection(clientDir, collection)) {
|
|
2444
2966
|
return { extraHead, hydrationScript };
|
|
2445
2967
|
}
|
|
2446
|
-
const modulePath = await findContentModulePath(collection, name, clientDir, cwd, isWatchMode);
|
|
2968
|
+
const modulePath = await findContentModulePath(collection, name, clientDir, cwd, isWatchMode, locale);
|
|
2447
2969
|
if (!modulePath) {
|
|
2448
2970
|
statusOverride = 404;
|
|
2449
2971
|
return { extraHead, hydrationScript, statusOverride };
|
|
2450
2972
|
}
|
|
2451
|
-
const key = `${collection}:${name}`;
|
|
2452
2973
|
extraHead += `
|
|
2453
2974
|
<link rel="modulepreload" href="${modulePath}" />`;
|
|
2454
2975
|
hydrationScript += `<script>
|
|
@@ -2490,12 +3011,12 @@ async function findLatestCandidate(chunkDir, candidates) {
|
|
|
2490
3011
|
}
|
|
2491
3012
|
return latest;
|
|
2492
3013
|
}
|
|
2493
|
-
async function findContentModulePath(collection, name, clientDir, cwd, isWatchMode) {
|
|
3014
|
+
async function findContentModulePath(collection, name, clientDir, cwd, isWatchMode, locale) {
|
|
2494
3015
|
try {
|
|
2495
3016
|
const registryPath = join(cwd, ".reroute", "content.ts");
|
|
2496
3017
|
const reg = await dynamicImport(registryPath, isWatchMode);
|
|
2497
3018
|
const get = reg?.getContentEntry;
|
|
2498
|
-
const entry = typeof get === "function" ? get(collection, name) : undefined;
|
|
3019
|
+
const entry = typeof get === "function" ? get(collection, name, locale) : undefined;
|
|
2499
3020
|
const moduleUrl = entry?.module;
|
|
2500
3021
|
if (moduleUrl?.endsWith(".js")) {
|
|
2501
3022
|
return moduleUrl;
|
|
@@ -2503,7 +3024,7 @@ async function findContentModulePath(collection, name, clientDir, cwd, isWatchMo
|
|
|
2503
3024
|
} catch {}
|
|
2504
3025
|
try {
|
|
2505
3026
|
const chunkDir = join(cwd, ".reroute", "chunks", collection);
|
|
2506
|
-
const files = await
|
|
3027
|
+
const files = await readdir5(chunkDir);
|
|
2507
3028
|
const candidates = files.filter((n) => n.startsWith(`${name}.`) && n.endsWith(".js"));
|
|
2508
3029
|
if (candidates.length) {
|
|
2509
3030
|
const latest = await findLatestCandidate(chunkDir, candidates);
|
|
@@ -2511,13 +3032,18 @@ async function findContentModulePath(collection, name, clientDir, cwd, isWatchMo
|
|
|
2511
3032
|
}
|
|
2512
3033
|
} catch {}
|
|
2513
3034
|
try {
|
|
2514
|
-
const
|
|
2515
|
-
const
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
3035
|
+
const contentRoot = join(clientDir, "routes", collection, "content");
|
|
3036
|
+
const candidates = locale ? [
|
|
3037
|
+
join(contentRoot, locale, `${name}.tsx`),
|
|
3038
|
+
join(contentRoot, locale, `${name}.ts`),
|
|
3039
|
+
join(contentRoot, `${name}.tsx`),
|
|
3040
|
+
join(contentRoot, `${name}.ts`)
|
|
3041
|
+
] : [join(contentRoot, `${name}.tsx`), join(contentRoot, `${name}.ts`)];
|
|
3042
|
+
for (const abs of candidates) {
|
|
3043
|
+
if (await Bun.file(abs).exists()) {
|
|
3044
|
+
const rel = abs.startsWith(clientDir) ? abs.slice(clientDir.length).replace(/^[/\\]/, "") : join("routes", collection, "content", `${name}.tsx`);
|
|
3045
|
+
return `/${rel.replace(/\\+/g, "/")}`;
|
|
3046
|
+
}
|
|
2521
3047
|
}
|
|
2522
3048
|
} catch {}
|
|
2523
3049
|
return null;
|
|
@@ -2711,11 +3237,18 @@ function duplicateQueryParamData(ssrData) {
|
|
|
2711
3237
|
return duplicated;
|
|
2712
3238
|
}
|
|
2713
3239
|
function getContentKeyFromPathname(pathname) {
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
3240
|
+
return resolveContentPathParts(pathname)?.key ?? null;
|
|
3241
|
+
}
|
|
3242
|
+
function createI18nScript(i18n) {
|
|
3243
|
+
if (!i18n?.enabled)
|
|
3244
|
+
return "";
|
|
3245
|
+
try {
|
|
3246
|
+
const json = escapeJsonForScript(JSON.stringify(i18n));
|
|
3247
|
+
return `<script>(function(){try{var w=(typeof window!=='undefined'?window:globalThis);w.__REROUTE_I18N__=${json};}catch(e){}})();</script>`;
|
|
3248
|
+
} catch (error) {
|
|
3249
|
+
console.error("[reroute] Failed to serialize i18n hydration:", error);
|
|
3250
|
+
return "";
|
|
3251
|
+
}
|
|
2719
3252
|
}
|
|
2720
3253
|
function createContentCaptureScript() {
|
|
2721
3254
|
return `<script>(function(){try{var w=window;w.__REROUTE_INITIAL_HYDRATION__=true;var h={};document.querySelectorAll('[data-reroute-key]').forEach(function(el){var k=el.getAttribute('data-reroute-key');if(k)h[k]=el.innerHTML;});w.__REROUTE_CONTENT_HTML__=h;var r=document.querySelector('[data-reroute-route="ssr"]');if(r)w.__REROUTE_ROUTE_HTML__=r.innerHTML;}catch(e){}})();</script>`;
|
|
@@ -2791,13 +3324,14 @@ function createSSRPathnameScript(pathname) {
|
|
|
2791
3324
|
return "";
|
|
2792
3325
|
}
|
|
2793
3326
|
}
|
|
2794
|
-
function createDataScript(ssrData, errorMsg, pathname, browserTelemetryConfig, traceContext, titleSuffix) {
|
|
3327
|
+
function createDataScript(ssrData, errorMsg, pathname, browserTelemetryConfig, traceContext, titleSuffix, i18n) {
|
|
2795
3328
|
let script = "";
|
|
2796
3329
|
script += createContentCaptureScript();
|
|
2797
3330
|
script += createSSRPathnameScript(pathname);
|
|
2798
3331
|
if (pathname) {
|
|
2799
3332
|
script += createSSRExportsScript(pathname);
|
|
2800
3333
|
}
|
|
3334
|
+
script += createI18nScript(i18n);
|
|
2801
3335
|
script += createTelemetryConfigScript(browserTelemetryConfig);
|
|
2802
3336
|
script += createTraceContextScript(traceContext);
|
|
2803
3337
|
script += createTitleSuffixScript(titleSuffix);
|
|
@@ -2817,7 +3351,9 @@ function createDataScript(ssrData, errorMsg, pathname, browserTelemetryConfig, t
|
|
|
2817
3351
|
}
|
|
2818
3352
|
return script;
|
|
2819
3353
|
}
|
|
2820
|
-
var init_data2 = () => {
|
|
3354
|
+
var init_data2 = __esm(() => {
|
|
3355
|
+
init_content_path();
|
|
3356
|
+
});
|
|
2821
3357
|
|
|
2822
3358
|
// packages/core/src/ssr/lib/scripts/feeds.ts
|
|
2823
3359
|
function createFeedsScript() {
|
|
@@ -3045,10 +3581,10 @@ function generateCollectionScripts(byCollectionForSSR) {
|
|
|
3045
3581
|
} catch {}
|
|
3046
3582
|
return "";
|
|
3047
3583
|
}
|
|
3048
|
-
function generateHydrationScripts(ssrData, isWatchMode, ssrError, collectionScripts = "", preloadScript = "", bundleUrl = "", pathname = "", browserTelemetryConfig, traceContext, titleSuffix) {
|
|
3584
|
+
function generateHydrationScripts(ssrData, isWatchMode, ssrError, collectionScripts = "", preloadScript = "", bundleUrl = "", pathname = "", browserTelemetryConfig, traceContext, titleSuffix, i18n) {
|
|
3049
3585
|
let scripts = preloadScript;
|
|
3050
3586
|
scripts += collectionScripts;
|
|
3051
|
-
scripts += createDataScript(ssrData, isWatchMode ? ssrError : undefined, pathname, browserTelemetryConfig, traceContext, titleSuffix);
|
|
3587
|
+
scripts += createDataScript(ssrData, isWatchMode ? ssrError : undefined, pathname, browserTelemetryConfig, traceContext, titleSuffix, i18n);
|
|
3052
3588
|
scripts += createFeedsScript();
|
|
3053
3589
|
scripts += createLlmsScript();
|
|
3054
3590
|
if (bundleUrl) {
|
|
@@ -3211,7 +3747,7 @@ async function renderSSRDocument(options) {
|
|
|
3211
3747
|
const browserTelemetryConfig = serializeBrowserTelemetryConfig2(browserTelemetryConfigRaw);
|
|
3212
3748
|
const traceContext = getTraceContextForInjection(options.parentSpan);
|
|
3213
3749
|
const hydrationScript = await withSpan("ssr.generate.scripts", async (span) => {
|
|
3214
|
-
const script = generateHydrationScripts(setup2.ssrData, isWatchMode, setup2.ssrError, collectionScripts, setup2.preloadHydrationScript, bundleUrl, pathname, browserTelemetryConfig, traceContext, options.titleSuffix);
|
|
3750
|
+
const script = generateHydrationScripts(setup2.ssrData, isWatchMode, setup2.ssrError, collectionScripts, setup2.preloadHydrationScript, bundleUrl, pathname, browserTelemetryConfig, traceContext, options.titleSuffix, options.i18n);
|
|
3215
3751
|
span.setAttribute("reroute.scripts.size", script.length);
|
|
3216
3752
|
return script;
|
|
3217
3753
|
});
|
|
@@ -3229,12 +3765,13 @@ async function renderSSRDocument(options) {
|
|
|
3229
3765
|
dedent(setup2.metadataResult.perPageHead)
|
|
3230
3766
|
].filter(Boolean).join(`
|
|
3231
3767
|
`));
|
|
3768
|
+
const i18nLocale = options.i18n?.enabled ? String(options.i18n.locale || "") : "";
|
|
3232
3769
|
const html2 = withSpanSync("ssr.apply.template", (span) => {
|
|
3233
3770
|
const result = applyIndexTemplate(baseTemplate, appHtml, {
|
|
3234
3771
|
head: [setup2.inlineStyleTag, combinedHead].filter(Boolean).join(`
|
|
3235
3772
|
`),
|
|
3236
3773
|
hydrationScript,
|
|
3237
|
-
lang: setup2.metadataResult.pageLang || lang,
|
|
3774
|
+
lang: setup2.metadataResult.pageLang || i18nLocale || lang,
|
|
3238
3775
|
appId
|
|
3239
3776
|
});
|
|
3240
3777
|
span.setAttributes({
|
|
@@ -4412,6 +4949,55 @@ async function discoverRoutes(cwd, isWatchMode) {
|
|
|
4412
4949
|
}
|
|
4413
4950
|
return { staticRoutes, dynamicRoutes };
|
|
4414
4951
|
}
|
|
4952
|
+
function groupNamedCollectionItems(items) {
|
|
4953
|
+
const byName = new Map;
|
|
4954
|
+
for (const item of items) {
|
|
4955
|
+
const name = String(item.name || "");
|
|
4956
|
+
if (!name)
|
|
4957
|
+
continue;
|
|
4958
|
+
const list = byName.get(name) || [];
|
|
4959
|
+
list.push(item);
|
|
4960
|
+
byName.set(name, list);
|
|
4961
|
+
}
|
|
4962
|
+
return byName;
|
|
4963
|
+
}
|
|
4964
|
+
function resolveItemHref(collection, item, defaultLocale, localize) {
|
|
4965
|
+
const name = String(item.name || "");
|
|
4966
|
+
const locale = item.locale || defaultLocale;
|
|
4967
|
+
if (name)
|
|
4968
|
+
return localize(collection, name, locale, defaultLocale);
|
|
4969
|
+
return String(item.href || "");
|
|
4970
|
+
}
|
|
4971
|
+
function buildNamedCollectionSitemapEntries(collection, name, variants, defaultLocale, base, localize) {
|
|
4972
|
+
const locales = [
|
|
4973
|
+
...new Set(variants.map((v) => v.locale || defaultLocale).filter(Boolean))
|
|
4974
|
+
];
|
|
4975
|
+
const alternates = locales.length > 1 ? [
|
|
4976
|
+
...locales.map((locale) => ({
|
|
4977
|
+
hreflang: locale,
|
|
4978
|
+
href: `${base}${localize(collection, name, locale, defaultLocale)}`
|
|
4979
|
+
})),
|
|
4980
|
+
{
|
|
4981
|
+
hreflang: "x-default",
|
|
4982
|
+
href: `${base}${localize(collection, name, defaultLocale, defaultLocale)}`
|
|
4983
|
+
}
|
|
4984
|
+
] : undefined;
|
|
4985
|
+
const entries = [];
|
|
4986
|
+
for (const item of variants) {
|
|
4987
|
+
const href = resolveItemHref(collection, item, defaultLocale, localize);
|
|
4988
|
+
if (!href)
|
|
4989
|
+
continue;
|
|
4990
|
+
const meta = item.meta || {};
|
|
4991
|
+
entries.push({
|
|
4992
|
+
loc: `${base}${href}`,
|
|
4993
|
+
lastmod: meta.date ? new Date(meta.date).toISOString() : undefined,
|
|
4994
|
+
changefreq: "weekly",
|
|
4995
|
+
priority: 0.7,
|
|
4996
|
+
alternates
|
|
4997
|
+
});
|
|
4998
|
+
}
|
|
4999
|
+
return entries;
|
|
5000
|
+
}
|
|
4415
5001
|
async function discoverCollectionContent(cwd, collection, isWatchMode, baseUrl) {
|
|
4416
5002
|
const entries = [];
|
|
4417
5003
|
try {
|
|
@@ -4423,18 +5009,26 @@ async function discoverCollectionContent(cwd, collection, isWatchMode, baseUrl)
|
|
|
4423
5009
|
const url = `${Bun.pathToFileURL(collectionFile).href}${isWatchMode ? `?t=${Date.now()}` : ""}`;
|
|
4424
5010
|
const mod = await import(url);
|
|
4425
5011
|
const items = mod.items || [];
|
|
5012
|
+
const defaultLocale = mod.defaultLocale || "en-US";
|
|
5013
|
+
const { localizeContentHref: localizeContentHref2 } = await Promise.resolve().then(() => (init_pathname(), exports_pathname));
|
|
5014
|
+
const base = baseUrl.replace(/\/$/, "");
|
|
5015
|
+
const byName = groupNamedCollectionItems(items);
|
|
5016
|
+
for (const [name, variants] of byName) {
|
|
5017
|
+
entries.push(...buildNamedCollectionSitemapEntries(collection, name, variants, defaultLocale, base, localizeContentHref2));
|
|
5018
|
+
}
|
|
4426
5019
|
for (const item of items) {
|
|
5020
|
+
if (item.name)
|
|
5021
|
+
continue;
|
|
4427
5022
|
const href = String(item.href || "");
|
|
5023
|
+
if (!href)
|
|
5024
|
+
continue;
|
|
4428
5025
|
const meta = item.meta || {};
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
};
|
|
4436
|
-
entries.push(entry);
|
|
4437
|
-
}
|
|
5026
|
+
entries.push({
|
|
5027
|
+
loc: `${base}${href}`,
|
|
5028
|
+
lastmod: meta.date ? new Date(meta.date).toISOString() : undefined,
|
|
5029
|
+
changefreq: "weekly",
|
|
5030
|
+
priority: 0.7
|
|
5031
|
+
});
|
|
4438
5032
|
}
|
|
4439
5033
|
} catch (error) {
|
|
4440
5034
|
console.error(`[reroute] Failed to discover collection ${collection}:`, error);
|
|
@@ -4729,11 +5323,17 @@ async function discoverCollectionFeedItems(cwd, collection, isWatchMode, baseUrl
|
|
|
4729
5323
|
const url = `${Bun.pathToFileURL(collectionFile).href}${isWatchMode ? `?t=${Date.now()}` : ""}`;
|
|
4730
5324
|
const mod = await import(url);
|
|
4731
5325
|
const contentItems = mod.items || [];
|
|
5326
|
+
const defaultLocale = mod.defaultLocale || "en-US";
|
|
5327
|
+
const { localizeContentHref: localizeContentHref2 } = await Promise.resolve().then(() => (init_pathname(), exports_pathname));
|
|
4732
5328
|
for (const item of contentItems) {
|
|
4733
|
-
const
|
|
5329
|
+
const name = String(item.name || "");
|
|
5330
|
+
const locale = item.locale || defaultLocale;
|
|
5331
|
+
const href = name ? localizeContentHref2(collection, name, locale, defaultLocale) : String(item.href || "");
|
|
4734
5332
|
const meta = item.meta || {};
|
|
4735
5333
|
if (href) {
|
|
4736
|
-
|
|
5334
|
+
const rssItem = createRSSItemFromMetaAndHref(href, meta, baseUrl, item, rssConfig);
|
|
5335
|
+
rssItem.locale = locale;
|
|
5336
|
+
items.push(rssItem);
|
|
4737
5337
|
}
|
|
4738
5338
|
}
|
|
4739
5339
|
} catch (error) {
|
|
@@ -4999,7 +5599,7 @@ function generateRSSXML(feed, options = {}) {
|
|
|
4999
5599
|
<link>${escapeXml(feed.link)}</link>
|
|
5000
5600
|
<description>${escapeXml(feed.description)}</description>
|
|
5001
5601
|
<lastBuildDate>${lastBuildDate}</lastBuildDate>
|
|
5002
|
-
<language
|
|
5602
|
+
<language>${escapeXml(feed.language || "en")}</language>
|
|
5003
5603
|
<atom:link href="${escapeXml(feed.link)}" rel="self" type="application/rss+xml" />
|
|
5004
5604
|
${itemsXML}
|
|
5005
5605
|
</channel>
|
|
@@ -5161,6 +5761,7 @@ async function generateSitemap(discovery4, baseUrl, options = {}) {
|
|
|
5161
5761
|
return createSingleSitemap(allEntries);
|
|
5162
5762
|
}
|
|
5163
5763
|
function generateSitemapXML(entries) {
|
|
5764
|
+
const hasAlternates = entries.some((e) => e.alternates && e.alternates.length > 0);
|
|
5164
5765
|
const urlsetEntries = entries.map((entry) => {
|
|
5165
5766
|
let xml = ` <url>
|
|
5166
5767
|
<loc>${escapeXml2(entry.loc)}</loc>`;
|
|
@@ -5176,13 +5777,20 @@ function generateSitemapXML(entries) {
|
|
|
5176
5777
|
xml += `
|
|
5177
5778
|
<priority>${entry.priority.toFixed(1)}</priority>`;
|
|
5178
5779
|
}
|
|
5780
|
+
if (entry.alternates?.length) {
|
|
5781
|
+
for (const alt of entry.alternates) {
|
|
5782
|
+
xml += `
|
|
5783
|
+
<xhtml:link rel="alternate" hreflang="${escapeXml2(alt.hreflang)}" href="${escapeXml2(alt.href)}" />`;
|
|
5784
|
+
}
|
|
5785
|
+
}
|
|
5179
5786
|
xml += `
|
|
5180
5787
|
</url>`;
|
|
5181
5788
|
return xml;
|
|
5182
5789
|
}).join(`
|
|
5183
5790
|
`);
|
|
5791
|
+
const xhtmlNs = hasAlternates ? ' xmlns:xhtml="http://www.w3.org/1999/xhtml"' : "";
|
|
5184
5792
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
5185
|
-
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
5793
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"${xhtmlNs}>
|
|
5186
5794
|
${urlsetEntries}
|
|
5187
5795
|
</urlset>`;
|
|
5188
5796
|
}
|
|
@@ -5280,7 +5888,8 @@ async function renderSSRDocumentStream(options) {
|
|
|
5280
5888
|
...parts
|
|
5281
5889
|
};
|
|
5282
5890
|
});
|
|
5283
|
-
const
|
|
5891
|
+
const i18nLocale = options.i18n?.enabled ? String(options.i18n.locale || "") : "";
|
|
5892
|
+
const pageLang = setup2.metadataResult.pageLang || i18nLocale || lang;
|
|
5284
5893
|
let headWithLang = htmlHead.replace(/<html([^>]*)>/i, (_m, attrs) => {
|
|
5285
5894
|
const hasLang = /(^|\s)lang\s*=/.test(attrs);
|
|
5286
5895
|
const newAttrs = hasLang ? attrs.replace(/lang\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/i, `lang="${pageLang}"`) : `${attrs} lang="${pageLang}"`;
|
|
@@ -5323,7 +5932,8 @@ async function renderSSRDocumentStream(options) {
|
|
|
5323
5932
|
parentSpan: options.parentSpan,
|
|
5324
5933
|
timeout: options.timeout,
|
|
5325
5934
|
ssrExport: setup2.metadataResult.ssrExport,
|
|
5326
|
-
titleSuffix: options.titleSuffix
|
|
5935
|
+
titleSuffix: options.titleSuffix,
|
|
5936
|
+
i18n: options.i18n
|
|
5327
5937
|
});
|
|
5328
5938
|
if (debug)
|
|
5329
5939
|
console.log(`[renderStream] ${pathname} - returning stream: ${(performance.now() - t0).toFixed(2)}ms`);
|
|
@@ -5436,7 +6046,7 @@ function buildStreamingScripts(ctx) {
|
|
|
5436
6046
|
ssrDataSnapshot[key] = value;
|
|
5437
6047
|
}
|
|
5438
6048
|
}
|
|
5439
|
-
const dataScript = createDataScript(ssrDataSnapshot, ctx.isWatchMode ? ctx.ssrError : undefined, ctx.pathname, ctx.browserTelemetryConfig, ctx.traceContext, ctx.titleSuffix);
|
|
6049
|
+
const dataScript = createDataScript(ssrDataSnapshot, ctx.isWatchMode ? ctx.ssrError : undefined, ctx.pathname, ctx.browserTelemetryConfig, ctx.traceContext, ctx.titleSuffix, ctx.i18n);
|
|
5440
6050
|
const feedsScript = createFeedsScript();
|
|
5441
6051
|
const llmsScript = createLlmsScript();
|
|
5442
6052
|
let allScripts = dataScript + feedsScript + llmsScript + collectionScripts + ctx.preloadHydrationScript;
|
|
@@ -5568,6 +6178,7 @@ var init_src = __esm(() => {
|
|
|
5568
6178
|
init_bundler();
|
|
5569
6179
|
init_config();
|
|
5570
6180
|
init_content();
|
|
6181
|
+
init_i18n();
|
|
5571
6182
|
init_llms();
|
|
5572
6183
|
init_og();
|
|
5573
6184
|
init_robots();
|
|
@@ -5584,6 +6195,7 @@ init_core();
|
|
|
5584
6195
|
|
|
5585
6196
|
export {
|
|
5586
6197
|
toPromise,
|
|
6198
|
+
toOgLocale,
|
|
5587
6199
|
toBytes,
|
|
5588
6200
|
stripStart,
|
|
5589
6201
|
stripHtmlTags,
|
|
@@ -5595,6 +6207,7 @@ export {
|
|
|
5595
6207
|
setGlobalSSRData,
|
|
5596
6208
|
setGlobalCollections,
|
|
5597
6209
|
seedSSRModuleForPath,
|
|
6210
|
+
resolveLocale,
|
|
5598
6211
|
resetSSRAccessTracking,
|
|
5599
6212
|
renderSSRDocumentStream,
|
|
5600
6213
|
renderSSRDocument,
|
|
@@ -5603,7 +6216,17 @@ export {
|
|
|
5603
6216
|
processCollections,
|
|
5604
6217
|
preloadContentModule,
|
|
5605
6218
|
performSSRSetup,
|
|
6219
|
+
parseCookieValue,
|
|
6220
|
+
parseContentPath,
|
|
6221
|
+
normalizePathname,
|
|
6222
|
+
negotiateLocale,
|
|
5606
6223
|
mergeLayoutData,
|
|
6224
|
+
matchRoutes,
|
|
6225
|
+
matchRoutePattern,
|
|
6226
|
+
lookupMessage,
|
|
6227
|
+
looksLikeLocale,
|
|
6228
|
+
localizeHref,
|
|
6229
|
+
localizeContentHref,
|
|
5607
6230
|
loadRoutesModule,
|
|
5608
6231
|
loadOGImageComponent,
|
|
5609
6232
|
loadIndexHtml,
|
|
@@ -5616,11 +6239,13 @@ export {
|
|
|
5616
6239
|
inlineTailwindCSS,
|
|
5617
6240
|
importContentModuleForPath,
|
|
5618
6241
|
htmlToMarkdown,
|
|
6242
|
+
hreflangTags,
|
|
5619
6243
|
gzipIfAccepted,
|
|
5620
6244
|
getSitemapExcludedRoutes,
|
|
5621
6245
|
getRedirectSourcePaths,
|
|
5622
6246
|
getPatternDepth,
|
|
5623
6247
|
getMimeType,
|
|
6248
|
+
getMessage,
|
|
5624
6249
|
getMatchingLayouts,
|
|
5625
6250
|
getContentMeta,
|
|
5626
6251
|
generateSitemapXML,
|
|
@@ -5637,6 +6262,7 @@ export {
|
|
|
5637
6262
|
generateContentHash,
|
|
5638
6263
|
generateCollectionScripts,
|
|
5639
6264
|
generateAtomXML,
|
|
6265
|
+
formatMessage,
|
|
5640
6266
|
formatAsText,
|
|
5641
6267
|
formatAsMarkdown,
|
|
5642
6268
|
findOGImageForPath,
|
|
@@ -5656,10 +6282,12 @@ export {
|
|
|
5656
6282
|
discoverRoutes,
|
|
5657
6283
|
discoverRobotsData,
|
|
5658
6284
|
discoverRSSData,
|
|
6285
|
+
discoverI18n,
|
|
5659
6286
|
discoverCollections,
|
|
5660
6287
|
discoverCollectionContent,
|
|
5661
6288
|
defineConfig,
|
|
5662
6289
|
deduplicateMetaTags,
|
|
6290
|
+
createTranslator,
|
|
5663
6291
|
createLlmsScript,
|
|
5664
6292
|
createLayoutDataKey,
|
|
5665
6293
|
createLayoutCacheKey,
|
|
@@ -5667,13 +6295,17 @@ export {
|
|
|
5667
6295
|
createDataScript,
|
|
5668
6296
|
createCollectionScript,
|
|
5669
6297
|
createBundlePreload,
|
|
6298
|
+
contentNegotiateRedirect,
|
|
6299
|
+
contentKey,
|
|
5670
6300
|
computeSSRDataForPath,
|
|
5671
6301
|
computeSSRData,
|
|
5672
6302
|
computeRouteData,
|
|
5673
6303
|
computeLayoutData,
|
|
5674
6304
|
computeContentData,
|
|
5675
6305
|
compressStreamIfAccepted,
|
|
6306
|
+
compareRouteSpecificity,
|
|
5676
6307
|
cleanupPathScopedSSRData,
|
|
6308
|
+
buildLocaleCookie,
|
|
5677
6309
|
buildHeadFromMeta,
|
|
5678
6310
|
blockSearchCrawlers,
|
|
5679
6311
|
blockAITrainingCrawlers,
|
|
@@ -5689,7 +6321,10 @@ export {
|
|
|
5689
6321
|
SEARCH_CRAWLERS,
|
|
5690
6322
|
LRUCache,
|
|
5691
6323
|
DefaultOGTemplate,
|
|
6324
|
+
DEFAULT_LOCALES_DIR,
|
|
6325
|
+
DEFAULT_LOCALE,
|
|
6326
|
+
DEFAULT_COOKIE,
|
|
5692
6327
|
AI_CRAWLERS
|
|
5693
6328
|
};
|
|
5694
6329
|
|
|
5695
|
-
//# debugId=
|
|
6330
|
+
//# debugId=C4F445FA1614E66D64756E2164756E21
|