UNPKG

@redocly/theme

Version:

Shared UI components lib

135 lines (111 loc) 4.15 kB
import type { Locale } from '@redocly/theme/core/types'; import { DEFAULT_LOCALE_PLACEHOLDER } from '@redocly/theme/core/constants'; export function combineUrls(baseURL: string, ...relativeURLs: (string | undefined)[]) { let res = baseURL; for (let relativeURL of relativeURLs) { res = relativeURL ? res.replace(/[\/\\]+$/, '') + '/' + relativeURL.replace(/^[\/\\]+/, '') : res; } return res; } export function withPathPrefix(url: string) { return combineUrls(getPathPrefix(), url); } export function withoutPathPrefix(pathname: string) { const pathPrefix = getPathPrefix(); return pathPrefix && pathname.startsWith(pathPrefix) ? pathname.slice(pathPrefix.length) : pathname; } export function withoutHash(url: undefined | null): undefined; export function withoutHash(url: string): string; export function withoutHash(url: string | undefined): string | undefined; export function withoutHash(url: string | undefined | null): string | undefined { if (url == null) return undefined; return url.split('#')[0]; } /** * * @returns url with leading and without trailing slash or empty string, e.g. '/prefix' */ export function getPathPrefix() { if (process.env.REDOCLY_PREFIX_PATHS) { return normalizePathPrefix(process.env.REDOCLY_PREFIX_PATHS); } return ''; } export function normalizePathPrefix(prefix: string) { const withoutTrailing = removeTrailingSlash(prefix); return addLeadingSlash(withoutTrailing === '.' ? '' : withoutTrailing); } export function addLeadingSlash(url: string): string { return url.startsWith('/') ? url : `/${url}`; } export function removeTrailingSlash(url: string): string { return url.endsWith('/') ? url.substring(0, url.length - 1) : url; } export function removeLeadingSlash(url: string): string { return url.startsWith('/') ? url.substring(1) : url; } export function isPathInFolder(child: string, parent: string): boolean { parent = removeTrailingSlash(removeLeadingSlash(slash(parent))); child = removeTrailingSlash(removeLeadingSlash(slash(child))); return child === parent || child.startsWith(parent + '/'); } /** * Convert Windows backslash paths to slash paths: foo\\bar ➔ foo/bar * * @param path * @return slashed path */ export function slash(path: string): string { const isExtendedLengthPath = /^\\\\\?\\/.test(path); if (isExtendedLengthPath) { return path; } return path.replace(/\\/g, `/`); } export function addTrailingSlash(url: string): string { return url.endsWith('/') ? url : `${url}/`; } /** * Adds locale to pathname, or replaces current locale in pathname with a new one * @param originalPathname - Pathname without path prefix * @param defaultLocale - Default locale code * @param newLocale - New locale code to apply * @param allLocales - Array of all available locales */ export function getPathnameForLocale( originalPathname: string, defaultLocale: string, newLocale: string, allLocales: Locale[], ) { const currentLocale = getLocaleFromPathname(originalPathname, defaultLocale, allLocales); if (currentLocale === newLocale) { return originalPathname; } const pathnameWithoutLocale = currentLocale === defaultLocale ? originalPathname : originalPathname.slice(currentLocale.length + 1); const newLocalePrefix = newLocale === defaultLocale ? '' : '/' + newLocale; return `${newLocalePrefix.toLowerCase()}${pathnameWithoutLocale}`; } /** * Extracts the locale code from a pathname * @param pathname - URL pathname to extract locale from without path prefix * @param defaultLocale - Default locale code to return if no locale found in pathname * @param allLocales - Array of all available locales to check against * @returns The locale code from the pathname, or the default locale if none found */ export function getLocaleFromPathname( pathname: string, defaultLocale: string = DEFAULT_LOCALE_PLACEHOLDER, allLocales: Locale[] = [], ) { const maybeLocale = pathname?.split('/')[1]; const locale = allLocales.find((locale) => locale.code.toLowerCase() === maybeLocale); return locale?.code || defaultLocale; }