@sebbro/paraglide-lite 0.1.0 → 0.1.2
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/bundler-plugins/per-locale-build/index.js +5 -3
- package/dist/bundler-plugins/per-locale-build/index.js.map +1 -1
- package/dist/bundler-plugins/per-locale-build/vite-environments.js +12 -7
- package/dist/bundler-plugins/per-locale-build/vite-environments.js.map +1 -1
- package/dist/bundler-plugins/plugin-core.d.ts +38 -2
- package/dist/bundler-plugins/plugin-core.js +198 -11
- package/dist/bundler-plugins/plugin-core.js.map +1 -1
- package/dist/bundler-plugins/rolldown.test.js +15 -6
- package/dist/bundler-plugins/rolldown.test.js.map +1 -1
- package/dist/bundler-plugins/unplugin.js +5 -0
- package/dist/bundler-plugins/unplugin.js.map +1 -1
- package/dist/bundler-plugins/unplugin.test.js +67 -0
- package/dist/bundler-plugins/unplugin.test.js.map +1 -1
- package/dist/bundler-plugins/virtual-modules.test.js +64 -1
- package/dist/bundler-plugins/virtual-modules.test.js.map +1 -1
- package/dist/cli/commands/compile/command.js +8 -1
- package/dist/cli/commands/compile/command.js.map +1 -1
- package/dist/cli/commands/compile/command.test.js +51 -0
- package/dist/cli/commands/compile/command.test.js.map +1 -1
- package/dist/compiler/compile-annotation.d.ts +2 -2
- package/dist/compiler/compile-annotation.js +9 -9
- package/dist/compiler/compile-annotation.js.map +1 -1
- package/dist/compiler/compile-local-variable.d.ts +2 -1
- package/dist/compiler/compile-local-variable.js +4 -4
- package/dist/compiler/compile-local-variable.js.map +1 -1
- package/dist/compiler/compile-local-variable.test.js +82 -0
- package/dist/compiler/compile-local-variable.test.js.map +1 -1
- package/dist/compiler/compile-message.js +10 -2
- package/dist/compiler/compile-message.js.map +1 -1
- package/dist/compiler/compile-message.test.js +132 -2
- package/dist/compiler/compile-message.test.js.map +1 -1
- package/dist/compiler/compile-pattern.js +4 -2
- package/dist/compiler/compile-pattern.js.map +1 -1
- package/dist/compiler/compile-pattern.test.js +31 -0
- package/dist/compiler/compile-pattern.test.js.map +1 -1
- package/dist/compiler/compile.bench.js +1 -1
- package/dist/compiler/compile.bench.js.map +1 -1
- package/dist/compiler/compile.test.js +14 -0
- package/dist/compiler/compile.test.js.map +1 -1
- package/dist/compiler/compiler-options.d.ts +9 -1
- package/dist/compiler/compiler-options.js.map +1 -1
- package/dist/compiler/emit-message-dts.d.ts +18 -0
- package/dist/compiler/emit-message-dts.js +166 -0
- package/dist/compiler/emit-message-dts.js.map +1 -0
- package/dist/compiler/emit-message-dts.test.d.ts +1 -0
- package/dist/compiler/emit-message-dts.test.js +283 -0
- package/dist/compiler/emit-message-dts.test.js.map +1 -0
- package/dist/compiler/runtime/create-runtime.d.ts +1 -0
- package/dist/compiler/runtime/create-runtime.js +11 -0
- package/dist/compiler/runtime/create-runtime.js.map +1 -1
- package/dist/compiler/runtime/exec-url-pattern.d.ts +9 -0
- package/dist/compiler/runtime/exec-url-pattern.js +31 -0
- package/dist/compiler/runtime/exec-url-pattern.js.map +1 -0
- package/dist/compiler/runtime/extract-locale-from-url.js +9 -4
- package/dist/compiler/runtime/extract-locale-from-url.js.map +1 -1
- package/dist/compiler/runtime/generate-static-localized-urls.js +13 -6
- package/dist/compiler/runtime/generate-static-localized-urls.js.map +1 -1
- package/dist/compiler/runtime/generate-static-localized-urls.test.js +38 -0
- package/dist/compiler/runtime/generate-static-localized-urls.test.js.map +1 -1
- package/dist/compiler/runtime/host-routing.d.ts +3 -3
- package/dist/compiler/runtime/host-routing.js +2 -2
- package/dist/compiler/runtime/host-routing.js.map +1 -1
- package/dist/compiler/runtime/host-routing.test.js +79 -0
- package/dist/compiler/runtime/host-routing.test.js.map +1 -1
- package/dist/compiler/runtime/localize-href.bench.d.ts +1 -0
- package/dist/compiler/runtime/localize-href.bench.js +68 -0
- package/dist/compiler/runtime/localize-href.bench.js.map +1 -0
- package/dist/compiler/runtime/localize-href.test.js +35 -0
- package/dist/compiler/runtime/localize-href.test.js.map +1 -1
- package/dist/compiler/runtime/localize-url.d.ts +14 -0
- package/dist/compiler/runtime/localize-url.js +338 -19
- package/dist/compiler/runtime/localize-url.js.map +1 -1
- package/dist/compiler/runtime/localize-url.test.js +139 -0
- package/dist/compiler/runtime/localize-url.test.js.map +1 -1
- package/dist/compiler/runtime/normalize-trailing-slash.d.ts +10 -0
- package/dist/compiler/runtime/normalize-trailing-slash.js +23 -0
- package/dist/compiler/runtime/normalize-trailing-slash.js.map +1 -0
- package/dist/compiler/runtime/route-strategy.js +4 -2
- package/dist/compiler/runtime/route-strategy.js.map +1 -1
- package/dist/compiler/runtime/should-redirect.js +4 -1
- package/dist/compiler/runtime/should-redirect.js.map +1 -1
- package/dist/compiler/runtime/should-redirect.test.js +26 -2
- package/dist/compiler/runtime/should-redirect.test.js.map +1 -1
- package/dist/compiler/runtime/type.d.ts +1 -0
- package/dist/compiler/runtime/type.js.map +1 -1
- package/dist/compiler/runtime/url-pattern.d.ts +11 -0
- package/dist/compiler/runtime/url-pattern.js +39 -1
- package/dist/compiler/runtime/url-pattern.js.map +1 -1
- package/dist/compiler/runtime/variables.d.ts +9 -3
- package/dist/compiler/runtime/variables.js +7 -1
- package/dist/compiler/runtime/variables.js.map +1 -1
- package/dist/compiler/server/create-server-file.js +18 -4
- package/dist/compiler/server/create-server-file.js.map +1 -1
- package/dist/compiler/server/create-server-file.test.js +76 -0
- package/dist/compiler/server/create-server-file.test.js.map +1 -1
- package/dist/compiler/server/middleware.js +6 -2
- package/dist/compiler/server/middleware.js.map +1 -1
- package/dist/compiler/server/middleware.test.js +30 -0
- package/dist/compiler/server/middleware.test.js.map +1 -1
- package/dist/compiler/strip-jsdoc.d.ts +9 -0
- package/dist/compiler/strip-jsdoc.js +19 -0
- package/dist/compiler/strip-jsdoc.js.map +1 -0
- package/dist/compiler/strip-jsdoc.test.d.ts +1 -0
- package/dist/compiler/strip-jsdoc.test.js +95 -0
- package/dist/compiler/strip-jsdoc.test.js.map +1 -0
- package/dist/compiler/variable-access.d.ts +2 -0
- package/dist/compiler/variable-access.js +6 -0
- package/dist/compiler/variable-access.js.map +1 -1
- package/dist/index.test.d.ts +1 -0
- package/dist/index.test.js +9 -0
- package/dist/index.test.js.map +1 -0
- package/dist/messages/load-messages.js +4 -5
- package/dist/messages/load-messages.js.map +1 -1
- package/dist/services/env-variables/index.js +1 -1
- package/dist/services/env-variables/index.js.map +1 -1
- package/dist/services/file-handling/write-output.bench.d.ts +1 -0
- package/dist/services/file-handling/write-output.bench.js +24 -0
- package/dist/services/file-handling/write-output.bench.js.map +1 -0
- package/dist/services/file-handling/write-output.d.ts +5 -0
- package/dist/services/file-handling/write-output.js +54 -9
- package/dist/services/file-handling/write-output.js.map +1 -1
- package/dist/services/file-handling/write-output.test.js +27 -0
- package/dist/services/file-handling/write-output.test.js.map +1 -1
- package/dist/services/logger/index.js +2 -0
- package/dist/services/logger/index.js.map +1 -1
- package/package.json +86 -86
|
@@ -2,9 +2,11 @@ import { extractLocaleFromUrl } from "./extract-locale-from-url.js";
|
|
|
2
2
|
import { getLocale } from "./get-locale.js";
|
|
3
3
|
import { getUrlOrigin } from "./get-url-origin.js";
|
|
4
4
|
import { assertIsLocale, toLocale } from "./check-locale.js";
|
|
5
|
-
import {
|
|
5
|
+
import { getUrlPattern } from "./url-pattern.js";
|
|
6
6
|
import { deLocalizeUrlHostRouting, localizeUrlHostRouting, } from "./host-routing.js";
|
|
7
|
-
import { baseLocale, TREE_SHAKE_DEFAULT_URL_PATTERN_USED, TREE_SHAKE_HOST_ROUTING_USED, urlPatterns, } from "./variables.js";
|
|
7
|
+
import { baseLocale, TREE_SHAKE_DEFAULT_URL_PATTERN_USED, TREE_SHAKE_HOST_ROUTING_USED, trailingSlash, urlPatterns, } from "./variables.js";
|
|
8
|
+
import { normalizeTrailingSlash } from "./normalize-trailing-slash.js";
|
|
9
|
+
import { execUrlPattern } from "./exec-url-pattern.js";
|
|
8
10
|
/**
|
|
9
11
|
* Lower-level URL localization function, primarily used in server contexts.
|
|
10
12
|
*
|
|
@@ -60,12 +62,24 @@ export function localizeUrl(url, options) {
|
|
|
60
62
|
if (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {
|
|
61
63
|
return localizeUrlDefaultPattern(url, targetLocale);
|
|
62
64
|
}
|
|
63
|
-
const
|
|
65
|
+
const originalUrl = typeof url === "string" ? new URL(url) : url;
|
|
66
|
+
const urlObj = trailingSlash === undefined
|
|
67
|
+
? originalUrl
|
|
68
|
+
: normalizeTrailingSlash(new URL(originalUrl));
|
|
64
69
|
// Iterate over URL patterns
|
|
65
70
|
for (const element of urlPatterns) {
|
|
71
|
+
// Most applications use a locale prefix (and sometimes a fixed domain)
|
|
72
|
+
// with a trailing catch-all path. Those routes do not need URLPattern's
|
|
73
|
+
// parser or matcher on every call. Keep the generic matcher below as the
|
|
74
|
+
// fallback for every other URLPattern shape. This stays inside the outer
|
|
75
|
+
// loop so specific patterns retain precedence over a later catch-all.
|
|
76
|
+
const fastPathLocalized = localizeUrlFastPath(urlObj, targetLocale, element);
|
|
77
|
+
if (fastPathLocalized !== undefined) {
|
|
78
|
+
return fastPathLocalized;
|
|
79
|
+
}
|
|
66
80
|
// match localized patterns
|
|
67
81
|
for (const [, localizedPattern] of element.localized) {
|
|
68
|
-
const match =
|
|
82
|
+
const match = execUrlPattern(getUrlPattern(localizedPattern, urlObj), urlObj);
|
|
69
83
|
if (!match) {
|
|
70
84
|
continue;
|
|
71
85
|
}
|
|
@@ -74,19 +88,19 @@ export function localizeUrl(url, options) {
|
|
|
74
88
|
continue;
|
|
75
89
|
}
|
|
76
90
|
const localizedUrl = fillPattern(targetPattern, aggregateGroups(match), urlObj.origin);
|
|
77
|
-
return fillMissingUrlParts(localizedUrl, match);
|
|
91
|
+
return normalizeTrailingSlash(fillMissingUrlParts(localizedUrl, match));
|
|
78
92
|
}
|
|
79
|
-
const unlocalizedMatch =
|
|
93
|
+
const unlocalizedMatch = execUrlPattern(getUrlPattern(element.pattern, urlObj), urlObj);
|
|
80
94
|
if (unlocalizedMatch) {
|
|
81
95
|
const targetPattern = element.localized.find(([locale]) => locale === targetLocale)?.[1];
|
|
82
96
|
if (targetPattern) {
|
|
83
97
|
const localizedUrl = fillPattern(targetPattern, aggregateGroups(unlocalizedMatch), urlObj.origin);
|
|
84
|
-
return fillMissingUrlParts(localizedUrl, unlocalizedMatch);
|
|
98
|
+
return normalizeTrailingSlash(fillMissingUrlParts(localizedUrl, unlocalizedMatch));
|
|
85
99
|
}
|
|
86
100
|
}
|
|
87
101
|
}
|
|
88
102
|
// If no match found, return the original URL
|
|
89
|
-
return
|
|
103
|
+
return originalUrl;
|
|
90
104
|
}
|
|
91
105
|
/**
|
|
92
106
|
* https://github.com/opral/inlang-paraglide-js/issues/381
|
|
@@ -96,11 +110,11 @@ export function localizeUrl(url, options) {
|
|
|
96
110
|
* @returns {URL}
|
|
97
111
|
*/
|
|
98
112
|
function localizeUrlDefaultPattern(url, locale) {
|
|
99
|
-
const urlObj = typeof url === "string" ? new URL(url, getUrlOrigin()) : new URL(url);
|
|
113
|
+
const urlObj = normalizeTrailingSlash(typeof url === "string" ? new URL(url, getUrlOrigin()) : new URL(url));
|
|
100
114
|
const currentLocale = extractLocaleFromUrl(urlObj);
|
|
101
115
|
// If current locale matches target locale, no change needed
|
|
102
116
|
if (currentLocale === locale) {
|
|
103
|
-
return urlObj;
|
|
117
|
+
return normalizeTrailingSlash(urlObj);
|
|
104
118
|
}
|
|
105
119
|
const pathSegments = urlObj.pathname.split("/").filter(Boolean);
|
|
106
120
|
// If current path starts with a locale, remove it
|
|
@@ -115,7 +129,7 @@ function localizeUrlDefaultPattern(url, locale) {
|
|
|
115
129
|
// For other locales, add prefix
|
|
116
130
|
urlObj.pathname = "/" + locale + "/" + pathSegments.join("/");
|
|
117
131
|
}
|
|
118
|
-
return urlObj;
|
|
132
|
+
return normalizeTrailingSlash(urlObj);
|
|
119
133
|
}
|
|
120
134
|
/**
|
|
121
135
|
* Low-level URL de-localization function, primarily used in server contexts.
|
|
@@ -164,28 +178,35 @@ export function deLocalizeUrl(url) {
|
|
|
164
178
|
if (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {
|
|
165
179
|
return deLocalizeUrlDefaultPattern(url);
|
|
166
180
|
}
|
|
167
|
-
const
|
|
181
|
+
const originalUrl = typeof url === "string" ? new URL(url) : url;
|
|
182
|
+
const urlObj = trailingSlash === undefined
|
|
183
|
+
? originalUrl
|
|
184
|
+
: normalizeTrailingSlash(new URL(originalUrl));
|
|
168
185
|
// Iterate over URL patterns
|
|
169
186
|
for (const element of urlPatterns) {
|
|
187
|
+
const fastPathDeLocalized = deLocalizeUrlFastPath(urlObj, element);
|
|
188
|
+
if (fastPathDeLocalized !== undefined) {
|
|
189
|
+
return fastPathDeLocalized;
|
|
190
|
+
}
|
|
170
191
|
// Iterate over localized versions
|
|
171
192
|
for (const [, localizedPattern] of element.localized) {
|
|
172
|
-
const match =
|
|
193
|
+
const match = execUrlPattern(getUrlPattern(localizedPattern, urlObj), urlObj);
|
|
173
194
|
if (match) {
|
|
174
195
|
// Convert localized URL back to the base pattern
|
|
175
196
|
const groups = aggregateGroups(match);
|
|
176
197
|
const baseUrl = fillPattern(element.pattern, groups, urlObj.origin);
|
|
177
|
-
return fillMissingUrlParts(baseUrl, match);
|
|
198
|
+
return normalizeTrailingSlash(fillMissingUrlParts(baseUrl, match));
|
|
178
199
|
}
|
|
179
200
|
}
|
|
180
201
|
// match unlocalized pattern
|
|
181
|
-
const unlocalizedMatch =
|
|
202
|
+
const unlocalizedMatch = execUrlPattern(getUrlPattern(element.pattern, urlObj), urlObj);
|
|
182
203
|
if (unlocalizedMatch) {
|
|
183
204
|
const baseUrl = fillPattern(element.pattern, aggregateGroups(unlocalizedMatch), urlObj.origin);
|
|
184
|
-
return fillMissingUrlParts(baseUrl, unlocalizedMatch);
|
|
205
|
+
return normalizeTrailingSlash(fillMissingUrlParts(baseUrl, unlocalizedMatch));
|
|
185
206
|
}
|
|
186
207
|
}
|
|
187
208
|
// no match found return the original url
|
|
188
|
-
return
|
|
209
|
+
return originalUrl;
|
|
189
210
|
}
|
|
190
211
|
/**
|
|
191
212
|
* De-localizes a URL using the default pattern (/:locale/*)
|
|
@@ -193,13 +214,13 @@ export function deLocalizeUrl(url) {
|
|
|
193
214
|
* @returns {URL}
|
|
194
215
|
*/
|
|
195
216
|
function deLocalizeUrlDefaultPattern(url) {
|
|
196
|
-
const urlObj = typeof url === "string" ? new URL(url, getUrlOrigin()) : new URL(url);
|
|
217
|
+
const urlObj = normalizeTrailingSlash(typeof url === "string" ? new URL(url, getUrlOrigin()) : new URL(url));
|
|
197
218
|
const pathSegments = urlObj.pathname.split("/").filter(Boolean);
|
|
198
219
|
// If first segment is a locale, remove it
|
|
199
220
|
if (pathSegments.length > 0 && toLocale(pathSegments[0])) {
|
|
200
221
|
urlObj.pathname = "/" + pathSegments.slice(1).join("/");
|
|
201
222
|
}
|
|
202
|
-
return urlObj;
|
|
223
|
+
return normalizeTrailingSlash(urlObj);
|
|
203
224
|
}
|
|
204
225
|
/**
|
|
205
226
|
* Takes matches of implicit wildcards in the UrlPattern (when a part is missing
|
|
@@ -324,4 +345,302 @@ export function aggregateGroups(match) {
|
|
|
324
345
|
...match.username.groups,
|
|
325
346
|
};
|
|
326
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* A small, deliberately conservative subset of URLPattern routing.
|
|
350
|
+
*
|
|
351
|
+
* The compiler emits routes such as `/:path(.*)?`, `/de/:path*`, or
|
|
352
|
+
* `https://example.com/:path*`. For those routes matching is equivalent to a
|
|
353
|
+
* pathname prefix check and (optionally) an origin check. Everything that has
|
|
354
|
+
* a dynamic host, a custom path regexp, or another URLPattern modifier keeps
|
|
355
|
+
* using the generic implementation above.
|
|
356
|
+
*
|
|
357
|
+
* @typedef {{
|
|
358
|
+
* protocol: string | undefined;
|
|
359
|
+
* hostname: string | undefined;
|
|
360
|
+
* port: string | undefined;
|
|
361
|
+
* pathnamePrefix: string;
|
|
362
|
+
* pathMode: "segments" | "catch-all-optional" | "catch-all-required";
|
|
363
|
+
* }} FastPathPattern
|
|
364
|
+
* @typedef {{
|
|
365
|
+
* base: FastPathPattern;
|
|
366
|
+
* localized: Array<{ locale: string; pattern: FastPathPattern }>;
|
|
367
|
+
* }} FastPathRoute
|
|
368
|
+
*/
|
|
369
|
+
/** @type {WeakMap<object, FastPathRoute | null>} */
|
|
370
|
+
const fastPathRouteCache = new WeakMap();
|
|
371
|
+
/**
|
|
372
|
+
* @param {URL} urlObj
|
|
373
|
+
* @param {string} targetLocale
|
|
374
|
+
* @param {{ pattern: string; localized: Array<[string, string]> }} element
|
|
375
|
+
* @returns {URL | undefined}
|
|
376
|
+
*/
|
|
377
|
+
function localizeUrlFastPath(urlObj, targetLocale, element) {
|
|
378
|
+
const route = getFastPathRoute(element);
|
|
379
|
+
if (route === null)
|
|
380
|
+
return undefined;
|
|
381
|
+
// Preserve URLPattern's ordering: localized patterns are checked before
|
|
382
|
+
// the unlocalized pattern, and the first matching pattern wins.
|
|
383
|
+
for (const localized of route.localized) {
|
|
384
|
+
const suffix = matchFastPathPattern(localized.pattern, urlObj);
|
|
385
|
+
if (suffix === undefined)
|
|
386
|
+
continue;
|
|
387
|
+
const target = route.localized.find((candidate) => candidate.locale === targetLocale)?.pattern;
|
|
388
|
+
if (target === undefined)
|
|
389
|
+
continue;
|
|
390
|
+
return applyFastPathPattern(target, suffix, urlObj);
|
|
391
|
+
}
|
|
392
|
+
const suffix = matchFastPathPattern(route.base, urlObj);
|
|
393
|
+
if (suffix !== undefined) {
|
|
394
|
+
const target = route.localized.find((candidate) => candidate.locale === targetLocale)?.pattern;
|
|
395
|
+
if (target !== undefined) {
|
|
396
|
+
return applyFastPathPattern(target, suffix, urlObj);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return undefined;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* @param {URL} urlObj
|
|
403
|
+
* @param {{ pattern: string; localized: Array<[string, string]> }} element
|
|
404
|
+
* @returns {URL | undefined}
|
|
405
|
+
*/
|
|
406
|
+
function deLocalizeUrlFastPath(urlObj, element) {
|
|
407
|
+
const route = getFastPathRoute(element);
|
|
408
|
+
if (route === null)
|
|
409
|
+
return undefined;
|
|
410
|
+
for (const localized of route.localized) {
|
|
411
|
+
const suffix = matchFastPathPattern(localized.pattern, urlObj);
|
|
412
|
+
if (suffix !== undefined) {
|
|
413
|
+
return applyFastPathPattern(route.base, suffix, urlObj);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
const suffix = matchFastPathPattern(route.base, urlObj);
|
|
417
|
+
if (suffix !== undefined) {
|
|
418
|
+
return applyFastPathPattern(route.base, suffix, urlObj);
|
|
419
|
+
}
|
|
420
|
+
return undefined;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* @param {{ pattern: string; localized: Array<[string, string]> }} element
|
|
424
|
+
* @returns {FastPathRoute | null}
|
|
425
|
+
*/
|
|
426
|
+
function getFastPathRoute(element) {
|
|
427
|
+
const cached = fastPathRouteCache.get(element);
|
|
428
|
+
if (cached !== undefined)
|
|
429
|
+
return cached;
|
|
430
|
+
const base = parseFastPathPattern(element.pattern);
|
|
431
|
+
if (base === undefined) {
|
|
432
|
+
fastPathRouteCache.set(element, null);
|
|
433
|
+
return null;
|
|
434
|
+
}
|
|
435
|
+
const localized = [];
|
|
436
|
+
for (const [locale, pattern] of element.localized) {
|
|
437
|
+
const parsed = parseFastPathPattern(pattern);
|
|
438
|
+
if (parsed === undefined || parsed.pathMode !== base.pathMode) {
|
|
439
|
+
fastPathRouteCache.set(element, null);
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
localized.push({ locale, pattern: parsed });
|
|
443
|
+
}
|
|
444
|
+
const route = { base, localized };
|
|
445
|
+
fastPathRouteCache.set(element, route);
|
|
446
|
+
return route;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Parse only catch-all path patterns. In particular, do not treat `:path(.)?`
|
|
450
|
+
* as a catch-all: URLPattern's `(.)` means exactly one character and cannot be
|
|
451
|
+
* represented by this prefix matcher without changing routing semantics.
|
|
452
|
+
*
|
|
453
|
+
* @param {string} pattern
|
|
454
|
+
* @returns {FastPathPattern | undefined}
|
|
455
|
+
*/
|
|
456
|
+
function parseFastPathPattern(pattern) {
|
|
457
|
+
const wildcard = pattern.match(/\/:path(?:\(\.\*\)(?:\?)?|\*)$/);
|
|
458
|
+
if (wildcard === null || wildcard.index === undefined)
|
|
459
|
+
return undefined;
|
|
460
|
+
const prefix = pattern.slice(0, wildcard.index);
|
|
461
|
+
const originAndPath = parseFastPathOriginAndPath(prefix);
|
|
462
|
+
if (originAndPath === undefined)
|
|
463
|
+
return undefined;
|
|
464
|
+
const pathMode = wildcard[0].endsWith("*")
|
|
465
|
+
? "segments"
|
|
466
|
+
: wildcard[0].endsWith("?")
|
|
467
|
+
? "catch-all-optional"
|
|
468
|
+
: "catch-all-required";
|
|
469
|
+
return { ...originAndPath, pathMode };
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* @param {string} prefix
|
|
473
|
+
* @returns {FastPathPattern | undefined}
|
|
474
|
+
*/
|
|
475
|
+
function parseFastPathOriginAndPath(prefix) {
|
|
476
|
+
if (prefix === "" || prefix.startsWith("/")) {
|
|
477
|
+
if (hasUrlPatternSyntax(prefix))
|
|
478
|
+
return undefined;
|
|
479
|
+
return {
|
|
480
|
+
protocol: undefined,
|
|
481
|
+
hostname: undefined,
|
|
482
|
+
port: undefined,
|
|
483
|
+
pathnamePrefix: normalizePathPrefix(prefix),
|
|
484
|
+
pathMode: "catch-all-optional",
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
// A `:protocol://host` pattern is common in generated configurations. The
|
|
488
|
+
// protocol is intentionally left unconstrained, just like URLPattern.
|
|
489
|
+
const dynamicProtocol = prefix.match(/^:protocol:\/\/([^/]+)(\/.*)?$/);
|
|
490
|
+
const staticOrigin = prefix.match(/^([A-Za-z][A-Za-z\d+.-]*):\/\/([^/]+)(\/.*)?$/);
|
|
491
|
+
if (dynamicProtocol !== null) {
|
|
492
|
+
const dynamicHost = dynamicProtocol[1] ?? "";
|
|
493
|
+
const hostMatch = dynamicHost.match(/^([^:(){}?*+]+)(?::(\d+))?$/);
|
|
494
|
+
if (hostMatch === null ||
|
|
495
|
+
(dynamicProtocol[2] !== undefined &&
|
|
496
|
+
hasUrlPatternSyntax(dynamicProtocol[2]))) {
|
|
497
|
+
return undefined;
|
|
498
|
+
}
|
|
499
|
+
return {
|
|
500
|
+
protocol: undefined,
|
|
501
|
+
hostname: (hostMatch[1] ?? "").toLowerCase(),
|
|
502
|
+
port: hostMatch[2],
|
|
503
|
+
pathnamePrefix: normalizePathPrefix(dynamicProtocol[2] ?? ""),
|
|
504
|
+
pathMode: "catch-all-optional",
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
if (staticOrigin === null)
|
|
508
|
+
return undefined;
|
|
509
|
+
const host = staticOrigin[2] ?? "";
|
|
510
|
+
const pathname = staticOrigin[3];
|
|
511
|
+
const hostMatch = host.match(/^([^:(){}?*+]+)(?::(\d+))?$/);
|
|
512
|
+
if (hostMatch === null ||
|
|
513
|
+
(pathname !== undefined && hasUrlPatternSyntax(pathname))) {
|
|
514
|
+
return undefined;
|
|
515
|
+
}
|
|
516
|
+
return {
|
|
517
|
+
protocol: `${staticOrigin[1]}:`,
|
|
518
|
+
hostname: (hostMatch[1] ?? "").toLowerCase(),
|
|
519
|
+
port: normalizePatternPort(hostMatch[2], `${staticOrigin[1]}:`),
|
|
520
|
+
pathnamePrefix: normalizePathPrefix(pathname ?? ""),
|
|
521
|
+
pathMode: "catch-all-optional",
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* @param {string | undefined} port
|
|
526
|
+
* @param {string} protocol
|
|
527
|
+
* @returns {string | undefined}
|
|
528
|
+
*/
|
|
529
|
+
function normalizePatternPort(port, protocol) {
|
|
530
|
+
if (port === "80" && protocol === "http:")
|
|
531
|
+
return "";
|
|
532
|
+
if (port === "443" && protocol === "https:")
|
|
533
|
+
return "";
|
|
534
|
+
return port;
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* @param {string} value
|
|
538
|
+
* @returns {boolean}
|
|
539
|
+
*/
|
|
540
|
+
function hasUrlPatternSyntax(value) {
|
|
541
|
+
return /[:(){}?*+]/.test(value);
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* @param {string} pathname
|
|
545
|
+
* @returns {string}
|
|
546
|
+
*/
|
|
547
|
+
function normalizePathPrefix(pathname) {
|
|
548
|
+
if (pathname === "" || pathname === "/")
|
|
549
|
+
return "/";
|
|
550
|
+
return pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* @param {FastPathPattern} pattern
|
|
554
|
+
* @param {URL} urlObj
|
|
555
|
+
* @returns {string | undefined}
|
|
556
|
+
*/
|
|
557
|
+
function matchFastPathPattern(pattern, urlObj) {
|
|
558
|
+
if (pattern.protocol !== undefined && pattern.protocol !== urlObj.protocol) {
|
|
559
|
+
return undefined;
|
|
560
|
+
}
|
|
561
|
+
if (pattern.hostname !== undefined &&
|
|
562
|
+
pattern.hostname !== urlObj.hostname.toLowerCase()) {
|
|
563
|
+
return undefined;
|
|
564
|
+
}
|
|
565
|
+
if (pattern.hostname !== undefined) {
|
|
566
|
+
const expectedPort = pattern.port ?? defaultPortForProtocol(pattern.protocol ?? urlObj.protocol);
|
|
567
|
+
if (expectedPort !== urlObj.port)
|
|
568
|
+
return undefined;
|
|
569
|
+
}
|
|
570
|
+
const prefix = pattern.pathnamePrefix;
|
|
571
|
+
if (prefix === "/") {
|
|
572
|
+
if (urlObj.pathname.startsWith("//"))
|
|
573
|
+
return undefined;
|
|
574
|
+
if (pattern.pathMode === "segments") {
|
|
575
|
+
return isNonEmptyPathSegments(urlObj.pathname)
|
|
576
|
+
? urlObj.pathname
|
|
577
|
+
: undefined;
|
|
578
|
+
}
|
|
579
|
+
return urlObj.pathname;
|
|
580
|
+
}
|
|
581
|
+
if (urlObj.pathname === prefix) {
|
|
582
|
+
return pattern.pathMode === "catch-all-required" ? undefined : "";
|
|
583
|
+
}
|
|
584
|
+
if (urlObj.pathname.startsWith(`${prefix}/`)) {
|
|
585
|
+
const suffix = urlObj.pathname.slice(prefix.length);
|
|
586
|
+
if (suffix.startsWith("//"))
|
|
587
|
+
return undefined;
|
|
588
|
+
if (pattern.pathMode === "segments" &&
|
|
589
|
+
!isNonEmptyPathSegments(suffix)) {
|
|
590
|
+
return undefined;
|
|
591
|
+
}
|
|
592
|
+
return suffix;
|
|
593
|
+
}
|
|
594
|
+
return undefined;
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* @param {string} pathname
|
|
598
|
+
* @returns {boolean}
|
|
599
|
+
*/
|
|
600
|
+
function isNonEmptyPathSegments(pathname) {
|
|
601
|
+
return pathname.length > 1 && !pathname.endsWith("/") && !pathname.includes("//");
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* URLPattern treats the default port as empty in URL instances.
|
|
605
|
+
*
|
|
606
|
+
* @param {string} protocol
|
|
607
|
+
* @returns {string}
|
|
608
|
+
*/
|
|
609
|
+
function defaultPortForProtocol(protocol) {
|
|
610
|
+
if (protocol === "http:")
|
|
611
|
+
return "";
|
|
612
|
+
if (protocol === "https:")
|
|
613
|
+
return "";
|
|
614
|
+
return "";
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* @param {FastPathPattern} pattern
|
|
618
|
+
* @param {string} suffix
|
|
619
|
+
* @param {URL} source
|
|
620
|
+
* @returns {URL}
|
|
621
|
+
*/
|
|
622
|
+
function applyFastPathPattern(pattern, suffix, source) {
|
|
623
|
+
const localized = new URL(source.href);
|
|
624
|
+
if (pattern.protocol !== undefined)
|
|
625
|
+
localized.protocol = pattern.protocol;
|
|
626
|
+
if (pattern.hostname !== undefined) {
|
|
627
|
+
localized.hostname = pattern.hostname;
|
|
628
|
+
localized.port =
|
|
629
|
+
pattern.port ?? defaultPortForProtocol(localized.protocol);
|
|
630
|
+
}
|
|
631
|
+
localized.pathname = joinFastPathPrefix(pattern.pathnamePrefix, suffix);
|
|
632
|
+
return localized;
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* @param {string} prefix
|
|
636
|
+
* @param {string} suffix
|
|
637
|
+
* @returns {string}
|
|
638
|
+
*/
|
|
639
|
+
function joinFastPathPrefix(prefix, suffix) {
|
|
640
|
+
if (prefix === "/")
|
|
641
|
+
return suffix === "" ? "/" : suffix;
|
|
642
|
+
if (suffix === "")
|
|
643
|
+
return prefix;
|
|
644
|
+
return `${prefix}${suffix.startsWith("/") ? suffix : `/${suffix}`}`;
|
|
645
|
+
}
|
|
327
646
|
//# sourceMappingURL=localize-url.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localize-url.js","sourceRoot":"","sources":["../../../src/compiler/runtime/localize-url.js"],"names":[],"mappings":"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","sourcesContent":["import { extractLocaleFromUrl } from \"./extract-locale-from-url.js\";\nimport { getLocale } from \"./get-locale.js\";\nimport { getUrlOrigin } from \"./get-url-origin.js\";\nimport { assertIsLocale, toLocale } from \"./check-locale.js\";\nimport { getCompiledUrlPattern } from \"./url-pattern.js\";\nimport {\n\tdeLocalizeUrlHostRouting,\n\tlocalizeUrlHostRouting,\n} from \"./host-routing.js\";\nimport {\n\tbaseLocale,\n\tTREE_SHAKE_DEFAULT_URL_PATTERN_USED,\n\tTREE_SHAKE_HOST_ROUTING_USED,\n\turlPatterns,\n} from \"./variables.js\";\n\n/**\n * Lower-level URL localization function, primarily used in server contexts.\n *\n * This function is designed for server-side usage where you need precise control\n * over URL localization, such as in middleware or request handlers. It works with\n * URL objects and always returns absolute URLs.\n *\n * For client-side UI components, use `localizeHref()` instead, which provides\n * a more convenient API with relative paths and automatic locale detection.\n *\n * @see https://paraglidejs.com/i18n-routing\n *\n * @example\n * ```typescript\n * // Server middleware example\n * app.use((req, res, next) => {\n * const url = new URL(req.url, `${req.protocol}://${req.headers.host}`);\n * const localized = localizeUrl(url, { locale: \"de\" });\n *\n * if (localized.href !== url.href) {\n * return res.redirect(localized.href);\n * }\n * next();\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Using with URL patterns\n * const url = new URL(\"https://example.com/about\");\n * localizeUrl(url, { locale: \"de\" });\n * // => URL(\"https://example.com/de/about\")\n *\n * // Using with domain-based localization\n * const url = new URL(\"https://example.com/store\");\n * localizeUrl(url, { locale: \"de\" });\n * // => URL(\"https://de.example.com/store\")\n * ```\n *\n * @param {string | URL} url - The URL to localize. If string, must be absolute.\n * @param {object} [options] - Options for localization\n * @param {Locale} [options.locale] - Target locale. If not provided, uses getLocale()\n * @returns {URL} The localized URL, always absolute\n */\nexport function localizeUrl(url, options) {\n\tconst targetLocale = options?.locale\n\t\t? assertIsLocale(options?.locale)\n\t\t: getLocale();\n\n\tif (TREE_SHAKE_HOST_ROUTING_USED) {\n\t\tconst urlObj =\n\t\t\ttypeof url === \"string\" ? new URL(url, getUrlOrigin()) : url;\n\t\treturn localizeUrlHostRouting(urlObj, targetLocale);\n\t}\n\n\tif (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {\n\t\treturn localizeUrlDefaultPattern(url, targetLocale);\n\t}\n\n\tconst urlObj = typeof url === \"string\" ? new URL(url) : url;\n\n\t// Iterate over URL patterns\n\tfor (const element of urlPatterns) {\n\t\t// match localized patterns\n\t\tfor (const [, localizedPattern] of element.localized) {\n\t\t\tconst match = getCompiledUrlPattern(localizedPattern).exec(urlObj.href);\n\n\t\t\tif (!match) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst targetPattern = element.localized.find(\n\t\t\t\t([locale]) => locale === targetLocale\n\t\t\t)?.[1];\n\n\t\t\tif (!targetPattern) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst localizedUrl = fillPattern(\n\t\t\t\ttargetPattern,\n\t\t\t\taggregateGroups(match),\n\t\t\t\turlObj.origin\n\t\t\t);\n\t\t\treturn fillMissingUrlParts(localizedUrl, match);\n\t\t}\n\t\tconst unlocalizedMatch = getCompiledUrlPattern(element.pattern).exec(\n\t\t\turlObj.href\n\t\t);\n\t\tif (unlocalizedMatch) {\n\t\t\tconst targetPattern = element.localized.find(\n\t\t\t\t([locale]) => locale === targetLocale\n\t\t\t)?.[1];\n\t\t\tif (targetPattern) {\n\t\t\t\tconst localizedUrl = fillPattern(\n\t\t\t\t\ttargetPattern,\n\t\t\t\t\taggregateGroups(unlocalizedMatch),\n\t\t\t\t\turlObj.origin\n\t\t\t\t);\n\t\t\t\treturn fillMissingUrlParts(localizedUrl, unlocalizedMatch);\n\t\t\t}\n\t\t}\n\t}\n\t// If no match found, return the original URL\n\treturn urlObj;\n}\n\n/**\n * https://github.com/opral/inlang-paraglide-js/issues/381\n *\n * @param {string | URL} url\n * @param {Locale} locale\n * @returns {URL}\n */\nfunction localizeUrlDefaultPattern(url, locale) {\n\tconst urlObj =\n\t\ttypeof url === \"string\" ? new URL(url, getUrlOrigin()) : new URL(url);\n\n\tconst currentLocale = extractLocaleFromUrl(urlObj);\n\n\t// If current locale matches target locale, no change needed\n\tif (currentLocale === locale) {\n\t\treturn urlObj;\n\t}\n\n\tconst pathSegments = urlObj.pathname.split(\"/\").filter(Boolean);\n\n\t// If current path starts with a locale, remove it\n\tif (pathSegments.length > 0 && toLocale(pathSegments[0])) {\n\t\tpathSegments.shift();\n\t}\n\n\t// For base locale, don't add prefix\n\tif (locale === baseLocale) {\n\t\turlObj.pathname = \"/\" + pathSegments.join(\"/\");\n\t} else {\n\t\t// For other locales, add prefix\n\t\turlObj.pathname = \"/\" + locale + \"/\" + pathSegments.join(\"/\");\n\t}\n\n\treturn urlObj;\n}\n\n/**\n * Low-level URL de-localization function, primarily used in server contexts.\n *\n * This function is designed for server-side usage where you need precise control\n * over URL de-localization, such as in middleware or request handlers. It works with\n * URL objects and always returns absolute URLs.\n *\n * For client-side UI components, use `deLocalizeHref()` instead, which provides\n * a more convenient API with relative paths.\n *\n * @see https://paraglidejs.com/i18n-routing\n *\n * @example\n * ```typescript\n * // Server middleware example\n * app.use((req, res, next) => {\n * const url = new URL(req.url, `${req.protocol}://${req.headers.host}`);\n * const baseUrl = deLocalizeUrl(url);\n *\n * // Store the base URL for later use\n * req.baseUrl = baseUrl;\n * next();\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Using with URL patterns\n * const url = new URL(\"https://example.com/de/about\");\n * deLocalizeUrl(url); // => URL(\"https://example.com/about\")\n *\n * // Using with domain-based localization\n * const url = new URL(\"https://de.example.com/store\");\n * deLocalizeUrl(url); // => URL(\"https://example.com/store\")\n * ```\n *\n * @param {string | URL} url - The URL to de-localize. If string, must be absolute.\n * @returns {URL} The de-localized URL, always absolute\n */\nexport function deLocalizeUrl(url) {\n\tif (TREE_SHAKE_HOST_ROUTING_USED) {\n\t\tconst urlObj =\n\t\t\ttypeof url === \"string\" ? new URL(url, getUrlOrigin()) : url;\n\t\treturn deLocalizeUrlHostRouting(urlObj);\n\t}\n\n\tif (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {\n\t\treturn deLocalizeUrlDefaultPattern(url);\n\t}\n\n\tconst urlObj = typeof url === \"string\" ? new URL(url) : url;\n\n\t// Iterate over URL patterns\n\tfor (const element of urlPatterns) {\n\t\t// Iterate over localized versions\n\t\tfor (const [, localizedPattern] of element.localized) {\n\t\t\tconst match = getCompiledUrlPattern(localizedPattern).exec(urlObj.href);\n\n\t\t\tif (match) {\n\t\t\t\t// Convert localized URL back to the base pattern\n\t\t\t\tconst groups = aggregateGroups(match);\n\n\t\t\t\tconst baseUrl = fillPattern(element.pattern, groups, urlObj.origin);\n\t\t\t\treturn fillMissingUrlParts(baseUrl, match);\n\t\t\t}\n\t\t}\n\t\t// match unlocalized pattern\n\t\tconst unlocalizedMatch = getCompiledUrlPattern(element.pattern).exec(\n\t\t\turlObj.href\n\t\t);\n\t\tif (unlocalizedMatch) {\n\t\t\tconst baseUrl = fillPattern(\n\t\t\t\telement.pattern,\n\t\t\t\taggregateGroups(unlocalizedMatch),\n\t\t\t\turlObj.origin\n\t\t\t);\n\t\t\treturn fillMissingUrlParts(baseUrl, unlocalizedMatch);\n\t\t}\n\t}\n\t// no match found return the original url\n\treturn urlObj;\n}\n\n/**\n * De-localizes a URL using the default pattern (/:locale/*)\n * @param {string|URL} url\n * @returns {URL}\n */\nfunction deLocalizeUrlDefaultPattern(url) {\n\tconst urlObj =\n\t\ttypeof url === \"string\" ? new URL(url, getUrlOrigin()) : new URL(url);\n\tconst pathSegments = urlObj.pathname.split(\"/\").filter(Boolean);\n\n\t// If first segment is a locale, remove it\n\tif (pathSegments.length > 0 && toLocale(pathSegments[0])) {\n\t\turlObj.pathname = \"/\" + pathSegments.slice(1).join(\"/\");\n\t}\n\n\treturn urlObj;\n}\n\n/**\n * Takes matches of implicit wildcards in the UrlPattern (when a part is missing\n * it is equal to '*') and adds them back to the result of fillPattern.\n *\n * At least protocol and hostname are required to create a valid URL inside fillPattern.\n *\n * @param {URL} url\n * @param {any} match\n * @returns {URL}\n */\nfunction fillMissingUrlParts(url, match) {\n\tif (match.protocol.groups[\"0\"]) {\n\t\turl.protocol = match.protocol.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.hostname.groups[\"0\"]) {\n\t\turl.hostname = match.hostname.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.username.groups[\"0\"]) {\n\t\turl.username = match.username.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.password.groups[\"0\"]) {\n\t\turl.password = match.password.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.port.groups[\"0\"]) {\n\t\turl.port = match.port.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.pathname.groups[\"0\"]) {\n\t\turl.pathname = match.pathname.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.search.groups[\"0\"]) {\n\t\turl.search = match.search.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.hash.groups[\"0\"]) {\n\t\turl.hash = match.hash.groups[\"0\"] ?? \"\";\n\t}\n\n\treturn url;\n}\n\n/**\n * Fills a URL pattern with values for named groups, supporting all URLPattern-style modifiers.\n *\n * This function will eventually be replaced by https://github.com/whatwg/urlpattern/issues/73\n *\n * Matches:\n * - :name -> Simple\n * - :name? -> Optional\n * - :name+ -> One or more\n * - :name* -> Zero or more\n * - :name(...) -> Regex group\n * - {text} -> Group delimiter\n * - {text}? -> Optional group delimiter\n *\n * If the value is `null`, the segment is removed.\n *\n * @param {string} pattern - The URL pattern containing named groups.\n * @param {Record<string, string | null | undefined>} values - Object of values for named groups.\n * @param {string} origin - Base URL to use for URL construction.\n * @returns {URL} - The constructed URL with named groups filled.\n */\nfunction fillPattern(pattern, values, origin) {\n\t// Pre-process the pattern to handle explicit port numbers\n\t// This detects patterns like \"http://localhost:5173\" and protects the port number\n\t// from being interpreted as a parameter\n\tlet processedPattern = pattern.replace(\n\t\t/(https?:\\/\\/[^:/]+):(\\d+)(\\/|$)/g,\n\t\t(_, protocol, port, slash) => {\n\t\t\t// Replace \":5173\" with \"#PORT-5173#\" to protect it from parameter replacement\n\t\t\treturn `${protocol}#PORT-${port}#${slash}`;\n\t\t}\n\t);\n\n\t// First, handle group delimiters with curly braces\n\tlet processedGroupDelimiters = processedPattern.replace(\n\t\t/\\{([^{}]*)\\}([?+*]?)/g,\n\t\t(_, content, modifier) => {\n\t\t\t// For optional group delimiters\n\t\t\tif (modifier === \"?\") {\n\t\t\t\t// For optional groups, we'll include the content\n\t\t\t\treturn content;\n\t\t\t}\n\t\t\t// For non-optional group delimiters, always include the content\n\t\t\treturn content;\n\t\t}\n\t);\n\n\t// Then handle named groups\n\tlet filled = processedGroupDelimiters.replace(\n\t\t/(\\/?):([a-zA-Z0-9_]+)(\\([^)]*\\))?([?+*]?)/g,\n\t\t(_, slash, name, __, modifier) => {\n\t\t\tconst value = values[name];\n\n\t\t\tif (value === null) {\n\t\t\t\t// If value is null, remove the entire segment including the preceding slash\n\t\t\t\treturn \"\";\n\t\t\t}\n\n\t\t\tif (modifier === \"?\") {\n\t\t\t\t// Optional segment\n\t\t\t\treturn value !== undefined ? `${slash}${value}` : \"\";\n\t\t\t}\n\n\t\t\tif (modifier === \"+\" || modifier === \"*\") {\n\t\t\t\t// Repeatable segments\n\t\t\t\tif (value === undefined && modifier === \"+\") {\n\t\t\t\t\tthrow new Error(`Missing value for \"${name}\" (one or more required)`);\n\t\t\t\t}\n\t\t\t\treturn value ? `${slash}${value}` : \"\";\n\t\t\t}\n\n\t\t\t// Simple named group (no modifier)\n\t\t\tif (value === undefined) {\n\t\t\t\tthrow new Error(`Missing value for \"${name}\"`);\n\t\t\t}\n\n\t\t\treturn `${slash}${value}`;\n\t\t}\n\t);\n\n\t// Restore port numbers\n\tfilled = filled.replace(/#PORT-(\\d+)#/g, \":$1\");\n\n\treturn new URL(filled, origin);\n}\n\n/**\n * Aggregates named groups from various parts of the URLPattern match result.\n *\n *\n * @param {any} match - The URLPattern match result object.\n * @returns {Record<string, string | null | undefined>} An object containing all named groups from the match.\n */\nexport function aggregateGroups(match) {\n\treturn {\n\t\t...match.hash.groups,\n\t\t...match.hostname.groups,\n\t\t...match.password.groups,\n\t\t...match.pathname.groups,\n\t\t...match.port.groups,\n\t\t...match.protocol.groups,\n\t\t...match.search.groups,\n\t\t...match.username.groups,\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"localize-url.js","sourceRoot":"","sources":["../../../src/compiler/runtime/localize-url.js"],"names":[],"mappings":"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","sourcesContent":["import { extractLocaleFromUrl } from \"./extract-locale-from-url.js\";\nimport { getLocale } from \"./get-locale.js\";\nimport { getUrlOrigin } from \"./get-url-origin.js\";\nimport { assertIsLocale, toLocale } from \"./check-locale.js\";\nimport { getUrlPattern } from \"./url-pattern.js\";\nimport {\n\tdeLocalizeUrlHostRouting,\n\tlocalizeUrlHostRouting,\n} from \"./host-routing.js\";\nimport {\n\tbaseLocale,\n\tTREE_SHAKE_DEFAULT_URL_PATTERN_USED,\n\tTREE_SHAKE_HOST_ROUTING_USED,\n\ttrailingSlash,\n\turlPatterns,\n} from \"./variables.js\";\nimport { normalizeTrailingSlash } from \"./normalize-trailing-slash.js\";\nimport { execUrlPattern } from \"./exec-url-pattern.js\";\n\n/**\n * Lower-level URL localization function, primarily used in server contexts.\n *\n * This function is designed for server-side usage where you need precise control\n * over URL localization, such as in middleware or request handlers. It works with\n * URL objects and always returns absolute URLs.\n *\n * For client-side UI components, use `localizeHref()` instead, which provides\n * a more convenient API with relative paths and automatic locale detection.\n *\n * @see https://paraglidejs.com/i18n-routing\n *\n * @example\n * ```typescript\n * // Server middleware example\n * app.use((req, res, next) => {\n * const url = new URL(req.url, `${req.protocol}://${req.headers.host}`);\n * const localized = localizeUrl(url, { locale: \"de\" });\n *\n * if (localized.href !== url.href) {\n * return res.redirect(localized.href);\n * }\n * next();\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Using with URL patterns\n * const url = new URL(\"https://example.com/about\");\n * localizeUrl(url, { locale: \"de\" });\n * // => URL(\"https://example.com/de/about\")\n *\n * // Using with domain-based localization\n * const url = new URL(\"https://example.com/store\");\n * localizeUrl(url, { locale: \"de\" });\n * // => URL(\"https://de.example.com/store\")\n * ```\n *\n * @param {string | URL} url - The URL to localize. If string, must be absolute.\n * @param {object} [options] - Options for localization\n * @param {Locale} [options.locale] - Target locale. If not provided, uses getLocale()\n * @returns {URL} The localized URL, always absolute\n */\nexport function localizeUrl(url, options) {\n\tconst targetLocale = options?.locale\n\t\t? assertIsLocale(options?.locale)\n\t\t: getLocale();\n\n\tif (TREE_SHAKE_HOST_ROUTING_USED) {\n\t\tconst urlObj =\n\t\t\ttypeof url === \"string\" ? new URL(url, getUrlOrigin()) : url;\n\t\treturn localizeUrlHostRouting(urlObj, targetLocale);\n\t}\n\n\tif (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {\n\t\treturn localizeUrlDefaultPattern(url, targetLocale);\n\t}\n\n\tconst originalUrl = typeof url === \"string\" ? new URL(url) : url;\n\tconst urlObj =\n\t\ttrailingSlash === undefined\n\t\t\t? originalUrl\n\t\t\t: normalizeTrailingSlash(new URL(originalUrl));\n\n\t// Iterate over URL patterns\n\tfor (const element of urlPatterns) {\n\t\t// Most applications use a locale prefix (and sometimes a fixed domain)\n\t\t// with a trailing catch-all path. Those routes do not need URLPattern's\n\t\t// parser or matcher on every call. Keep the generic matcher below as the\n\t\t// fallback for every other URLPattern shape. This stays inside the outer\n\t\t// loop so specific patterns retain precedence over a later catch-all.\n\t\tconst fastPathLocalized = localizeUrlFastPath(\n\t\t\turlObj,\n\t\t\ttargetLocale,\n\t\t\telement\n\t\t);\n\t\tif (fastPathLocalized !== undefined) {\n\t\t\treturn fastPathLocalized;\n\t\t}\n\n\t\t// match localized patterns\n\t\tfor (const [, localizedPattern] of element.localized) {\n\t\t\tconst match = execUrlPattern(\n\t\t\t\tgetUrlPattern(localizedPattern, urlObj),\n\t\t\t\turlObj\n\t\t\t);\n\n\t\t\tif (!match) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst targetPattern = element.localized.find(\n\t\t\t\t([locale]) => locale === targetLocale\n\t\t\t)?.[1];\n\n\t\t\tif (!targetPattern) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst localizedUrl = fillPattern(\n\t\t\t\ttargetPattern,\n\t\t\t\taggregateGroups(match),\n\t\t\t\turlObj.origin\n\t\t\t);\n\t\t\treturn normalizeTrailingSlash(fillMissingUrlParts(localizedUrl, match));\n\t\t}\n\t\tconst unlocalizedMatch = execUrlPattern(\n\t\t\tgetUrlPattern(element.pattern, urlObj),\n\t\t\turlObj\n\t\t);\n\t\tif (unlocalizedMatch) {\n\t\t\tconst targetPattern = element.localized.find(\n\t\t\t\t([locale]) => locale === targetLocale\n\t\t\t)?.[1];\n\t\t\tif (targetPattern) {\n\t\t\t\tconst localizedUrl = fillPattern(\n\t\t\t\t\ttargetPattern,\n\t\t\t\t\taggregateGroups(unlocalizedMatch),\n\t\t\t\t\turlObj.origin\n\t\t\t\t);\n\t\t\t\treturn normalizeTrailingSlash(\n\t\t\t\t\tfillMissingUrlParts(localizedUrl, unlocalizedMatch)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\t// If no match found, return the original URL\n\treturn originalUrl;\n}\n\n/**\n * https://github.com/opral/inlang-paraglide-js/issues/381\n *\n * @param {string | URL} url\n * @param {Locale} locale\n * @returns {URL}\n */\nfunction localizeUrlDefaultPattern(url, locale) {\n\tconst urlObj = normalizeTrailingSlash(\n\t\ttypeof url === \"string\" ? new URL(url, getUrlOrigin()) : new URL(url)\n\t);\n\n\tconst currentLocale = extractLocaleFromUrl(urlObj);\n\n\t// If current locale matches target locale, no change needed\n\tif (currentLocale === locale) {\n\t\treturn normalizeTrailingSlash(urlObj);\n\t}\n\n\tconst pathSegments = urlObj.pathname.split(\"/\").filter(Boolean);\n\n\t// If current path starts with a locale, remove it\n\tif (pathSegments.length > 0 && toLocale(pathSegments[0])) {\n\t\tpathSegments.shift();\n\t}\n\n\t// For base locale, don't add prefix\n\tif (locale === baseLocale) {\n\t\turlObj.pathname = \"/\" + pathSegments.join(\"/\");\n\t} else {\n\t\t// For other locales, add prefix\n\t\turlObj.pathname = \"/\" + locale + \"/\" + pathSegments.join(\"/\");\n\t}\n\n\treturn normalizeTrailingSlash(urlObj);\n}\n\n/**\n * Low-level URL de-localization function, primarily used in server contexts.\n *\n * This function is designed for server-side usage where you need precise control\n * over URL de-localization, such as in middleware or request handlers. It works with\n * URL objects and always returns absolute URLs.\n *\n * For client-side UI components, use `deLocalizeHref()` instead, which provides\n * a more convenient API with relative paths.\n *\n * @see https://paraglidejs.com/i18n-routing\n *\n * @example\n * ```typescript\n * // Server middleware example\n * app.use((req, res, next) => {\n * const url = new URL(req.url, `${req.protocol}://${req.headers.host}`);\n * const baseUrl = deLocalizeUrl(url);\n *\n * // Store the base URL for later use\n * req.baseUrl = baseUrl;\n * next();\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Using with URL patterns\n * const url = new URL(\"https://example.com/de/about\");\n * deLocalizeUrl(url); // => URL(\"https://example.com/about\")\n *\n * // Using with domain-based localization\n * const url = new URL(\"https://de.example.com/store\");\n * deLocalizeUrl(url); // => URL(\"https://example.com/store\")\n * ```\n *\n * @param {string | URL} url - The URL to de-localize. If string, must be absolute.\n * @returns {URL} The de-localized URL, always absolute\n */\nexport function deLocalizeUrl(url) {\n\tif (TREE_SHAKE_HOST_ROUTING_USED) {\n\t\tconst urlObj =\n\t\t\ttypeof url === \"string\" ? new URL(url, getUrlOrigin()) : url;\n\t\treturn deLocalizeUrlHostRouting(urlObj);\n\t}\n\n\tif (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {\n\t\treturn deLocalizeUrlDefaultPattern(url);\n\t}\n\n\tconst originalUrl = typeof url === \"string\" ? new URL(url) : url;\n\tconst urlObj =\n\t\ttrailingSlash === undefined\n\t\t\t? originalUrl\n\t\t\t: normalizeTrailingSlash(new URL(originalUrl));\n\n\t// Iterate over URL patterns\n\tfor (const element of urlPatterns) {\n\t\tconst fastPathDeLocalized = deLocalizeUrlFastPath(urlObj, element);\n\t\tif (fastPathDeLocalized !== undefined) {\n\t\t\treturn fastPathDeLocalized;\n\t\t}\n\n\t\t// Iterate over localized versions\n\t\tfor (const [, localizedPattern] of element.localized) {\n\t\t\tconst match = execUrlPattern(\n\t\t\t\tgetUrlPattern(localizedPattern, urlObj),\n\t\t\t\turlObj\n\t\t\t);\n\n\t\t\tif (match) {\n\t\t\t\t// Convert localized URL back to the base pattern\n\t\t\t\tconst groups = aggregateGroups(match);\n\n\t\t\t\tconst baseUrl = fillPattern(element.pattern, groups, urlObj.origin);\n\t\t\t\treturn normalizeTrailingSlash(fillMissingUrlParts(baseUrl, match));\n\t\t\t}\n\t\t}\n\t\t// match unlocalized pattern\n\t\tconst unlocalizedMatch = execUrlPattern(\n\t\t\tgetUrlPattern(element.pattern, urlObj),\n\t\t\turlObj\n\t\t);\n\t\tif (unlocalizedMatch) {\n\t\t\tconst baseUrl = fillPattern(\n\t\t\t\telement.pattern,\n\t\t\t\taggregateGroups(unlocalizedMatch),\n\t\t\t\turlObj.origin\n\t\t\t);\n\t\t\treturn normalizeTrailingSlash(\n\t\t\t\tfillMissingUrlParts(baseUrl, unlocalizedMatch)\n\t\t\t);\n\t\t}\n\t}\n\t// no match found return the original url\n\treturn originalUrl;\n}\n\n/**\n * De-localizes a URL using the default pattern (/:locale/*)\n * @param {string|URL} url\n * @returns {URL}\n */\nfunction deLocalizeUrlDefaultPattern(url) {\n\tconst urlObj = normalizeTrailingSlash(\n\t\ttypeof url === \"string\" ? new URL(url, getUrlOrigin()) : new URL(url)\n\t);\n\tconst pathSegments = urlObj.pathname.split(\"/\").filter(Boolean);\n\n\t// If first segment is a locale, remove it\n\tif (pathSegments.length > 0 && toLocale(pathSegments[0])) {\n\t\turlObj.pathname = \"/\" + pathSegments.slice(1).join(\"/\");\n\t}\n\n\treturn normalizeTrailingSlash(urlObj);\n}\n\n/**\n * Takes matches of implicit wildcards in the UrlPattern (when a part is missing\n * it is equal to '*') and adds them back to the result of fillPattern.\n *\n * At least protocol and hostname are required to create a valid URL inside fillPattern.\n *\n * @param {URL} url\n * @param {any} match\n * @returns {URL}\n */\nfunction fillMissingUrlParts(url, match) {\n\tif (match.protocol.groups[\"0\"]) {\n\t\turl.protocol = match.protocol.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.hostname.groups[\"0\"]) {\n\t\turl.hostname = match.hostname.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.username.groups[\"0\"]) {\n\t\turl.username = match.username.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.password.groups[\"0\"]) {\n\t\turl.password = match.password.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.port.groups[\"0\"]) {\n\t\turl.port = match.port.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.pathname.groups[\"0\"]) {\n\t\turl.pathname = match.pathname.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.search.groups[\"0\"]) {\n\t\turl.search = match.search.groups[\"0\"] ?? \"\";\n\t}\n\tif (match.hash.groups[\"0\"]) {\n\t\turl.hash = match.hash.groups[\"0\"] ?? \"\";\n\t}\n\n\treturn url;\n}\n\n/**\n * Fills a URL pattern with values for named groups, supporting all URLPattern-style modifiers.\n *\n * This function will eventually be replaced by https://github.com/whatwg/urlpattern/issues/73\n *\n * Matches:\n * - :name -> Simple\n * - :name? -> Optional\n * - :name+ -> One or more\n * - :name* -> Zero or more\n * - :name(...) -> Regex group\n * - {text} -> Group delimiter\n * - {text}? -> Optional group delimiter\n *\n * If the value is `null`, the segment is removed.\n *\n * @param {string} pattern - The URL pattern containing named groups.\n * @param {Record<string, string | null | undefined>} values - Object of values for named groups.\n * @param {string} origin - Base URL to use for URL construction.\n * @returns {URL} - The constructed URL with named groups filled.\n */\nfunction fillPattern(pattern, values, origin) {\n\t// Pre-process the pattern to handle explicit port numbers\n\t// This detects patterns like \"http://localhost:5173\" and protects the port number\n\t// from being interpreted as a parameter\n\tlet processedPattern = pattern.replace(\n\t\t/(https?:\\/\\/[^:/]+):(\\d+)(\\/|$)/g,\n\t\t(_, protocol, port, slash) => {\n\t\t\t// Replace \":5173\" with \"#PORT-5173#\" to protect it from parameter replacement\n\t\t\treturn `${protocol}#PORT-${port}#${slash}`;\n\t\t}\n\t);\n\n\t// First, handle group delimiters with curly braces\n\tlet processedGroupDelimiters = processedPattern.replace(\n\t\t/\\{([^{}]*)\\}([?+*]?)/g,\n\t\t(_, content, modifier) => {\n\t\t\t// For optional group delimiters\n\t\t\tif (modifier === \"?\") {\n\t\t\t\t// For optional groups, we'll include the content\n\t\t\t\treturn content;\n\t\t\t}\n\t\t\t// For non-optional group delimiters, always include the content\n\t\t\treturn content;\n\t\t}\n\t);\n\n\t// Then handle named groups\n\tlet filled = processedGroupDelimiters.replace(\n\t\t/(\\/?):([a-zA-Z0-9_]+)(\\([^)]*\\))?([?+*]?)/g,\n\t\t(_, slash, name, __, modifier) => {\n\t\t\tconst value = values[name];\n\n\t\t\tif (value === null) {\n\t\t\t\t// If value is null, remove the entire segment including the preceding slash\n\t\t\t\treturn \"\";\n\t\t\t}\n\n\t\t\tif (modifier === \"?\") {\n\t\t\t\t// Optional segment\n\t\t\t\treturn value !== undefined ? `${slash}${value}` : \"\";\n\t\t\t}\n\n\t\t\tif (modifier === \"+\" || modifier === \"*\") {\n\t\t\t\t// Repeatable segments\n\t\t\t\tif (value === undefined && modifier === \"+\") {\n\t\t\t\t\tthrow new Error(`Missing value for \"${name}\" (one or more required)`);\n\t\t\t\t}\n\t\t\t\treturn value ? `${slash}${value}` : \"\";\n\t\t\t}\n\n\t\t\t// Simple named group (no modifier)\n\t\t\tif (value === undefined) {\n\t\t\t\tthrow new Error(`Missing value for \"${name}\"`);\n\t\t\t}\n\n\t\t\treturn `${slash}${value}`;\n\t\t}\n\t);\n\n\t// Restore port numbers\n\tfilled = filled.replace(/#PORT-(\\d+)#/g, \":$1\");\n\n\treturn new URL(filled, origin);\n}\n\n/**\n * Aggregates named groups from various parts of the URLPattern match result.\n *\n *\n * @param {any} match - The URLPattern match result object.\n * @returns {Record<string, string | null | undefined>} An object containing all named groups from the match.\n */\nexport function aggregateGroups(match) {\n\treturn {\n\t\t...match.hash.groups,\n\t\t...match.hostname.groups,\n\t\t...match.password.groups,\n\t\t...match.pathname.groups,\n\t\t...match.port.groups,\n\t\t...match.protocol.groups,\n\t\t...match.search.groups,\n\t\t...match.username.groups,\n\t};\n}\n\n/**\n * A small, deliberately conservative subset of URLPattern routing.\n *\n * The compiler emits routes such as `/:path(.*)?`, `/de/:path*`, or\n * `https://example.com/:path*`. For those routes matching is equivalent to a\n * pathname prefix check and (optionally) an origin check. Everything that has\n * a dynamic host, a custom path regexp, or another URLPattern modifier keeps\n * using the generic implementation above.\n *\n * @typedef {{\n * protocol: string | undefined;\n * hostname: string | undefined;\n * port: string | undefined;\n * pathnamePrefix: string;\n * pathMode: \"segments\" | \"catch-all-optional\" | \"catch-all-required\";\n * }} FastPathPattern\n * @typedef {{\n * base: FastPathPattern;\n * localized: Array<{ locale: string; pattern: FastPathPattern }>;\n * }} FastPathRoute\n */\n\n/** @type {WeakMap<object, FastPathRoute | null>} */\nconst fastPathRouteCache = new WeakMap();\n\n/**\n * @param {URL} urlObj\n * @param {string} targetLocale\n * @param {{ pattern: string; localized: Array<[string, string]> }} element\n * @returns {URL | undefined}\n */\nfunction localizeUrlFastPath(urlObj, targetLocale, element) {\n\tconst route = getFastPathRoute(element);\n\tif (route === null) return undefined;\n\n\t// Preserve URLPattern's ordering: localized patterns are checked before\n\t// the unlocalized pattern, and the first matching pattern wins.\n\tfor (const localized of route.localized) {\n\t\tconst suffix = matchFastPathPattern(localized.pattern, urlObj);\n\t\tif (suffix === undefined) continue;\n\n\t\tconst target = route.localized.find(\n\t\t\t(candidate) => candidate.locale === targetLocale\n\t\t)?.pattern;\n\t\tif (target === undefined) continue;\n\n\t\treturn applyFastPathPattern(target, suffix, urlObj);\n\t}\n\n\tconst suffix = matchFastPathPattern(route.base, urlObj);\n\tif (suffix !== undefined) {\n\t\tconst target = route.localized.find(\n\t\t\t(candidate) => candidate.locale === targetLocale\n\t\t)?.pattern;\n\t\tif (target !== undefined) {\n\t\t\treturn applyFastPathPattern(target, suffix, urlObj);\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\n/**\n * @param {URL} urlObj\n * @param {{ pattern: string; localized: Array<[string, string]> }} element\n * @returns {URL | undefined}\n */\nfunction deLocalizeUrlFastPath(urlObj, element) {\n\tconst route = getFastPathRoute(element);\n\tif (route === null) return undefined;\n\n\tfor (const localized of route.localized) {\n\t\tconst suffix = matchFastPathPattern(localized.pattern, urlObj);\n\t\tif (suffix !== undefined) {\n\t\t\treturn applyFastPathPattern(route.base, suffix, urlObj);\n\t\t}\n\t}\n\n\tconst suffix = matchFastPathPattern(route.base, urlObj);\n\tif (suffix !== undefined) {\n\t\treturn applyFastPathPattern(route.base, suffix, urlObj);\n\t}\n\n\treturn undefined;\n}\n\n/**\n * @param {{ pattern: string; localized: Array<[string, string]> }} element\n * @returns {FastPathRoute | null}\n */\nfunction getFastPathRoute(element) {\n\tconst cached = fastPathRouteCache.get(element);\n\tif (cached !== undefined) return cached;\n\n\tconst base = parseFastPathPattern(element.pattern);\n\tif (base === undefined) {\n\t\tfastPathRouteCache.set(element, null);\n\t\treturn null;\n\t}\n\n\tconst localized = [];\n\tfor (const [locale, pattern] of element.localized) {\n\t\tconst parsed = parseFastPathPattern(pattern);\n\t\tif (parsed === undefined || parsed.pathMode !== base.pathMode) {\n\t\t\tfastPathRouteCache.set(element, null);\n\t\t\treturn null;\n\t\t}\n\t\tlocalized.push({ locale, pattern: parsed });\n\t}\n\n\tconst route = { base, localized };\n\tfastPathRouteCache.set(element, route);\n\treturn route;\n}\n\n/**\n * Parse only catch-all path patterns. In particular, do not treat `:path(.)?`\n * as a catch-all: URLPattern's `(.)` means exactly one character and cannot be\n * represented by this prefix matcher without changing routing semantics.\n *\n * @param {string} pattern\n * @returns {FastPathPattern | undefined}\n */\nfunction parseFastPathPattern(pattern) {\n\tconst wildcard = pattern.match(/\\/:path(?:\\(\\.\\*\\)(?:\\?)?|\\*)$/);\n\tif (wildcard === null || wildcard.index === undefined) return undefined;\n\n\tconst prefix = pattern.slice(0, wildcard.index);\n\tconst originAndPath = parseFastPathOriginAndPath(prefix);\n\tif (originAndPath === undefined) return undefined;\n\tconst pathMode = wildcard[0].endsWith(\"*\")\n\t\t? \"segments\"\n\t\t: wildcard[0].endsWith(\"?\")\n\t\t\t? \"catch-all-optional\"\n\t\t\t: \"catch-all-required\";\n\n\treturn { ...originAndPath, pathMode };\n}\n\n/**\n * @param {string} prefix\n * @returns {FastPathPattern | undefined}\n */\nfunction parseFastPathOriginAndPath(prefix) {\n\tif (prefix === \"\" || prefix.startsWith(\"/\")) {\n\t\tif (hasUrlPatternSyntax(prefix)) return undefined;\n\t\treturn {\n\t\t\tprotocol: undefined,\n\t\t\thostname: undefined,\n\t\t\tport: undefined,\n\t\t\tpathnamePrefix: normalizePathPrefix(prefix),\n\t\t\tpathMode: \"catch-all-optional\",\n\t\t};\n\t}\n\n\t// A `:protocol://host` pattern is common in generated configurations. The\n\t// protocol is intentionally left unconstrained, just like URLPattern.\n\tconst dynamicProtocol = prefix.match(/^:protocol:\\/\\/([^/]+)(\\/.*)?$/);\n\tconst staticOrigin = prefix.match(\n\t\t/^([A-Za-z][A-Za-z\\d+.-]*):\\/\\/([^/]+)(\\/.*)?$/\n\t);\n\tif (dynamicProtocol !== null) {\n\t\tconst dynamicHost = dynamicProtocol[1] ?? \"\";\n\t\tconst hostMatch = dynamicHost.match(/^([^:(){}?*+]+)(?::(\\d+))?$/);\n\t\tif (\n\t\t\thostMatch === null ||\n\t\t\t(dynamicProtocol[2] !== undefined &&\n\t\t\t\thasUrlPatternSyntax(dynamicProtocol[2]))\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn {\n\t\t\tprotocol: undefined,\n\t\t\thostname: (hostMatch[1] ?? \"\").toLowerCase(),\n\t\t\tport: hostMatch[2],\n\t\t\tpathnamePrefix: normalizePathPrefix(dynamicProtocol[2] ?? \"\"),\n\t\t\tpathMode: \"catch-all-optional\",\n\t\t};\n\t}\n\n\tif (staticOrigin === null) return undefined;\n\n\tconst host = staticOrigin[2] ?? \"\";\n\tconst pathname = staticOrigin[3];\n\tconst hostMatch = host.match(/^([^:(){}?*+]+)(?::(\\d+))?$/);\n\tif (\n\t\thostMatch === null ||\n\t\t(pathname !== undefined && hasUrlPatternSyntax(pathname))\n\t) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tprotocol: `${staticOrigin[1]}:`,\n\t\thostname: (hostMatch[1] ?? \"\").toLowerCase(),\n\t\tport: normalizePatternPort(hostMatch[2], `${staticOrigin[1]}:`),\n\t\tpathnamePrefix: normalizePathPrefix(pathname ?? \"\"),\n\t\tpathMode: \"catch-all-optional\",\n\t};\n}\n\n/**\n * @param {string | undefined} port\n * @param {string} protocol\n * @returns {string | undefined}\n */\nfunction normalizePatternPort(port, protocol) {\n\tif (port === \"80\" && protocol === \"http:\") return \"\";\n\tif (port === \"443\" && protocol === \"https:\") return \"\";\n\treturn port;\n}\n\n/**\n * @param {string} value\n * @returns {boolean}\n */\nfunction hasUrlPatternSyntax(value) {\n\treturn /[:(){}?*+]/.test(value);\n}\n\n/**\n * @param {string} pathname\n * @returns {string}\n */\nfunction normalizePathPrefix(pathname) {\n\tif (pathname === \"\" || pathname === \"/\") return \"/\";\n\treturn pathname.endsWith(\"/\") ? pathname.slice(0, -1) : pathname;\n}\n\n/**\n * @param {FastPathPattern} pattern\n * @param {URL} urlObj\n * @returns {string | undefined}\n */\nfunction matchFastPathPattern(pattern, urlObj) {\n\tif (pattern.protocol !== undefined && pattern.protocol !== urlObj.protocol) {\n\t\treturn undefined;\n\t}\n\tif (\n\t\tpattern.hostname !== undefined &&\n\t\tpattern.hostname !== urlObj.hostname.toLowerCase()\n\t) {\n\t\treturn undefined;\n\t}\n\tif (pattern.hostname !== undefined) {\n\t\tconst expectedPort =\n\t\t\tpattern.port ?? defaultPortForProtocol(pattern.protocol ?? urlObj.protocol);\n\t\tif (expectedPort !== urlObj.port) return undefined;\n\t}\n\n\tconst prefix = pattern.pathnamePrefix;\n\tif (prefix === \"/\") {\n\t\tif (urlObj.pathname.startsWith(\"//\")) return undefined;\n\t\tif (pattern.pathMode === \"segments\") {\n\t\t\treturn isNonEmptyPathSegments(urlObj.pathname)\n\t\t\t\t? urlObj.pathname\n\t\t\t\t: undefined;\n\t\t}\n\t\treturn urlObj.pathname;\n\t}\n\tif (urlObj.pathname === prefix) {\n\t\treturn pattern.pathMode === \"catch-all-required\" ? undefined : \"\";\n\t}\n\tif (urlObj.pathname.startsWith(`${prefix}/`)) {\n\t\tconst suffix = urlObj.pathname.slice(prefix.length);\n\t\tif (suffix.startsWith(\"//\")) return undefined;\n\t\tif (\n\t\t\tpattern.pathMode === \"segments\" &&\n\t\t\t!isNonEmptyPathSegments(suffix)\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn suffix;\n\t}\n\treturn undefined;\n}\n\n/**\n * @param {string} pathname\n * @returns {boolean}\n */\nfunction isNonEmptyPathSegments(pathname) {\n\treturn pathname.length > 1 && !pathname.endsWith(\"/\") && !pathname.includes(\"//\");\n}\n\n/**\n * URLPattern treats the default port as empty in URL instances.\n *\n * @param {string} protocol\n * @returns {string}\n */\nfunction defaultPortForProtocol(protocol) {\n\tif (protocol === \"http:\") return \"\";\n\tif (protocol === \"https:\") return \"\";\n\treturn \"\";\n}\n\n/**\n * @param {FastPathPattern} pattern\n * @param {string} suffix\n * @param {URL} source\n * @returns {URL}\n */\nfunction applyFastPathPattern(pattern, suffix, source) {\n\tconst localized = new URL(source.href);\n\tif (pattern.protocol !== undefined) localized.protocol = pattern.protocol;\n\tif (pattern.hostname !== undefined) {\n\t\tlocalized.hostname = pattern.hostname;\n\t\tlocalized.port =\n\t\t\tpattern.port ?? defaultPortForProtocol(localized.protocol);\n\t}\n\tlocalized.pathname = joinFastPathPrefix(pattern.pathnamePrefix, suffix);\n\treturn localized;\n}\n\n/**\n * @param {string} prefix\n * @param {string} suffix\n * @returns {string}\n */\nfunction joinFastPathPrefix(prefix, suffix) {\n\tif (prefix === \"/\") return suffix === \"\" ? \"/\" : suffix;\n\tif (suffix === \"\") return prefix;\n\treturn `${prefix}${suffix.startsWith(\"/\") ? suffix : `/${suffix}`}`;\n}\n"]}
|