| | import { languageKeys } from '@/languages/lib/languages-server' |
| | import nonEnterpriseDefaultVersion from '@/versions/lib/non-enterprise-default-version' |
| | import { allVersions } from '@/versions/lib/all-versions' |
| | import { |
| | latest, |
| | latestStable, |
| | supported, |
| | deprecatedWithFunctionalRedirects, |
| | } from '@/versions/lib/enterprise-server-releases' |
| | import { getPathWithLanguage, getVersionStringFromPath } from '@/frame/lib/path-utils' |
| |
|
| | import type { Context } from '@/types' |
| |
|
| | const languagePrefixRegex = new RegExp(`^/(${languageKeys.join('|')})/`) |
| | const nonEnterpriseDefaultVersionPrefix = `/${nonEnterpriseDefaultVersion}` |
| |
|
| | const supportedAndRecentlyDeprecated = [...supported, ...deprecatedWithFunctionalRedirects] |
| |
|
| | export function splitPathByLanguage(uri: string, userLanguage?: string): [string, string] { |
| | let language = userLanguage || 'en' |
| | let withoutLanguage = uri |
| | if (languagePrefixRegex.test(uri)) { |
| | const match = uri.match(languagePrefixRegex) |
| | if (match) { |
| | language = match[1] |
| | withoutLanguage = uri.replace(languagePrefixRegex, '/') |
| | } |
| | } |
| | return [language, withoutLanguage] |
| | } |
| |
|
| | |
| | export default function getRedirect(uri: string, context: Context): string | undefined { |
| | const { redirects, userLanguage } = context |
| |
|
| | if (!redirects) { |
| | return undefined |
| | } |
| |
|
| | const [language, withoutLanguage] = splitPathByLanguage(uri, userLanguage) |
| |
|
| | if (withoutLanguage.startsWith('/github-ae@latest')) { |
| | |
| | |
| | |
| | const nonAERedirect = githubAERedirect(uri, context) |
| | if (nonAERedirect.includes('/github-ae@latest')) { |
| | |
| | |
| | throw new Error('Still going to github-ae@latest URL') |
| | } |
| | return nonAERedirect |
| | } |
| |
|
| | let destination: string | undefined |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | if (withoutLanguage in redirects) { |
| | |
| | if (redirects[withoutLanguage].includes('://')) { |
| | return redirects[withoutLanguage] |
| | } |
| | return getPathWithLanguage(redirects[withoutLanguage], language) |
| | } |
| |
|
| | let basicCorrection: string | undefined |
| |
|
| | if (withoutLanguage.startsWith(nonEnterpriseDefaultVersionPrefix)) { |
| | |
| | basicCorrection = `/${language}${withoutLanguage.replace(nonEnterpriseDefaultVersionPrefix, '')}` |
| | } else if (withoutLanguage.replace('/', '') in allVersions && !languagePrefixRegex.test(uri)) { |
| | |
| | basicCorrection = `/${language}${withoutLanguage}` |
| | return basicCorrection |
| | } |
| |
|
| | if ( |
| | withoutLanguage === '/enterprise-server' || |
| | withoutLanguage.startsWith('/enterprise-server/') |
| | ) { |
| | |
| | basicCorrection = `/${language}${withoutLanguage.replace( |
| | '/enterprise-server', |
| | `/enterprise-server@${latestStable}`, |
| | )}` |
| | |
| | if (withoutLanguage === '/enterprise-server') { |
| | return basicCorrection |
| | } |
| | } else if (withoutLanguage.startsWith('/enterprise-server@latest')) { |
| | |
| | basicCorrection = `/${language}${withoutLanguage.replace( |
| | '/enterprise-server@latest', |
| | `/enterprise-server@${latestStable}`, |
| | )}` |
| | |
| | |
| | if (withoutLanguage === '/enterprise-server@latest') { |
| | return basicCorrection |
| | } |
| | } else if ( |
| | withoutLanguage.startsWith('/enterprise/') && |
| | supportedAndRecentlyDeprecated.includes(withoutLanguage.split('/')[2]) |
| | ) { |
| | |
| |
|
| | |
| | |
| | |
| | const version = withoutLanguage.split('/')[2] |
| | if (withoutLanguage === `/enterprise/${version}`) { |
| | |
| | basicCorrection = `/${language}${withoutLanguage.replace( |
| | `/enterprise/${version}`, |
| | `/enterprise-server@${version}`, |
| | )}` |
| | return basicCorrection |
| | } else { |
| | basicCorrection = `/${language}${withoutLanguage.replace( |
| | `/enterprise/${version}/`, |
| | `/enterprise-server@${version}/`, |
| | )}` |
| | } |
| | } else if (withoutLanguage === '/enterprise') { |
| | |
| | basicCorrection = `/${language}/enterprise-server@${latest}` |
| | return basicCorrection |
| | } else if ( |
| | withoutLanguage.startsWith('/enterprise/') && |
| | !supported.includes(withoutLanguage.split('/')[2]) |
| | ) { |
| | |
| | |
| | |
| | |
| | basicCorrection = `/${language}${withoutLanguage |
| | .replace(`/enterprise/`, `/enterprise-server@${latest}/`) |
| | .replace('/user/', '/')}` |
| | } else if (withoutLanguage.startsWith('/insights')) { |
| | |
| | basicCorrection = uri.replace('/insights', `${language}/enterprise-server@${latest}/insights`) |
| | } |
| |
|
| | if (basicCorrection) { |
| | return getRedirect(basicCorrection, context) || basicCorrection |
| | } |
| |
|
| | if (withoutLanguage.startsWith('/admin/')) { |
| | const prefix = `/enterprise-server@${latest}` |
| | let suffix = withoutLanguage |
| | if (suffix.startsWith('/admin/guides/')) { |
| | suffix = suffix.replace('/admin/guides/', '/admin/') |
| | } |
| | const newURL = prefix + suffix |
| | destination = redirects[newURL] || newURL |
| | } else if ( |
| | withoutLanguage.split('/')[1].includes('@') && |
| | withoutLanguage.split('/')[1] in allVersions |
| | ) { |
| | |
| | const majorVersion = withoutLanguage.split('/')[1].split('@')[0] |
| | const split = withoutLanguage.split('/') |
| | const version = split[1].split('@')[1] |
| | let prefix: string |
| | let suffix: string |
| |
|
| | if (supported.includes(version) || version === 'latest') { |
| | prefix = `/${majorVersion}@${version}` |
| | suffix = `/${split.slice(2).join('/')}` |
| |
|
| | if ( |
| | suffix.includes('/user') || |
| | suffix.startsWith('/admin/guide') || |
| | suffix.startsWith('/articles/user') |
| | ) { |
| | suffix = tryReplacements(prefix, suffix, context) || suffix |
| | } |
| | } else { |
| | |
| | prefix = `/${majorVersion}@${version}` |
| | suffix = `/${split.slice(2).join('/')}` |
| | } |
| |
|
| | const newURL = prefix + suffix |
| | if (newURL !== withoutLanguage) { |
| | |
| | destination = redirects[newURL] || newURL |
| | } else { |
| | destination = redirects[newURL] |
| | } |
| | } else if (withoutLanguage.startsWith('/desktop/guides/')) { |
| | |
| | const newURL = withoutLanguage.replace('/desktop/guides/', '/desktop/') |
| | destination = redirects[newURL] || newURL |
| | } else { |
| | destination = redirects[withoutLanguage] |
| | } |
| |
|
| | if (destination !== undefined) { |
| | |
| | |
| | return `/${language}${destination}` |
| | } |
| |
|
| | return undefined |
| | } |
| |
|
| | function githubAERedirect(uri: string, context: Context): string { |
| | const { redirects, userLanguage, pages } = context |
| |
|
| | if (!redirects || !pages) { |
| | |
| | const [language] = splitPathByLanguage(uri, userLanguage) |
| | return `/${language}` |
| | } |
| |
|
| | const [language, withoutLanguage] = splitPathByLanguage(uri, userLanguage) |
| |
|
| | |
| | |
| | const cloudEquivalent = uri.replace('/github-ae@latest', '/enterprise-cloud@latest') |
| | const fptEquivalent = uri.replace('/github-ae@latest', '') |
| | const withoutVersion = withoutLanguage.replace('/github-ae@latest', '') |
| | if (!withoutVersion) { |
| | |
| | |
| | |
| | |
| | if (uri.startsWith('/github-ae@latest')) { |
| | return `/${language}${cloudEquivalent}` |
| | } |
| | return cloudEquivalent |
| | } |
| |
|
| | |
| | |
| | if (uri.startsWith('/github-ae@latest')) { |
| | const languageCloudEquivalent = `/${language}${cloudEquivalent}` |
| | if (languageCloudEquivalent in pages) { |
| | return languageCloudEquivalent |
| | } |
| |
|
| | const languageFptEquivalent = `/${language}${fptEquivalent}` |
| | if (languageFptEquivalent in pages) { |
| | return languageFptEquivalent |
| | } |
| | } else { |
| | |
| | if (cloudEquivalent in pages) { |
| | return cloudEquivalent |
| | } |
| | if (fptEquivalent in pages) { |
| | return fptEquivalent |
| | } |
| | } |
| |
|
| | |
| | |
| | const legacyRedirect = redirects[withoutLanguage] |
| | if (legacyRedirect && !legacyRedirect.includes('/github-ae@latest')) { |
| | if (legacyRedirect.includes('://')) { |
| | return legacyRedirect |
| | } |
| | return `/${language}${legacyRedirect}` |
| | } |
| |
|
| | |
| | |
| | |
| | if (redirects[withoutVersion]) { |
| | const cloudCandidate = `/${language}/enterprise-cloud@latest${redirects[withoutVersion]}` |
| | if (cloudCandidate in pages) { |
| | return cloudCandidate |
| | } |
| |
|
| | const fptCandidate = `/${language}${redirects[withoutVersion]}` |
| | |
| | |
| | if (fptCandidate in pages) { |
| | const versionFromCandidate = getVersionStringFromPath(fptCandidate) |
| | if ( |
| | !( |
| | versionFromCandidate.startsWith('enterprise-server@') || |
| | versionFromCandidate === 'github-ae@latest' |
| | ) |
| | ) { |
| | return fptCandidate |
| | } |
| | } |
| | } |
| |
|
| | |
| | return `/${language}` |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | function tryReplacements(prefix: string, suffix: string, context: Context): string | undefined { |
| | const { pages, redirects } = context |
| |
|
| | if (!pages || !redirects) { |
| | return undefined |
| | } |
| |
|
| | const test = (testSuffix: string): boolean => { |
| | |
| | |
| | |
| | if (testSuffix.includes('/rest')) { |
| | return false |
| | } |
| | const candidateAsRedirect = prefix + testSuffix |
| | const candidateAsURL = `/en${candidateAsRedirect}` |
| | return candidateAsRedirect in redirects || candidateAsURL in pages |
| | } |
| |
|
| | let attempt = suffix.replace('/user', '/github') |
| | if (test(attempt)) return attempt |
| |
|
| | attempt = suffix.replace('/user', '') |
| | if (test(attempt)) return attempt |
| |
|
| | attempt = suffix.replace('/admin/guides', '/admin') |
| | if (test(attempt)) return attempt |
| |
|
| | attempt = suffix.replace('/admin/guides/user', '/admin/github') |
| | if (test(attempt)) return attempt |
| |
|
| | attempt = suffix.replace('/admin/guides', '/admin').replace('/user', '/github') |
| | if (test(attempt)) return attempt |
| |
|
| | return undefined |
| | } |
| |
|