@@ -9,25 +9,34 @@ import {
99} from '#src/versions/lib/enterprise-server-releases.js'
1010import { getPathWithLanguage , getVersionStringFromPath } from '#src/frame/lib/path-utils.js'
1111
12+ import type { Context } from '@/types.js'
13+
1214const languagePrefixRegex = new RegExp ( `^/(${ languageKeys . join ( '|' ) } )/` )
1315const nonEnterpriseDefaultVersionPrefix = `/${ nonEnterpriseDefaultVersion } `
1416
1517const supportedAndRecentlyDeprecated = [ ...supported , ...deprecatedWithFunctionalRedirects ]
1618
17- export function splitPathByLanguage ( uri , userLanguage ) {
19+ export function splitPathByLanguage ( uri : string , userLanguage ?: string ) : [ string , string ] {
1820 let language = userLanguage || 'en'
1921 let withoutLanguage = uri
2022 if ( languagePrefixRegex . test ( uri ) ) {
21- language = uri . match ( languagePrefixRegex ) [ 1 ]
22- withoutLanguage = uri . replace ( languagePrefixRegex , '/' )
23+ const match = uri . match ( languagePrefixRegex )
24+ if ( match ) {
25+ language = match [ 1 ]
26+ withoutLanguage = uri . replace ( languagePrefixRegex , '/' )
27+ }
2328 }
2429 return [ language , withoutLanguage ]
2530}
2631
2732// Return the new URI if there is one, otherwise return undefined.
28- export default function getRedirect ( uri , context ) {
33+ export default function getRedirect ( uri : string , context : Context ) : string | undefined {
2934 const { redirects, userLanguage } = context
3035
36+ if ( ! redirects ) {
37+ return undefined
38+ }
39+
3140 const [ language , withoutLanguage ] = splitPathByLanguage ( uri , userLanguage )
3241
3342 if ( withoutLanguage . startsWith ( '/github-ae@latest' ) ) {
@@ -43,7 +52,7 @@ export default function getRedirect(uri, context) {
4352 return nonAERedirect
4453 }
4554
46- let destination
55+ let destination : string | undefined
4756
4857 // `redirects` is sourced from more than one thing. The primary use
4958 // case is gathering up the `redirect_from` frontmatter key.
@@ -60,7 +69,7 @@ export default function getRedirect(uri, context) {
6069 return getPathWithLanguage ( redirects [ withoutLanguage ] , language )
6170 }
6271
63- let basicCorrection
72+ let basicCorrection : string | undefined
6473
6574 if ( withoutLanguage . startsWith ( nonEnterpriseDefaultVersionPrefix ) ) {
6675 // E.g. '/free-pro-team@latest/foo/bar' or '/free-pro-team@latest'
@@ -157,8 +166,8 @@ export default function getRedirect(uri, context) {
157166 const majorVersion = withoutLanguage . split ( '/' ) [ 1 ] . split ( '@' ) [ 0 ]
158167 const split = withoutLanguage . split ( '/' )
159168 const version = split [ 1 ] . split ( '@' ) [ 1 ]
160- let prefix
161- let suffix
169+ let prefix : string
170+ let suffix : string
162171
163172 if ( supported . includes ( version ) || version === 'latest' ) {
164173 prefix = `/${ majorVersion } @${ version } `
@@ -171,6 +180,10 @@ export default function getRedirect(uri, context) {
171180 ) {
172181 suffix = tryReplacements ( prefix , suffix , context ) || suffix
173182 }
183+ } else {
184+ // If version is not supported, we still need to set these values
185+ prefix = `/${ majorVersion } @${ version } `
186+ suffix = '/' + split . slice ( 2 ) . join ( '/' )
174187 }
175188
176189 const newURL = prefix + suffix
@@ -193,11 +206,19 @@ export default function getRedirect(uri, context) {
193206 // to the destination URL.
194207 return `/${ language } ${ destination } `
195208 }
209+
210+ return undefined
196211}
197212
198- function githubAERedirect ( uri , context ) {
213+ function githubAERedirect ( uri : string , context : Context ) : string {
199214 const { redirects, userLanguage, pages } = context
200215
216+ if ( ! redirects || ! pages ) {
217+ // Fallback to home page if context is incomplete
218+ const [ language ] = splitPathByLanguage ( uri , userLanguage )
219+ return `/${ language } `
220+ }
221+
201222 const [ language , withoutLanguage ] = splitPathByLanguage ( uri , userLanguage )
202223
203224 // From now on, github-ae@latest redirects to enterprise-cloud or
@@ -283,8 +304,14 @@ function githubAERedirect(uri, context) {
283304// This function tries different string replacement on the suffix
284305// (the pathname after the language and version part) until it
285306// finds one string replacement that yields either a page or a redirect.
286- function tryReplacements ( prefix , suffix , { pages, redirects } ) {
287- const test = ( suffix ) => {
307+ function tryReplacements ( prefix : string , suffix : string , context : Context ) : string | undefined {
308+ const { pages, redirects } = context
309+
310+ if ( ! pages || ! redirects ) {
311+ return undefined
312+ }
313+
314+ const test = ( suffix : string ) : boolean => {
288315 // This is a generally broad search and replace and this particular
289316 // replacement has never been present in api documentation only enterprise
290317 // admin documentation, so we're excluding the REST api pages
@@ -310,4 +337,6 @@ function tryReplacements(prefix, suffix, { pages, redirects }) {
310337
311338 attempt = suffix . replace ( '/admin/guides' , '/admin' ) . replace ( '/user' , '/github' )
312339 if ( test ( attempt ) ) return attempt
340+
341+ return undefined
313342}
0 commit comments