@inlang/paraglide-js 2.25.4 → 2.26.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/dist/compiler/runtime/create-runtime.js +24 -1
- package/dist/compiler/runtime/create-runtime.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-url.js +11 -4
- package/dist/compiler/runtime/extract-locale-from-url.js.map +1 -1
- package/dist/compiler/runtime/generate-static-localized-urls.js +5 -3
- package/dist/compiler/runtime/generate-static-localized-urls.js.map +1 -1
- package/dist/compiler/runtime/localize-url.js +25 -54
- package/dist/compiler/runtime/localize-url.js.map +1 -1
- package/dist/compiler/runtime/route-strategy.js +9 -3
- package/dist/compiler/runtime/route-strategy.js.map +1 -1
- package/dist/compiler/runtime/type.test.js +9 -0
- package/dist/compiler/runtime/type.test.js.map +1 -1
- package/dist/compiler/runtime/url-pattern-cache.d.ts +11 -0
- package/dist/compiler/runtime/url-pattern-cache.js +42 -0
- package/dist/compiler/runtime/url-pattern-cache.js.map +1 -0
- package/dist/compiler/runtime/url-pattern-index.d.ts +24 -0
- package/dist/compiler/runtime/url-pattern-index.differential.test.d.ts +1 -0
- package/dist/compiler/runtime/url-pattern-index.differential.test.js +152 -0
- package/dist/compiler/runtime/url-pattern-index.differential.test.js.map +1 -0
- package/dist/compiler/runtime/url-pattern-index.js +168 -0
- package/dist/compiler/runtime/url-pattern-index.js.map +1 -0
- package/dist/compiler/runtime/url-pattern-index.test.d.ts +1 -0
- package/dist/compiler/runtime/url-pattern-index.test.js +262 -0
- package/dist/compiler/runtime/url-pattern-index.test.js.map +1 -0
- package/dist/compiler/server/create-server-file.js +1 -1
- package/dist/compiler/server/create-server-file.js.map +1 -1
- package/dist/compiler/server/create-server-file.test.js +12 -0
- package/dist/compiler/server/create-server-file.test.js.map +1 -1
- package/dist/services/env-variables/index.js +1 -1
- package/dist/services/env-variables/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -93,6 +93,29 @@ ${injectCode("./normalize-trailing-slash.js", {
|
|
|
93
93
|
privateExports: ["normalizeTrailingSlash"],
|
|
94
94
|
})}
|
|
95
95
|
|
|
96
|
+
${needsUrlPatternPolyfill
|
|
97
|
+
? injectCode("./url-pattern-cache.js", {
|
|
98
|
+
privateExports: ["getUrlPattern"],
|
|
99
|
+
}) +
|
|
100
|
+
"\n\n" +
|
|
101
|
+
injectCode("./url-pattern-index.js", {
|
|
102
|
+
privateExports: [
|
|
103
|
+
"getRoutingConfigVersion",
|
|
104
|
+
"currentRoutingConfigVersion",
|
|
105
|
+
"getUrlPatternCandidates",
|
|
106
|
+
"getRouteStrategyCandidates",
|
|
107
|
+
],
|
|
108
|
+
})
|
|
109
|
+
: `// Default routing does not need a matcher cache or candidate index.
|
|
110
|
+
/** @param {string} pattern @param {URL} url @returns {URLPattern} */
|
|
111
|
+
function getUrlPattern(pattern, url) { return new URLPattern(pattern, url.href); }
|
|
112
|
+
function getRoutingConfigVersion() { return 0; }
|
|
113
|
+
function currentRoutingConfigVersion() { return 0; }
|
|
114
|
+
/** @param {URL} _url @returns {typeof urlPatterns} */
|
|
115
|
+
function getUrlPatternCandidates(_url) { return urlPatterns; }
|
|
116
|
+
/** @param {URL} _url @returns {typeof routeStrategies} */
|
|
117
|
+
function getRouteStrategyCandidates(_url) { return routeStrategies; }`}
|
|
118
|
+
|
|
96
119
|
${injectCode("./exec-url-pattern.js", {
|
|
97
120
|
privateExports: ["execUrlPattern"],
|
|
98
121
|
})}
|
|
@@ -142,7 +165,7 @@ ${injectCode("./type-definitions.js").replace(`@typedef {string} Locale`, `@type
|
|
|
142
165
|
function injectCode(path, options) {
|
|
143
166
|
const code = fs.readFileSync(new URL(path, import.meta.url), "utf-8");
|
|
144
167
|
// Regex to match single-line and multi-line imports
|
|
145
|
-
const importRegex =
|
|
168
|
+
const importRegex = /^\s*import\s+[\s\S]*?from\s+['"][^'"]+['"]\s*;?/gm;
|
|
146
169
|
const sourceMapRegex = /\/\/# sourceMappingURL=.*$/gm;
|
|
147
170
|
const blockSourceMapRegex = /\/\*# sourceMappingURL=.*?\*\//g;
|
|
148
171
|
let injected = code
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-runtime.js","sourceRoot":"","sources":["../../../src/compiler/runtime/create-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs\";\nimport type { CompilerOptions } from \"../compiler-options.js\";\nimport { perLocaleBuildStaticLocaleExpression } from \"../per-locale-build.js\";\n\n/**\n * Returns the code for the `runtime.js` module\n */\nexport function createRuntimeFile(args: {\n\tbaseLocale: string;\n\tlocales: string[];\n\tcompilerOptions: {\n\t\tstrategy: NonNullable<CompilerOptions[\"strategy\"]>;\n\t\trouteStrategies?: CompilerOptions[\"routeStrategies\"];\n\t\tcookieName: NonNullable<CompilerOptions[\"cookieName\"]>;\n\t\tcookieMaxAge: NonNullable<CompilerOptions[\"cookieMaxAge\"]>;\n\t\tcookieDomain: CompilerOptions[\"cookieDomain\"];\n\t\turlPatterns?: CompilerOptions[\"urlPatterns\"];\n\t\ttrailingSlash?: CompilerOptions[\"trailingSlash\"];\n\t\texperimentalMiddlewareLocaleSplitting: CompilerOptions[\"experimentalMiddlewareLocaleSplitting\"];\n\t\tisServer: CompilerOptions[\"isServer\"];\n\t\texperimentalStaticLocale?: CompilerOptions[\"experimentalStaticLocale\"];\n\t\tlocalStorageKey: CompilerOptions[\"localStorageKey\"];\n\t\tdisableAsyncLocalStorage: NonNullable<\n\t\t\tCompilerOptions[\"disableAsyncLocalStorage\"]\n\t\t>;\n\t};\n}): string {\n\tconst urlPatterns = args.compilerOptions.urlPatterns ?? [];\n\tconst routeStrategies = args.compilerOptions.routeStrategies ?? [];\n\n\tlet defaultUrlPatternUsed = false;\n\n\t// add default urlPatterns for a good out of the box experience\n\tif (args.compilerOptions.urlPatterns === undefined) {\n\t\tdefaultUrlPatternUsed = true;\n\t\turlPatterns.push({\n\t\t\tpattern: `:protocol://:domain(.*)::port?/:path(.*)?`,\n\t\t\tlocalized: [],\n\t\t});\n\t\tfor (const locale of args.locales) {\n\t\t\tif (locale === args.baseLocale) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\turlPatterns[0]?.localized.push([\n\t\t\t\tlocale,\n\t\t\t\t`:protocol://:domain(.*)::port?/${locale}/:path(.*)?`,\n\t\t\t]);\n\t\t}\n\t\turlPatterns[0]?.localized.push([\n\t\t\targs.baseLocale,\n\t\t\t`:protocol://:domain(.*)::port?/:path(.*)?`,\n\t\t]);\n\t}\n\tconst strategiesUsedByRoutes = routeStrategies.flatMap((routeStrategy) =>\n\t\t\"strategy\" in routeStrategy ? routeStrategy.strategy : []\n\t);\n\tconst allUsedStrategies = new Set([\n\t\t...args.compilerOptions.strategy,\n\t\t...strategiesUsedByRoutes,\n\t]);\n\tconst needsUrlPatternPolyfill =\n\t\t!defaultUrlPatternUsed || routeStrategies.length > 0;\n\n\t// verify that urlPatterns' locales are valid\n\tfor (const urlPattern of urlPatterns) {\n\t\tfor (const [locale] of urlPattern.localized) {\n\t\t\tif (!args.locales.includes(locale)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid locale \"${locale}\" in urlPatterns. It must be one of the locales defined in the \"locales\" array.`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst code = `\n${needsUrlPatternPolyfill ? `import \"@inlang/paraglide-js/urlpattern-polyfill\";` : \"/** @type {any} */\\nconst URLPattern = {}\"}\n\n${injectCode(\"./variables.js\")\n\t.replace(\n\t\t`export const baseLocale = \"en\";`,\n\t\t`export const baseLocale = \"${args.baseLocale}\";`\n\t)\n\t.replace(\n\t\t`export const locales = /** @type {readonly string[]} */ ([\"en\", \"de\"]);`,\n\t\t`export const locales = /** @type {const} */ (${JSON.stringify(args.locales)});`\n\t)\n\t.replace(\n\t\t`export const strategy = [\"globalVariable\"];`,\n\t\t`export const strategy = ${JSON.stringify(args.compilerOptions.strategy, null, 2)};`\n\t)\n\t.replace(`<cookie-name>`, `${args.compilerOptions.cookieName}`)\n\t.replace(`60 * 60 * 24 * 400`, `${args.compilerOptions.cookieMaxAge}`)\n\t.replace(`<cookie-domain>`, `${args.compilerOptions.cookieDomain}`)\n\t.replace(\n\t\t`export const routeStrategies = [];`,\n\t\t`export const routeStrategies = ${JSON.stringify(routeStrategies, null, 2)};`\n\t)\n\t.replace(\n\t\t`export const TREE_SHAKE_COOKIE_STRATEGY_USED = false;`,\n\t\t`const TREE_SHAKE_COOKIE_STRATEGY_USED = ${allUsedStrategies.has(\"cookie\")};`\n\t)\n\t.replace(\n\t\t`export const TREE_SHAKE_URL_STRATEGY_USED = false;`,\n\t\t`const TREE_SHAKE_URL_STRATEGY_USED = ${allUsedStrategies.has(\"url\")};`\n\t)\n\t.replace(\n\t\t`export const TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED = false;`,\n\t\t`const TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED = ${allUsedStrategies.has(\"globalVariable\")};`\n\t)\n\t.replace(\n\t\t`export const TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED = false;`,\n\t\t`const TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED = ${allUsedStrategies.has(\"preferredLanguage\")};`\n\t)\n\t.replace(\n\t\t`export const urlPatterns = [];`,\n\t\t`export const urlPatterns = ${JSON.stringify(urlPatterns, null, 2)};`\n\t)\n\t.replace(\n\t\t`export const trailingSlash = undefined;`,\n\t\t`export const trailingSlash = ${\n\t\t\targs.compilerOptions.trailingSlash === undefined\n\t\t\t\t? \"undefined\"\n\t\t\t\t: JSON.stringify(args.compilerOptions.trailingSlash)\n\t\t};`\n\t)\n\t.replace(\n\t\t`export const disableAsyncLocalStorage = false;`,\n\t\t`export const disableAsyncLocalStorage = ${args.compilerOptions.disableAsyncLocalStorage};`\n\t)\n\t.replace(\n\t\t`export const TREE_SHAKE_DEFAULT_URL_PATTERN_USED = false;`,\n\t\t`const TREE_SHAKE_DEFAULT_URL_PATTERN_USED = ${defaultUrlPatternUsed};`\n\t)\n\t.replace(\n\t\t`export const experimentalMiddlewareLocaleSplitting = false;`,\n\t\t`export const experimentalMiddlewareLocaleSplitting = ${args.compilerOptions.experimentalMiddlewareLocaleSplitting};`\n\t)\n\t.replace(\n\t\t`export const isServer = typeof window === \"undefined\";`,\n\t\t`export const isServer = ${args.compilerOptions.isServer};`\n\t)\n\t.replace(\n\t\t`export const experimentalStaticLocale = undefined;`,\n\t\targs.compilerOptions.experimentalStaticLocale\n\t\t\t? `export const experimentalStaticLocale = ${\n\t\t\t\t\targs.compilerOptions.experimentalStaticLocale ===\n\t\t\t\t\tperLocaleBuildStaticLocaleExpression\n\t\t\t\t\t\t? args.compilerOptions.experimentalStaticLocale\n\t\t\t\t\t\t: `assertIsLocale(${args.compilerOptions.experimentalStaticLocale})`\n\t\t\t\t};`\n\t\t\t: `export const experimentalStaticLocale = undefined;`\n\t)\n\t.replace(\n\t\t`export const localStorageKey = \"PARAGLIDE_LOCALE\";`,\n\t\t`export const localStorageKey = \"${args.compilerOptions.localStorageKey}\";`\n\t)\n\t.replace(\n\t\t`export const TREE_SHAKE_LOCAL_STORAGE_STRATEGY_USED = false;`,\n\t\t`const TREE_SHAKE_LOCAL_STORAGE_STRATEGY_USED = ${allUsedStrategies.has(\"localStorage\")};`\n\t)}\n\n/** @type {any} */ (globalThis).__paraglide =\n\t/** @type {any} */ (globalThis).__paraglide ?? {};\n/** @type {any} */ (globalThis).__paraglide.ssr =\n\t/** @type {any} */ (globalThis).__paraglide.ssr ?? {};\n\n${injectCode(\"./get-locale.js\")}\n\n${injectCode(\"./get-text-direction.js\")}\n\n${injectCode(\"./set-locale.js\")}\n\n${injectCode(\"./get-url-origin.js\")}\n\n${injectCode(\"./check-locale.js\")}\n\n${injectCode(\"./normalize-trailing-slash.js\", {\n\tprivateExports: [\"normalizeTrailingSlash\"],\n})}\n\n${injectCode(\"./exec-url-pattern.js\", {\n\tprivateExports: [\"execUrlPattern\"],\n})}\n\n${injectCode(\"./extract-locale-from-request.js\")}\n\n${injectCode(\"./extract-locale-from-request-async.js\")}\n\n${injectCode(\"./extract-locale-from-cookie.js\", {\n\tprivateExports: [\"clearLocaleCookieCache\"],\n})}\n\n${injectCode(\"./extract-locale-from-header.js\")}\n\n${injectCode(\"./extract-locale-from-navigator.js\")}\n\n${injectCode(\"./extract-locale-from-url.js\")}\n\n${injectCode(\"./localize-url.js\")}\n\n${injectCode(\"./route-strategy.js\")}\n\n${injectCode(\"./should-redirect.js\")}\n\n${injectCode(\"./localize-href.js\")}\n\n${injectCode(\"./track-message-call.js\")}\n\n${injectCode(\"./generate-static-localized-urls.js\")}\n\n${injectCode(\"./strategy.js\")}\n\n${injectCode(\"./type-definitions.js\").replace(\n\t`@typedef {string} Locale`,\n\t`@typedef {typeof locales[number]} Locale`\n)}\n`;\n\n\treturn code;\n}\n\n/**\n * Load a file from the current directory.\n *\n * Prunes the imports on top of the file as the runtime is\n * self-contained.\n *\n * @param {string} path\n * @param {{ privateExports?: string[] }} [options]\n * @returns {string}\n */\nfunction injectCode(\n\tpath: string,\n\toptions?: { privateExports?: string[] }\n): string {\n\tconst code = fs.readFileSync(new URL(path, import.meta.url), \"utf-8\");\n\t// Regex to match single-line and multi-line imports\n\tconst importRegex = /import\\s+[\\s\\S]*?from\\s+['\"][^'\"]+['\"]\\s*;?/g;\n\tconst sourceMapRegex = /\\/\\/# sourceMappingURL=.*$/gm;\n\tconst blockSourceMapRegex = /\\/\\*# sourceMappingURL=.*?\\*\\//g;\n\tlet injected = code\n\t\t.replace(importRegex, \"\")\n\t\t.replace(sourceMapRegex, \"\")\n\t\t.replace(blockSourceMapRegex, \"\")\n\t\t.trim();\n\tfor (const exportName of options?.privateExports ?? []) {\n\t\tinjected = injected.replace(\n\t\t\tnew RegExp(`\\\\bexport\\\\s+function\\\\s+${exportName}\\\\b`, \"g\"),\n\t\t\t`function ${exportName}`\n\t\t);\n\t}\n\treturn injected;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"create-runtime.js","sourceRoot":"","sources":["../../../src/compiler/runtime/create-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs\";\nimport type { CompilerOptions } from \"../compiler-options.js\";\nimport { perLocaleBuildStaticLocaleExpression } from \"../per-locale-build.js\";\n\n/**\n * Returns the code for the `runtime.js` module\n */\nexport function createRuntimeFile(args: {\n\tbaseLocale: string;\n\tlocales: string[];\n\tcompilerOptions: {\n\t\tstrategy: NonNullable<CompilerOptions[\"strategy\"]>;\n\t\trouteStrategies?: CompilerOptions[\"routeStrategies\"];\n\t\tcookieName: NonNullable<CompilerOptions[\"cookieName\"]>;\n\t\tcookieMaxAge: NonNullable<CompilerOptions[\"cookieMaxAge\"]>;\n\t\tcookieDomain: CompilerOptions[\"cookieDomain\"];\n\t\turlPatterns?: CompilerOptions[\"urlPatterns\"];\n\t\ttrailingSlash?: CompilerOptions[\"trailingSlash\"];\n\t\texperimentalMiddlewareLocaleSplitting: CompilerOptions[\"experimentalMiddlewareLocaleSplitting\"];\n\t\tisServer: CompilerOptions[\"isServer\"];\n\t\texperimentalStaticLocale?: CompilerOptions[\"experimentalStaticLocale\"];\n\t\tlocalStorageKey: CompilerOptions[\"localStorageKey\"];\n\t\tdisableAsyncLocalStorage: NonNullable<\n\t\t\tCompilerOptions[\"disableAsyncLocalStorage\"]\n\t\t>;\n\t};\n}): string {\n\tconst urlPatterns = args.compilerOptions.urlPatterns ?? [];\n\tconst routeStrategies = args.compilerOptions.routeStrategies ?? [];\n\n\tlet defaultUrlPatternUsed = false;\n\n\t// add default urlPatterns for a good out of the box experience\n\tif (args.compilerOptions.urlPatterns === undefined) {\n\t\tdefaultUrlPatternUsed = true;\n\t\turlPatterns.push({\n\t\t\tpattern: `:protocol://:domain(.*)::port?/:path(.*)?`,\n\t\t\tlocalized: [],\n\t\t});\n\t\tfor (const locale of args.locales) {\n\t\t\tif (locale === args.baseLocale) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\turlPatterns[0]?.localized.push([\n\t\t\t\tlocale,\n\t\t\t\t`:protocol://:domain(.*)::port?/${locale}/:path(.*)?`,\n\t\t\t]);\n\t\t}\n\t\turlPatterns[0]?.localized.push([\n\t\t\targs.baseLocale,\n\t\t\t`:protocol://:domain(.*)::port?/:path(.*)?`,\n\t\t]);\n\t}\n\tconst strategiesUsedByRoutes = routeStrategies.flatMap((routeStrategy) =>\n\t\t\"strategy\" in routeStrategy ? routeStrategy.strategy : []\n\t);\n\tconst allUsedStrategies = new Set([\n\t\t...args.compilerOptions.strategy,\n\t\t...strategiesUsedByRoutes,\n\t]);\n\tconst needsUrlPatternPolyfill =\n\t\t!defaultUrlPatternUsed || routeStrategies.length > 0;\n\n\t// verify that urlPatterns' locales are valid\n\tfor (const urlPattern of urlPatterns) {\n\t\tfor (const [locale] of urlPattern.localized) {\n\t\t\tif (!args.locales.includes(locale)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid locale \"${locale}\" in urlPatterns. It must be one of the locales defined in the \"locales\" array.`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst code = `\n${needsUrlPatternPolyfill ? `import \"@inlang/paraglide-js/urlpattern-polyfill\";` : \"/** @type {any} */\\nconst URLPattern = {}\"}\n\n${injectCode(\"./variables.js\")\n\t.replace(\n\t\t`export const baseLocale = \"en\";`,\n\t\t`export const baseLocale = \"${args.baseLocale}\";`\n\t)\n\t.replace(\n\t\t`export const locales = /** @type {readonly string[]} */ ([\"en\", \"de\"]);`,\n\t\t`export const locales = /** @type {const} */ (${JSON.stringify(args.locales)});`\n\t)\n\t.replace(\n\t\t`export const strategy = [\"globalVariable\"];`,\n\t\t`export const strategy = ${JSON.stringify(args.compilerOptions.strategy, null, 2)};`\n\t)\n\t.replace(`<cookie-name>`, `${args.compilerOptions.cookieName}`)\n\t.replace(`60 * 60 * 24 * 400`, `${args.compilerOptions.cookieMaxAge}`)\n\t.replace(`<cookie-domain>`, `${args.compilerOptions.cookieDomain}`)\n\t.replace(\n\t\t`export const routeStrategies = [];`,\n\t\t`export const routeStrategies = ${JSON.stringify(routeStrategies, null, 2)};`\n\t)\n\t.replace(\n\t\t`export const TREE_SHAKE_COOKIE_STRATEGY_USED = false;`,\n\t\t`const TREE_SHAKE_COOKIE_STRATEGY_USED = ${allUsedStrategies.has(\"cookie\")};`\n\t)\n\t.replace(\n\t\t`export const TREE_SHAKE_URL_STRATEGY_USED = false;`,\n\t\t`const TREE_SHAKE_URL_STRATEGY_USED = ${allUsedStrategies.has(\"url\")};`\n\t)\n\t.replace(\n\t\t`export const TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED = false;`,\n\t\t`const TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED = ${allUsedStrategies.has(\"globalVariable\")};`\n\t)\n\t.replace(\n\t\t`export const TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED = false;`,\n\t\t`const TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED = ${allUsedStrategies.has(\"preferredLanguage\")};`\n\t)\n\t.replace(\n\t\t`export const urlPatterns = [];`,\n\t\t`export const urlPatterns = ${JSON.stringify(urlPatterns, null, 2)};`\n\t)\n\t.replace(\n\t\t`export const trailingSlash = undefined;`,\n\t\t`export const trailingSlash = ${\n\t\t\targs.compilerOptions.trailingSlash === undefined\n\t\t\t\t? \"undefined\"\n\t\t\t\t: JSON.stringify(args.compilerOptions.trailingSlash)\n\t\t};`\n\t)\n\t.replace(\n\t\t`export const disableAsyncLocalStorage = false;`,\n\t\t`export const disableAsyncLocalStorage = ${args.compilerOptions.disableAsyncLocalStorage};`\n\t)\n\t.replace(\n\t\t`export const TREE_SHAKE_DEFAULT_URL_PATTERN_USED = false;`,\n\t\t`const TREE_SHAKE_DEFAULT_URL_PATTERN_USED = ${defaultUrlPatternUsed};`\n\t)\n\t.replace(\n\t\t`export const experimentalMiddlewareLocaleSplitting = false;`,\n\t\t`export const experimentalMiddlewareLocaleSplitting = ${args.compilerOptions.experimentalMiddlewareLocaleSplitting};`\n\t)\n\t.replace(\n\t\t`export const isServer = typeof window === \"undefined\";`,\n\t\t`export const isServer = ${args.compilerOptions.isServer};`\n\t)\n\t.replace(\n\t\t`export const experimentalStaticLocale = undefined;`,\n\t\targs.compilerOptions.experimentalStaticLocale\n\t\t\t? `export const experimentalStaticLocale = ${\n\t\t\t\t\targs.compilerOptions.experimentalStaticLocale ===\n\t\t\t\t\tperLocaleBuildStaticLocaleExpression\n\t\t\t\t\t\t? args.compilerOptions.experimentalStaticLocale\n\t\t\t\t\t\t: `assertIsLocale(${args.compilerOptions.experimentalStaticLocale})`\n\t\t\t\t};`\n\t\t\t: `export const experimentalStaticLocale = undefined;`\n\t)\n\t.replace(\n\t\t`export const localStorageKey = \"PARAGLIDE_LOCALE\";`,\n\t\t`export const localStorageKey = \"${args.compilerOptions.localStorageKey}\";`\n\t)\n\t.replace(\n\t\t`export const TREE_SHAKE_LOCAL_STORAGE_STRATEGY_USED = false;`,\n\t\t`const TREE_SHAKE_LOCAL_STORAGE_STRATEGY_USED = ${allUsedStrategies.has(\"localStorage\")};`\n\t)}\n\n/** @type {any} */ (globalThis).__paraglide =\n\t/** @type {any} */ (globalThis).__paraglide ?? {};\n/** @type {any} */ (globalThis).__paraglide.ssr =\n\t/** @type {any} */ (globalThis).__paraglide.ssr ?? {};\n\n${injectCode(\"./get-locale.js\")}\n\n${injectCode(\"./get-text-direction.js\")}\n\n${injectCode(\"./set-locale.js\")}\n\n${injectCode(\"./get-url-origin.js\")}\n\n${injectCode(\"./check-locale.js\")}\n\n${injectCode(\"./normalize-trailing-slash.js\", {\n\tprivateExports: [\"normalizeTrailingSlash\"],\n})}\n\n${\n\tneedsUrlPatternPolyfill\n\t\t? injectCode(\"./url-pattern-cache.js\", {\n\t\t\t\tprivateExports: [\"getUrlPattern\"],\n\t\t\t}) +\n\t\t\t\"\\n\\n\" +\n\t\t\tinjectCode(\"./url-pattern-index.js\", {\n\t\t\t\tprivateExports: [\n\t\t\t\t\t\"getRoutingConfigVersion\",\n\t\t\t\t\t\"currentRoutingConfigVersion\",\n\t\t\t\t\t\"getUrlPatternCandidates\",\n\t\t\t\t\t\"getRouteStrategyCandidates\",\n\t\t\t\t],\n\t\t\t})\n\t\t: `// Default routing does not need a matcher cache or candidate index.\n/** @param {string} pattern @param {URL} url @returns {URLPattern} */\nfunction getUrlPattern(pattern, url) { return new URLPattern(pattern, url.href); }\nfunction getRoutingConfigVersion() { return 0; }\nfunction currentRoutingConfigVersion() { return 0; }\n/** @param {URL} _url @returns {typeof urlPatterns} */\nfunction getUrlPatternCandidates(_url) { return urlPatterns; }\n/** @param {URL} _url @returns {typeof routeStrategies} */\nfunction getRouteStrategyCandidates(_url) { return routeStrategies; }`\n}\n\n${injectCode(\"./exec-url-pattern.js\", {\n\tprivateExports: [\"execUrlPattern\"],\n})}\n\n${injectCode(\"./extract-locale-from-request.js\")}\n\n${injectCode(\"./extract-locale-from-request-async.js\")}\n\n${injectCode(\"./extract-locale-from-cookie.js\", {\n\tprivateExports: [\"clearLocaleCookieCache\"],\n})}\n\n${injectCode(\"./extract-locale-from-header.js\")}\n\n${injectCode(\"./extract-locale-from-navigator.js\")}\n\n${injectCode(\"./extract-locale-from-url.js\")}\n\n${injectCode(\"./localize-url.js\")}\n\n${injectCode(\"./route-strategy.js\")}\n\n${injectCode(\"./should-redirect.js\")}\n\n${injectCode(\"./localize-href.js\")}\n\n${injectCode(\"./track-message-call.js\")}\n\n${injectCode(\"./generate-static-localized-urls.js\")}\n\n${injectCode(\"./strategy.js\")}\n\n${injectCode(\"./type-definitions.js\").replace(\n\t`@typedef {string} Locale`,\n\t`@typedef {typeof locales[number]} Locale`\n)}\n`;\n\n\treturn code;\n}\n\n/**\n * Load a file from the current directory.\n *\n * Prunes the imports on top of the file as the runtime is\n * self-contained.\n *\n * @param {string} path\n * @param {{ privateExports?: string[] }} [options]\n * @returns {string}\n */\nfunction injectCode(\n\tpath: string,\n\toptions?: { privateExports?: string[] }\n): string {\n\tconst code = fs.readFileSync(new URL(path, import.meta.url), \"utf-8\");\n\t// Regex to match single-line and multi-line imports\n\tconst importRegex = /^\\s*import\\s+[\\s\\S]*?from\\s+['\"][^'\"]+['\"]\\s*;?/gm;\n\tconst sourceMapRegex = /\\/\\/# sourceMappingURL=.*$/gm;\n\tconst blockSourceMapRegex = /\\/\\*# sourceMappingURL=.*?\\*\\//g;\n\tlet injected = code\n\t\t.replace(importRegex, \"\")\n\t\t.replace(sourceMapRegex, \"\")\n\t\t.replace(blockSourceMapRegex, \"\")\n\t\t.trim();\n\tfor (const exportName of options?.privateExports ?? []) {\n\t\tinjected = injected.replace(\n\t\t\tnew RegExp(`\\\\bexport\\\\s+function\\\\s+${exportName}\\\\b`, \"g\"),\n\t\t\t`function ${exportName}`\n\t\t);\n\t}\n\treturn injected;\n}\n"]}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { toLocale } from "./check-locale.js";
|
|
2
|
-
import { baseLocale, TREE_SHAKE_DEFAULT_URL_PATTERN_USED,
|
|
2
|
+
import { baseLocale, TREE_SHAKE_DEFAULT_URL_PATTERN_USED, } from "./variables.js";
|
|
3
3
|
import { normalizeTrailingSlash } from "./normalize-trailing-slash.js";
|
|
4
4
|
import { execUrlPattern } from "./exec-url-pattern.js";
|
|
5
|
+
import { getUrlPattern } from "./url-pattern-cache.js";
|
|
6
|
+
import { getUrlPatternCandidates, getRoutingConfigVersion, } from "./url-pattern-index.js";
|
|
7
|
+
let cachedLocaleConfigVersion = -1;
|
|
5
8
|
/**
|
|
6
9
|
* If extractLocaleFromUrl is called many times on the same page and the URL
|
|
7
10
|
* hasn't changed, we don't need to recompute it every time which can get expensive.
|
|
@@ -24,7 +27,10 @@ let cachedLocale;
|
|
|
24
27
|
*/
|
|
25
28
|
export function extractLocaleFromUrl(url) {
|
|
26
29
|
const urlString = typeof url === "string" ? url : url.href;
|
|
27
|
-
|
|
30
|
+
const configVersion = TREE_SHAKE_DEFAULT_URL_PATTERN_USED
|
|
31
|
+
? 0
|
|
32
|
+
: getRoutingConfigVersion();
|
|
33
|
+
if (cachedUrl === urlString && cachedLocaleConfigVersion === configVersion) {
|
|
28
34
|
return cachedLocale;
|
|
29
35
|
}
|
|
30
36
|
/** @type {Locale | undefined} */
|
|
@@ -38,9 +44,9 @@ export function extractLocaleFromUrl(url) {
|
|
|
38
44
|
else {
|
|
39
45
|
const urlObj = normalizeTrailingSlash(typeof url === "string" ? new URL(url) : new URL(url));
|
|
40
46
|
// Iterate over URL patterns
|
|
41
|
-
for (const element of
|
|
47
|
+
for (const element of getUrlPatternCandidates(urlObj)) {
|
|
42
48
|
for (const [locale, localizedPattern] of element.localized) {
|
|
43
|
-
const match = execUrlPattern(
|
|
49
|
+
const match = execUrlPattern(getUrlPattern(localizedPattern, urlObj), urlObj);
|
|
44
50
|
if (match) {
|
|
45
51
|
result = locale;
|
|
46
52
|
break;
|
|
@@ -50,6 +56,7 @@ export function extractLocaleFromUrl(url) {
|
|
|
50
56
|
break;
|
|
51
57
|
}
|
|
52
58
|
}
|
|
59
|
+
cachedLocaleConfigVersion = configVersion;
|
|
53
60
|
cachedUrl = urlString;
|
|
54
61
|
cachedLocale = result;
|
|
55
62
|
return result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract-locale-from-url.js","sourceRoot":"","sources":["../../../src/compiler/runtime/extract-locale-from-url.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EACN,UAAU,EACV,mCAAmC,
|
|
1
|
+
{"version":3,"file":"extract-locale-from-url.js","sourceRoot":"","sources":["../../../src/compiler/runtime/extract-locale-from-url.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EACN,UAAU,EACV,mCAAmC,GACnC,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EACN,uBAAuB,EACvB,uBAAuB,GACvB,MAAM,wBAAwB,CAAC;AAEhC,IAAI,yBAAyB,GAAG,CAAC,CAAC,CAAC;AAEnC;;;;;GAKG;AACH,+BAA+B;AAC/B,IAAI,SAAS,CAAC;AACd,+BAA+B;AAC/B,IAAI,YAAY,CAAC;AAEjB;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAG;IACvC,MAAM,SAAS,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IAE3D,MAAM,aAAa,GAAG,mCAAmC;QACxD,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,uBAAuB,EAAE,CAAC;IAC7B,IAAI,SAAS,KAAK,SAAS,IAAI,yBAAyB,KAAK,aAAa,EAAE,CAAC;QAC5E,OAAO,YAAY,CAAC;IACrB,CAAC;IAED,iCAAiC;IACjC,IAAI,MAAM,CAAC;IACX,IAAI,mCAAmC,EAAE,CAAC;QACzC,MAAM,MAAM,GACX,OAAO,GAAG,KAAK,QAAQ;YACtB,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,EAAE,oBAAoB,CAAC;YACpC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACjB,MAAM,GAAG,8BAA8B,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACP,MAAM,MAAM,GAAG,sBAAsB,CACpC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CACrD,CAAC;QAEF,4BAA4B;QAC5B,KAAK,MAAM,OAAO,IAAI,uBAAuB,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,KAAK,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBAC5D,MAAM,KAAK,GAAG,cAAc,CAC3B,aAAa,CAAC,gBAAgB,EAAE,MAAM,CAAC,EACvC,MAAM,CACN,CAAC;gBAEF,IAAI,KAAK,EAAE,CAAC;oBACX,MAAM,GAAG,MAAM,CAAC;oBAChB,MAAM;gBACP,CAAC;YACF,CAAC;YACD,IAAI,MAAM;gBAAE,MAAM;QACnB,CAAC;IACF,CAAC;IAED,yBAAyB,GAAG,aAAa,CAAC;IAC1C,SAAS,GAAG,SAAS,CAAC;IACtB,YAAY,GAAG,MAAM,CAAC;IACtB,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,8BAA8B,CAAC,GAAG;IAC1C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAChE,OAAO,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC;AAChD,CAAC","sourcesContent":["import { toLocale } from \"./check-locale.js\";\nimport {\n\tbaseLocale,\n\tTREE_SHAKE_DEFAULT_URL_PATTERN_USED,\n} from \"./variables.js\";\nimport { normalizeTrailingSlash } from \"./normalize-trailing-slash.js\";\nimport { execUrlPattern } from \"./exec-url-pattern.js\";\nimport { getUrlPattern } from \"./url-pattern-cache.js\";\nimport {\n\tgetUrlPatternCandidates,\n\tgetRoutingConfigVersion,\n} from \"./url-pattern-index.js\";\n\nlet cachedLocaleConfigVersion = -1;\n\n/**\n * If extractLocaleFromUrl is called many times on the same page and the URL\n * hasn't changed, we don't need to recompute it every time which can get expensive.\n * We might use a LRU cache if needed, but for now storing only the last result is enough.\n * https://github.com/opral/monorepo/pull/3575#discussion_r2066731243\n */\n/** @type {string|undefined} */\nlet cachedUrl;\n/** @type {Locale|undefined} */\nlet cachedLocale;\n\n/**\n * Extracts the locale from a given URL using native URLPattern.\n *\n * The built-in default `/:locale/...` routing is case-insensitive because it\n * canonicalizes the first path segment with `toLocale()`. Custom `urlPatterns`\n * keep URLPattern's normal exact matching semantics for path segments.\n *\n * @param {URL|string} url - The full URL from which to extract the locale.\n * @returns {Locale|undefined} The extracted locale, or undefined if no locale is found.\n */\nexport function extractLocaleFromUrl(url) {\n\tconst urlString = typeof url === \"string\" ? url : url.href;\n\n\tconst configVersion = TREE_SHAKE_DEFAULT_URL_PATTERN_USED\n\t\t? 0\n\t\t: getRoutingConfigVersion();\n\tif (cachedUrl === urlString && cachedLocaleConfigVersion === configVersion) {\n\t\treturn cachedLocale;\n\t}\n\n\t/** @type {Locale | undefined} */\n\tlet result;\n\tif (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {\n\t\tconst urlObj =\n\t\t\ttypeof url === \"string\"\n\t\t\t\t? new URL(url, \"http://example.com\")\n\t\t\t\t: new URL(url);\n\t\tresult = defaultUrlPatternExtractLocale(normalizeTrailingSlash(urlObj));\n\t} else {\n\t\tconst urlObj = normalizeTrailingSlash(\n\t\t\ttypeof url === \"string\" ? new URL(url) : new URL(url)\n\t\t);\n\n\t\t// Iterate over URL patterns\n\t\tfor (const element of getUrlPatternCandidates(urlObj)) {\n\t\t\tfor (const [locale, localizedPattern] of element.localized) {\n\t\t\t\tconst match = execUrlPattern(\n\t\t\t\t\tgetUrlPattern(localizedPattern, urlObj),\n\t\t\t\t\turlObj\n\t\t\t\t);\n\n\t\t\t\tif (match) {\n\t\t\t\t\tresult = locale;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (result) break;\n\t\t}\n\t}\n\n\tcachedLocaleConfigVersion = configVersion;\n\tcachedUrl = urlString;\n\tcachedLocale = result;\n\treturn result;\n}\n\n/**\n * https://github.com/opral/inlang-paraglide-js/issues/381\n *\n * @param {URL | string} url - The full URL from which to extract the locale.\n * @returns {Locale | undefined} The extracted locale, or undefined if no locale is found.\n */\nfunction defaultUrlPatternExtractLocale(url) {\n\tconst urlObj = new URL(url, \"http://example.com\");\n\tconst pathSegments = urlObj.pathname.split(\"/\").filter(Boolean);\n\treturn toLocale(pathSegments[0]) || baseLocale;\n}\n"]}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { localizeUrl } from "./localize-url.js";
|
|
2
2
|
import { normalizeTrailingSlash } from "./normalize-trailing-slash.js";
|
|
3
3
|
import { execUrlPattern } from "./exec-url-pattern.js";
|
|
4
|
-
import {
|
|
4
|
+
import { getUrlPattern } from "./url-pattern-cache.js";
|
|
5
|
+
import { getUrlPatternCandidates } from "./url-pattern-index.js";
|
|
6
|
+
import { locales, baseLocale, TREE_SHAKE_DEFAULT_URL_PATTERN_USED, trailingSlash, } from "./variables.js";
|
|
5
7
|
/**
|
|
6
8
|
* Generates localized URL variants for all provided URLs based on your configured locales and URL patterns.
|
|
7
9
|
*
|
|
@@ -78,10 +80,10 @@ export function generateStaticLocalizedUrls(urls) {
|
|
|
78
80
|
const url = normalizeTrailingSlash(new URL(originalUrl));
|
|
79
81
|
// Try each URL pattern to find one that matches
|
|
80
82
|
let patternFound = false;
|
|
81
|
-
for (const pattern of
|
|
83
|
+
for (const pattern of getUrlPatternCandidates(url)) {
|
|
82
84
|
try {
|
|
83
85
|
// Try to match the unlocalized pattern
|
|
84
|
-
const unlocalizedMatch = execUrlPattern(
|
|
86
|
+
const unlocalizedMatch = execUrlPattern(getUrlPattern(pattern.pattern, url), url);
|
|
85
87
|
if (!unlocalizedMatch)
|
|
86
88
|
continue;
|
|
87
89
|
patternFound = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-static-localized-urls.js","sourceRoot":"","sources":["../../../src/compiler/runtime/generate-static-localized-urls.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EACN,OAAO,EACP,UAAU,EACV,mCAAmC,EACnC,aAAa,
|
|
1
|
+
{"version":3,"file":"generate-static-localized-urls.js","sourceRoot":"","sources":["../../../src/compiler/runtime/generate-static-localized-urls.js"],"names":[],"mappings":"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","sourcesContent":["import { localizeUrl } from \"./localize-url.js\";\nimport { normalizeTrailingSlash } from \"./normalize-trailing-slash.js\";\nimport { execUrlPattern } from \"./exec-url-pattern.js\";\nimport { getUrlPattern } from \"./url-pattern-cache.js\";\nimport { getUrlPatternCandidates } from \"./url-pattern-index.js\";\nimport {\n\tlocales,\n\tbaseLocale,\n\tTREE_SHAKE_DEFAULT_URL_PATTERN_USED,\n\ttrailingSlash,\n} from \"./variables.js\";\n\n/**\n * Generates localized URL variants for all provided URLs based on your configured locales and URL patterns.\n *\n * This function is essential for Static Site Generation (SSG) where you need to tell your framework\n * which pages to pre-render at build time. It's also useful for generating sitemaps and\n * `<link rel=\"alternate\" hreflang>` tags for SEO.\n *\n * The function respects your `urlPatterns` configuration - if you have translated pathnames\n * (e.g., `/about` → `/ueber-uns` for German), it will generate the correct localized paths.\n *\n * @see https://paraglidejs.com/static-site-generation\n *\n * @example\n * // Basic usage - generate all locale variants for a list of paths\n * const localizedUrls = generateStaticLocalizedUrls([\n * \"/\",\n * \"/about\",\n * \"/blog/post-1\",\n * ]);\n * // Returns URL objects for each locale:\n * // [\"/en/\", \"/de/\", \"/en/about\", \"/de/about\", \"/en/blog/post-1\", \"/de/blog/post-1\"]\n *\n * @example\n * // Use with framework SSG APIs\n * // SvelteKit\n * export function entries() {\n * const paths = [\"/\", \"/about\", \"/contact\"];\n * return generateStaticLocalizedUrls(paths).map(url => ({\n * locale: extractLocaleFromUrl(url)\n * }));\n * }\n *\n * @example\n * // Sitemap generation\n * const allPages = [\"/\", \"/about\", \"/blog\"];\n * const sitemapUrls = generateStaticLocalizedUrls(allPages);\n *\n * @param {(string | URL)[]} urls - List of canonical URLs or paths to generate localized versions for.\n * Can be absolute URLs (`https://example.com/about`) or paths (`/about`).\n * Paths are resolved against `http://localhost` internally.\n * @returns {URL[]} Array of URL objects representing all localized variants.\n * The order follows each input URL with all its locale variants before moving to the next URL.\n */\nexport function generateStaticLocalizedUrls(urls) {\n\t/** @type {Set<URL>} */\n\tconst localizedUrls = new Set();\n\n\t// For default URL pattern, we can optimize the generation\n\tif (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {\n\t\tfor (const urlInput of urls) {\n\t\t\tconst originalUrl =\n\t\t\t\turlInput instanceof URL\n\t\t\t\t\t? urlInput\n\t\t\t\t\t: new URL(urlInput, \"http://localhost\");\n\t\t\tconst url =\n\t\t\t\ttrailingSlash === undefined\n\t\t\t\t\t? originalUrl\n\t\t\t\t\t: normalizeTrailingSlash(new URL(originalUrl));\n\n\t\t\t// Base locale doesn't get a prefix\n\t\t\tlocalizedUrls.add(url);\n\n\t\t\t// Other locales get their code as prefix\n\t\t\tfor (const locale of locales) {\n\t\t\t\tif (locale !== baseLocale) {\n\t\t\t\t\tconst localizedPath = `/${locale}${url.pathname}${url.search}${url.hash}`;\n\t\t\t\t\tconst localizedUrl = new URL(localizedPath, url.origin);\n\t\t\t\t\tlocalizedUrls.add(normalizeTrailingSlash(localizedUrl));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn Array.from(localizedUrls);\n\t}\n\n\t// For custom URL patterns, we need to use localizeUrl for each URL and locale\n\tfor (const urlInput of urls) {\n\t\tconst originalUrl =\n\t\t\turlInput instanceof URL\n\t\t\t\t? urlInput\n\t\t\t\t: new URL(urlInput, \"http://localhost\");\n\t\tconst url = normalizeTrailingSlash(new URL(originalUrl));\n\n\t\t// Try each URL pattern to find one that matches\n\t\tlet patternFound = false;\n\t\tfor (const pattern of getUrlPatternCandidates(url)) {\n\t\t\ttry {\n\t\t\t\t// Try to match the unlocalized pattern\n\t\t\t\tconst unlocalizedMatch = execUrlPattern(\n\t\t\t\t\tgetUrlPattern(pattern.pattern, url),\n\t\t\t\t\turl\n\t\t\t\t);\n\n\t\t\t\tif (!unlocalizedMatch) continue;\n\n\t\t\t\tpatternFound = true;\n\n\t\t\t\t// Track unique localized URLs to avoid duplicates when patterns are the same\n\t\t\t\tconst seenUrls = new Set();\n\n\t\t\t\t// Generate localized URL for each locale\n\t\t\t\tfor (const [locale] of pattern.localized) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst localizedUrl = localizeUrl(url, { locale });\n\t\t\t\t\t\tconst urlString = localizedUrl.href;\n\n\t\t\t\t\t\t// Only add if we haven't seen this exact URL before\n\t\t\t\t\t\tif (!seenUrls.has(urlString)) {\n\t\t\t\t\t\t\tseenUrls.add(urlString);\n\t\t\t\t\t\t\tlocalizedUrls.add(localizedUrl);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Skip if localization fails for this locale\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} catch {\n\t\t\t\t// Skip if pattern matching fails\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// If no pattern matched, use the URL as is\n\t\tif (!patternFound) {\n\t\t\tlocalizedUrls.add(originalUrl);\n\t\t}\n\t}\n\n\treturn Array.from(localizedUrls);\n}\n"]}
|
|
@@ -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 { baseLocale, TREE_SHAKE_DEFAULT_URL_PATTERN_USED, trailingSlash,
|
|
5
|
+
import { baseLocale, TREE_SHAKE_DEFAULT_URL_PATTERN_USED, trailingSlash, } from "./variables.js";
|
|
6
6
|
import { normalizeTrailingSlash } from "./normalize-trailing-slash.js";
|
|
7
7
|
import { execUrlPattern } from "./exec-url-pattern.js";
|
|
8
|
+
import { getUrlPattern } from "./url-pattern-cache.js";
|
|
9
|
+
import { getUrlPatternCandidates, currentRoutingConfigVersion, } from "./url-pattern-index.js";
|
|
8
10
|
/**
|
|
9
11
|
* Lower-level URL localization function, primarily used in server contexts.
|
|
10
12
|
*
|
|
@@ -61,7 +63,7 @@ export function localizeUrl(url, options) {
|
|
|
61
63
|
? originalUrl
|
|
62
64
|
: normalizeTrailingSlash(new URL(originalUrl));
|
|
63
65
|
// Iterate over URL patterns
|
|
64
|
-
for (const element of
|
|
66
|
+
for (const element of getUrlPatternCandidates(urlObj)) {
|
|
65
67
|
// Most applications use a locale prefix (and sometimes a fixed domain)
|
|
66
68
|
// with a trailing catch-all path. Those routes do not need URLPattern's
|
|
67
69
|
// parser or matcher on every call. Keep the generic matcher below as the
|
|
@@ -174,7 +176,7 @@ export function deLocalizeUrl(url) {
|
|
|
174
176
|
? originalUrl
|
|
175
177
|
: normalizeTrailingSlash(new URL(originalUrl));
|
|
176
178
|
// Iterate over URL patterns
|
|
177
|
-
for (const element of
|
|
179
|
+
for (const element of getUrlPatternCandidates(urlObj)) {
|
|
178
180
|
const fastPathDeLocalized = deLocalizeUrlFastPath(urlObj, element);
|
|
179
181
|
if (fastPathDeLocalized !== undefined) {
|
|
180
182
|
return fastPathDeLocalized;
|
|
@@ -337,45 +339,6 @@ export function aggregateGroups(match) {
|
|
|
337
339
|
...match.username.groups,
|
|
338
340
|
};
|
|
339
341
|
}
|
|
340
|
-
/** @type {Map<string, URLPattern>} */
|
|
341
|
-
const urlPatternCache = new Map();
|
|
342
|
-
const URL_PATTERN_CACHE_LIMIT = 128;
|
|
343
|
-
const ABSOLUTE_URL_PATTERN = /^(?:[A-Za-z][A-Za-z\d+.-]*|:[A-Za-z][A-Za-z\d_-]*):\/\//;
|
|
344
|
-
/**
|
|
345
|
-
* URLPattern's base URL affects relative patterns. Absolute patterns only
|
|
346
|
-
* depend on the pattern itself, while root-relative patterns also depend on
|
|
347
|
-
* the URL origin. Other relative patterns are deliberately not cached because
|
|
348
|
-
* their semantics depend on the complete base URL.
|
|
349
|
-
*
|
|
350
|
-
* @param {string} pattern
|
|
351
|
-
* @param {URL} url
|
|
352
|
-
* @returns {URLPattern}
|
|
353
|
-
*/
|
|
354
|
-
function getUrlPattern(pattern, url) {
|
|
355
|
-
const isAbsolutePattern = ABSOLUTE_URL_PATTERN.test(pattern);
|
|
356
|
-
const isRootRelativePattern = pattern.startsWith("/");
|
|
357
|
-
if (!isAbsolutePattern && !isRootRelativePattern) {
|
|
358
|
-
return new URLPattern(pattern, url.href);
|
|
359
|
-
}
|
|
360
|
-
const key = isAbsolutePattern
|
|
361
|
-
? pattern
|
|
362
|
-
: JSON.stringify([url.origin, pattern]);
|
|
363
|
-
const cached = urlPatternCache.get(key);
|
|
364
|
-
if (cached !== undefined) {
|
|
365
|
-
// Refresh the entry so frequently used patterns stay in the bounded cache.
|
|
366
|
-
urlPatternCache.delete(key);
|
|
367
|
-
urlPatternCache.set(key, cached);
|
|
368
|
-
return cached;
|
|
369
|
-
}
|
|
370
|
-
const compiled = new URLPattern(pattern, url.href);
|
|
371
|
-
if (urlPatternCache.size >= URL_PATTERN_CACHE_LIMIT) {
|
|
372
|
-
const oldestKey = urlPatternCache.keys().next().value;
|
|
373
|
-
if (oldestKey !== undefined)
|
|
374
|
-
urlPatternCache.delete(oldestKey);
|
|
375
|
-
}
|
|
376
|
-
urlPatternCache.set(key, compiled);
|
|
377
|
-
return compiled;
|
|
378
|
-
}
|
|
379
342
|
/**
|
|
380
343
|
* A small, deliberately conservative subset of URLPattern routing.
|
|
381
344
|
*
|
|
@@ -397,7 +360,7 @@ function getUrlPattern(pattern, url) {
|
|
|
397
360
|
* localized: Array<{ locale: string; pattern: FastPathPattern }>;
|
|
398
361
|
* }} FastPathRoute
|
|
399
362
|
*/
|
|
400
|
-
/** @type {WeakMap<object, FastPathRoute | null>} */
|
|
363
|
+
/** @type {WeakMap<object, { version: number; route: FastPathRoute | null }>} */
|
|
401
364
|
const fastPathRouteCache = new WeakMap();
|
|
402
365
|
/**
|
|
403
366
|
* @param {URL} urlObj
|
|
@@ -456,24 +419,33 @@ function deLocalizeUrlFastPath(urlObj, element) {
|
|
|
456
419
|
*/
|
|
457
420
|
function getFastPathRoute(element) {
|
|
458
421
|
const cached = fastPathRouteCache.get(element);
|
|
459
|
-
if (cached
|
|
460
|
-
return cached;
|
|
422
|
+
if (cached?.version === currentRoutingConfigVersion())
|
|
423
|
+
return cached.route;
|
|
461
424
|
const base = parseFastPathPattern(element.pattern);
|
|
462
425
|
if (base === undefined) {
|
|
463
|
-
fastPathRouteCache.set(element,
|
|
426
|
+
fastPathRouteCache.set(element, {
|
|
427
|
+
version: currentRoutingConfigVersion(),
|
|
428
|
+
route: null,
|
|
429
|
+
});
|
|
464
430
|
return null;
|
|
465
431
|
}
|
|
466
432
|
const localized = [];
|
|
467
433
|
for (const [locale, pattern] of element.localized) {
|
|
468
434
|
const parsed = parseFastPathPattern(pattern);
|
|
469
435
|
if (parsed === undefined || parsed.pathMode !== base.pathMode) {
|
|
470
|
-
fastPathRouteCache.set(element,
|
|
436
|
+
fastPathRouteCache.set(element, {
|
|
437
|
+
version: currentRoutingConfigVersion(),
|
|
438
|
+
route: null,
|
|
439
|
+
});
|
|
471
440
|
return null;
|
|
472
441
|
}
|
|
473
442
|
localized.push({ locale, pattern: parsed });
|
|
474
443
|
}
|
|
475
444
|
const route = { base, localized };
|
|
476
|
-
fastPathRouteCache.set(element,
|
|
445
|
+
fastPathRouteCache.set(element, {
|
|
446
|
+
version: currentRoutingConfigVersion(),
|
|
447
|
+
route,
|
|
448
|
+
});
|
|
477
449
|
return route;
|
|
478
450
|
}
|
|
479
451
|
/**
|
|
@@ -594,7 +566,8 @@ function matchFastPathPattern(pattern, urlObj) {
|
|
|
594
566
|
return undefined;
|
|
595
567
|
}
|
|
596
568
|
if (pattern.hostname !== undefined) {
|
|
597
|
-
const expectedPort = pattern.port ??
|
|
569
|
+
const expectedPort = pattern.port ??
|
|
570
|
+
defaultPortForProtocol(pattern.protocol ?? urlObj.protocol);
|
|
598
571
|
if (expectedPort !== urlObj.port)
|
|
599
572
|
return undefined;
|
|
600
573
|
}
|
|
@@ -616,8 +589,7 @@ function matchFastPathPattern(pattern, urlObj) {
|
|
|
616
589
|
const suffix = urlObj.pathname.slice(prefix.length);
|
|
617
590
|
if (suffix.startsWith("//"))
|
|
618
591
|
return undefined;
|
|
619
|
-
if (pattern.pathMode === "segments" &&
|
|
620
|
-
!isNonEmptyPathSegments(suffix)) {
|
|
592
|
+
if (pattern.pathMode === "segments" && !isNonEmptyPathSegments(suffix)) {
|
|
621
593
|
return undefined;
|
|
622
594
|
}
|
|
623
595
|
return suffix;
|
|
@@ -629,7 +601,7 @@ function matchFastPathPattern(pattern, urlObj) {
|
|
|
629
601
|
* @returns {boolean}
|
|
630
602
|
*/
|
|
631
603
|
function isNonEmptyPathSegments(pathname) {
|
|
632
|
-
return pathname.length > 1 && !pathname.endsWith("/") && !pathname.includes("//");
|
|
604
|
+
return (pathname.length > 1 && !pathname.endsWith("/") && !pathname.includes("//"));
|
|
633
605
|
}
|
|
634
606
|
/**
|
|
635
607
|
* URLPattern treats the default port as empty in URL instances.
|
|
@@ -656,8 +628,7 @@ function applyFastPathPattern(pattern, suffix, source) {
|
|
|
656
628
|
localized.protocol = pattern.protocol;
|
|
657
629
|
if (pattern.hostname !== undefined) {
|
|
658
630
|
localized.hostname = pattern.hostname;
|
|
659
|
-
localized.port =
|
|
660
|
-
pattern.port ?? defaultPortForProtocol(localized.protocol);
|
|
631
|
+
localized.port = pattern.port ?? defaultPortForProtocol(localized.protocol);
|
|
661
632
|
}
|
|
662
633
|
localized.pathname = joinFastPathPrefix(pattern.pathnamePrefix, suffix);
|
|
663
634
|
return localized;
|