'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var utils = require('../shared/utils.js'); function getInternalTemplate(pathnames, pathname, locale) { const sortedPathnames = utils.getSortedPathnames(Object.keys(pathnames)); // Try to find a localized pathname that matches for (const internalPathname of sortedPathnames) { const localizedPathnamesOrPathname = pathnames[internalPathname]; if (typeof localizedPathnamesOrPathname === 'string') { const localizedPathname = localizedPathnamesOrPathname; if (utils.matchesPathname(localizedPathname, pathname)) { return [undefined, internalPathname]; } } else { // Prefer the entry with the current locale in case multiple // localized pathnames match the current pathname const sortedEntries = Object.entries(localizedPathnamesOrPathname); const curLocaleIndex = sortedEntries.findIndex(_ref => { let [entryLocale] = _ref; return entryLocale === locale; }); if (curLocaleIndex > 0) { sortedEntries.unshift(sortedEntries.splice(curLocaleIndex, 1)[0]); } for (const [entryLocale, entryPathname] of sortedEntries) { if (utils.matchesPathname(entryPathname, pathname)) { return [entryLocale, internalPathname]; } } } } // Try to find an internal pathname that matches (this can be the case // if all localized pathnames are different from the internal pathnames) for (const internalPathname of Object.keys(pathnames)) { if (utils.matchesPathname(internalPathname, pathname)) { return [undefined, internalPathname]; } } // No match return [undefined, undefined]; } function formatTemplatePathname(sourcePathname, sourceTemplate, targetTemplate, prefix) { const params = getRouteParams(sourceTemplate, sourcePathname); let targetPathname = ''; targetPathname += formatPathnameTemplate(targetTemplate, params); // A pathname with an optional catchall like `/categories/[[...slug]]` // should be normalized to `/categories` if the catchall is not present // and no trailing slash is configured targetPathname = utils.normalizeTrailingSlash(targetPathname); return targetPathname; } /** * Removes potential prefixes from the pathname. */ function getNormalizedPathname(pathname, locales, localePrefix) { // Add trailing slash for consistent handling // both for the root as well as nested paths if (!pathname.endsWith('/')) { pathname += '/'; } const localePrefixes = getLocalePrefixes(locales, localePrefix); const regex = new RegExp("^(".concat(localePrefixes.map(_ref2 => { let [, prefix] = _ref2; return prefix.replaceAll('/', '\\/'); }).join('|'), ")/(.*)"), 'i'); const match = pathname.match(regex); let result = match ? '/' + match[2] : pathname; if (result !== '/') { result = utils.normalizeTrailingSlash(result); } return result; } function getLocalePrefixes(locales, localePrefix) { let sort = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; const prefixes = locales.map(locale => [locale, utils.getLocalePrefix(locale, localePrefix)]); if (sort) { // More specific ones first prefixes.sort((a, b) => b[1].length - a[1].length); } return prefixes; } function getPathnameMatch(pathname, locales, localePrefix) { const localePrefixes = getLocalePrefixes(locales, localePrefix); for (const [locale, prefix] of localePrefixes) { let exact, matches; if (pathname === prefix || pathname.startsWith(prefix + '/')) { exact = matches = true; } else { const normalizedPathname = pathname.toLowerCase(); const normalizedPrefix = prefix.toLowerCase(); if (normalizedPathname === normalizedPrefix || normalizedPathname.startsWith(normalizedPrefix + '/')) { exact = false; matches = true; } } if (matches) { return { locale, prefix, matchedPrefix: pathname.slice(0, prefix.length), exact }; } } } function getRouteParams(template, pathname) { const normalizedPathname = utils.normalizeTrailingSlash(pathname); const normalizedTemplate = utils.normalizeTrailingSlash(template); const regex = utils.templateToRegex(normalizedTemplate); const match = regex.exec(normalizedPathname); if (!match) return undefined; const params = {}; for (let i = 1; i < match.length; i++) { var _normalizedTemplate$m; const key = (_normalizedTemplate$m = normalizedTemplate.match(/\[([^\]]+)\]/g)) === null || _normalizedTemplate$m === void 0 ? void 0 : _normalizedTemplate$m[i - 1].replace(/[[\]]/g, ''); if (key) params[key] = match[i]; } return params; } function formatPathnameTemplate(template, params) { if (!params) return template; // Simplify syntax for optional catchall ('[[...slug]]') so // we can replace the value with simple interpolation template = template.replace(/\[\[/g, '[').replace(/\]\]/g, ']'); let result = template; Object.entries(params).forEach(_ref3 => { let [key, value] = _ref3; result = result.replace("[".concat(key, "]"), value); }); return result; } function formatPathname(pathname, prefix, search) { let result = pathname; if (prefix) { result = utils.prefixPathname(prefix, result); } if (search) { result += search; } return result; } function getHost(requestHeaders) { var _ref4, _requestHeaders$get; return (_ref4 = (_requestHeaders$get = requestHeaders.get('x-forwarded-host')) !== null && _requestHeaders$get !== void 0 ? _requestHeaders$get : requestHeaders.get('host')) !== null && _ref4 !== void 0 ? _ref4 : undefined; } function isLocaleSupportedOnDomain(locale, domain) { return domain.defaultLocale === locale || !domain.locales || domain.locales.includes(locale); } function getBestMatchingDomain(curHostDomain, locale, domainsConfig) { let domainConfig; // Prio 1: Stay on current domain if (curHostDomain && isLocaleSupportedOnDomain(locale, curHostDomain)) { domainConfig = curHostDomain; } // Prio 2: Use alternative domain with matching default locale if (!domainConfig) { domainConfig = domainsConfig.find(cur => cur.defaultLocale === locale); } // Prio 3: Use alternative domain with restricted matching locale if (!domainConfig) { domainConfig = domainsConfig.find(cur => { var _cur$locales; return (_cur$locales = cur.locales) === null || _cur$locales === void 0 ? void 0 : _cur$locales.includes(locale); }); } // Prio 4: Stay on the current domain if it supports all locales if (!domainConfig && (curHostDomain === null || curHostDomain === void 0 ? void 0 : curHostDomain.locales) == null) { domainConfig = curHostDomain; } // Prio 5: Use alternative domain that supports all locales if (!domainConfig) { domainConfig = domainsConfig.find(cur => !cur.locales); } return domainConfig; } function applyBasePath(pathname, basePath) { return utils.normalizeTrailingSlash(basePath + pathname); } function getLocaleAsPrefix(locale) { return "/".concat(locale); } function sanitizePathname(pathname) { // Sanitize malicious URIs, e.g.: // '/en/\\example.org → /en/%5C%5Cexample.org' // '/en////example.org → /en/example.org' return pathname.replace(/\\/g, '%5C').replace(/\/+/g, '/'); } exports.applyBasePath = applyBasePath; exports.formatPathname = formatPathname; exports.formatPathnameTemplate = formatPathnameTemplate; exports.formatTemplatePathname = formatTemplatePathname; exports.getBestMatchingDomain = getBestMatchingDomain; exports.getHost = getHost; exports.getInternalTemplate = getInternalTemplate; exports.getLocaleAsPrefix = getLocaleAsPrefix; exports.getLocalePrefixes = getLocalePrefixes; exports.getNormalizedPathname = getNormalizedPathname; exports.getPathnameMatch = getPathnameMatch; exports.getRouteParams = getRouteParams; exports.isLocaleSupportedOnDomain = isLocaleSupportedOnDomain; exports.sanitizePathname = sanitizePathname;