@redocly/theme
Version:
Shared UI components lib
135 lines (111 loc) • 4.15 kB
text/typescript
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;
}