-
Notifications
You must be signed in to change notification settings - Fork 68.3k
Expand file tree
/
Copy pathpath-utils.ts
More file actions
169 lines (139 loc) · 6.09 KB
/
Copy pathpath-utils.ts
File metadata and controls
169 lines (139 loc) · 6.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import slash from 'slash'
import path from 'path'
import patterns from './patterns'
import { latest } from '@/versions/lib/enterprise-server-releases'
import { productIds } from '@/products/lib/all-products'
import { allVersions } from '@/versions/lib/all-versions'
import nonEnterpriseDefaultVersion from '@/versions/lib/non-enterprise-default-version'
const supportedVersions = new Set(Object.keys(allVersions))
// Extracts the language code from the path
// if href is '/en/something', returns 'en'
export function getLangFromPath(href: string | undefined): string | null {
if (!href) return null
// first remove the version from the path so we don't match, say, `/free-pro-team` as `/fr/`
const match = getPathWithoutVersion(href).match(patterns.getLanguageCode)
return match ? match[1] : null
}
// Add the language to the given HREF
// /articles/foo -> /en/articles/foo
export function getPathWithLanguage(href: string | undefined, languageCode: string): string {
if (!href) return `/${languageCode}`
return slash(path.posix.join('/', languageCode, getPathWithoutLanguage(href))).replace(
patterns.trailingSlash,
'$1',
)
}
// Remove the language from the given HREF
// /en/articles/foo -> /articles/foo
export function getPathWithoutLanguage(href: string | undefined): string {
if (!href) return '/'
return slash(href.replace(patterns.hasLanguageCode, '/'))
}
// Remove the version segment from the path
export function getPathWithoutVersion(href: string | undefined): string {
if (!href) return '/'
const versionFromPath = getVersionStringFromPath(href)
// If the derived version is not found in the list of all versions, just return the HREF
return allVersions[versionFromPath]
? href.replace(`/${getVersionStringFromPath(href)}`, '')
: href
}
// Return the version segment in a path
export function getVersionStringFromPath(
href: string | undefined,
supportedOnly: true,
): string | undefined
export function getVersionStringFromPath(href: string | undefined, supportedOnly?: false): string
export function getVersionStringFromPath(
href: string | undefined,
supportedOnly = false,
): string | undefined {
if (!href) return nonEnterpriseDefaultVersion
href = getPathWithoutLanguage(href)
// Some URLs don't ever have a version in the URL and it won't be found
// if you continue digging deeper. So exit early with the default on these.
if (['/', '/categories.json'].includes(href)) {
return nonEnterpriseDefaultVersion
}
// Get the first segment
const versionFromPath = href.split('/')[1]
// If the first segment is a supported product, assume this is FPT
if (productIds.includes(versionFromPath)) {
return nonEnterpriseDefaultVersion
}
// Otherwise, check if it's a supported version
if (supportedVersions.has(versionFromPath)) {
return versionFromPath
}
// If the version segment is the latest enterprise-server release, return the latest release
if (versionFromPath === 'enterprise-server@latest') {
return `enterprise-server@${latest}`
}
// If it's just a plan with no @release (e.g., `enterprise-server`), return the latest release
const planObject = Object.values(allVersions).find((v) => v.plan === versionFromPath)
if (planObject) {
return allVersions[planObject.latestVersion].version
}
// If the caller of this function explicitly wants to know if the
// version part is *not* supported, they get back `undefined`.
// But this function is used in many other places where it potentially
// doesn't care if the version is supported.
// For example, in lib/redirects/permalinks.ts it needs to know if the
// URL didn't contain a valid version.
if (supportedOnly) {
return
}
// Otherwise, return the first segment as-is, which may not be a real supported version,
// but additional checks are done on this segment in getVersionedPathWithoutLanguage
return versionFromPath
}
// Return the corresponding object for the version segment in a path
export function getVersionObjectFromPath(href: string | undefined) {
const versionFromPath = getVersionStringFromPath(href, false)
return allVersions[versionFromPath]
}
// Return the product segment from the path
// Extracts the product identifier from various URL patterns including versioned paths
export function getProductStringFromPath(href: string | undefined): string {
// Handle empty or undefined paths
if (!href) return 'homepage'
const normalizedHref = getPathWithoutLanguage(href)
if (normalizedHref === '/') return 'homepage'
// Split path into segments (first segment is always empty string)
const pathParts = normalizedHref.split('/')
// Handle special product paths that appear anywhere in the URL
if (pathParts.includes('early-access')) return 'early-access'
// Handle special products that always appear as the first segment
// These products use custom sidebars and need explicit handling
const specialProducts = ['rest', 'copilot', 'get-started']
if (specialProducts.includes(pathParts[1])) {
return pathParts[1]
}
// Determine if first segment is a version (e.g., 'enterprise-server@3.9')
// If yes, product is in pathParts[2], otherwise it's in pathParts[1]
// Examples:
// /enterprise-server@3.9/admin -> product is 'admin'
// /github/getting-started -> product is 'github'
// /enterprise-server@3.9 -> product is 'enterprise-server@3.9' (enterprise landing)
const hasVersionPrefix = supportedVersions.has(pathParts[1])
const productString = hasVersionPrefix && pathParts[2] ? pathParts[2] : pathParts[1]
return productString
}
export function getCategoryStringFromPath(href: string | undefined): string | undefined {
if (!href) return undefined
href = getPathWithoutLanguage(href)
if (href === '/') return undefined
const pathParts = href.split('/')
if (pathParts.includes('early-access')) return undefined
const productIndex = productIds.includes(pathParts[2]) ? 2 : 1
return pathParts[productIndex + 1]
}
export default {
getPathWithLanguage,
getPathWithoutLanguage,
getPathWithoutVersion,
getVersionStringFromPath,
getVersionObjectFromPath,
getProductStringFromPath,
getCategoryStringFromPath,
}