UNPKG

@intlayer/core

Version:

Includes core Intlayer functions like translation, dictionary, and utility functions shared across multiple packages.

117 lines (115 loc) 4.8 kB
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); //#region src/localization/rewriteUtils.ts /** * True when rewrite rules are explicitly disabled at build time * (INTLAYER_ROUTING_REWRITE_RULES === 'false'). */ const TREE_SHAKE_REWRITE = process.env["INTLAYER_ROUTING_REWRITE_RULES"] === "false"; /** * Normalizes legacy Record format or extracts specialized rules from RewriteObject. */ const getRewriteRules = (rewrite, context = "url") => { if (!rewrite || TREE_SHAKE_REWRITE) return void 0; if ("url" in rewrite) return rewrite[context]; return { rules: Object.entries(rewrite).map(([canonical, localized]) => ({ canonical: canonical.startsWith("/") ? canonical.replace(/\[([^\]]+)\]/g, ":$1") : `/${canonical.replace(/\[([^\]]+)\]/g, ":$1")}`, localized: Object.fromEntries(Object.entries(localized).map(([locale, pattern]) => { return [locale, pattern?.startsWith("/") ? pattern.replace(/\[([^\]]+)\]/g, ":$1") : `/${(pattern || "").replace(/\[([^\]]+)\]/g, ":$1")}`]; })) })) }; }; /** * Converts normalized pattern to Regex. * Internal syntax supports: * - :param -> ([^/]+) (one segment) * - :param* -> (.*) (zero or more segments) * - :param+ -> (.+) (one or more segments) * - :param? -> ([^/]*) (zero or one segment) */ const patternToRegex = (pattern) => { const regexString = pattern.replace(/\//g, "\\/").replace(/\\\/:(?:[^/\\*+?]+)\*/g, "(?:\\/(.*))?").replace(/\\\/:(?:[^/\\*+?]+)\?/g, "(?:\\/([^\\/]+))?").replace(/:([^/\\*+?]+)\*/g, "(.*)").replace(/:([^/\\*+?]+)\?/g, "([^\\/]*)").replace(/:([^/\\*+?]+)\+/g, "(.+)").replace(/:([^/\\*+?]+)/g, "([^\\/]+)"); return new RegExp(`^${regexString}$`); }; /** * Replaces route parameters in a path with provided values. */ const fillPath = (pattern, params) => { let index = 0; return pattern.replace(/:([^/\\*+?]+)[*+?]?/g, () => params[index++] ?? "").replace(/\/+/g, "/").replace(/\/$/, "") || "/"; }; /** * Extract values from a URL based on a pattern. */ const extractParams = (url, pattern) => { const regex = patternToRegex(pattern); const match = url.match(regex); return match ? match.slice(1) : null; }; /** * Given a localized URL (e.g., "/produits/123"), finds the canonical internal path (e.g., "/products/123"). * If locale is provided, only check for that locale. Otherwise, check for all locales. */ const getCanonicalPath = (localizedPath, locale, rewriteRules) => { if (!rewriteRules || TREE_SHAKE_REWRITE) return localizedPath; for (const rule of rewriteRules.rules) { const { canonical, localized } = rule; const localesToCheck = locale ? [locale] : Object.keys(localized); for (const loc of localesToCheck) { const localizedPattern = localized[loc]; if (!localizedPattern) continue; const params = extractParams(localizedPath, localizedPattern); if (params) return fillPath(canonical, params); } } return localizedPath; }; /** * Given a canonical path (e.g., "/products/123"), finds the localized URL pattern (e.g., "/produits/123"). */ const getLocalizedPath = (canonicalPath, locale, rewriteRules) => { if (!rewriteRules || TREE_SHAKE_REWRITE) return { path: canonicalPath, isRewritten: false }; for (const rule of rewriteRules.rules) { const { canonical, localized } = rule; const params = extractParams(canonicalPath, canonical); if (params) { const targetPattern = localized[locale]; if (targetPattern) return { path: fillPath(targetPattern, params), isRewritten: true }; } } return { path: canonicalPath, isRewritten: false }; }; /** * Returns the internal path for a given canonical path and locale. * Ensures the locale prefix is present exactly once. */ const getInternalPath = (canonicalPath, locale) => { const pathWithLeadingSlash = canonicalPath.startsWith("/") ? canonicalPath : `/${canonicalPath}`; if (pathWithLeadingSlash.startsWith(`/${locale}/`) || pathWithLeadingSlash === `/${locale}`) return pathWithLeadingSlash; return `/${locale}${pathWithLeadingSlash === "/" ? "" : pathWithLeadingSlash}`; }; /** * Given a current pathname and locale, returns the pretty localized path if a rewrite rule exists and the path is not already localized. */ const getRewritePath = (pathname, locale, rewrite) => { if (TREE_SHAKE_REWRITE) return void 0; const rules = getRewriteRules(rewrite, "url"); if (!rules) return void 0; const { path: localizedPath, isRewritten } = getLocalizedPath(getCanonicalPath(pathname, void 0, rules), locale, rules); if (isRewritten && localizedPath !== pathname) return localizedPath; }; //#endregion exports.getCanonicalPath = getCanonicalPath; exports.getInternalPath = getInternalPath; exports.getLocalizedPath = getLocalizedPath; exports.getRewritePath = getRewritePath; exports.getRewriteRules = getRewriteRules; //# sourceMappingURL=rewriteUtils.cjs.map