2020-09-27 15:10:11 +03:00
|
|
|
const slash = require('slash')
|
|
|
|
const path = require('path')
|
|
|
|
const patterns = require('./patterns')
|
2020-12-17 18:19:44 +03:00
|
|
|
const { deprecated, latest } = require('./enterprise-server-releases')
|
2020-09-27 15:10:11 +03:00
|
|
|
const allProducts = require('./all-products')
|
|
|
|
const allVersions = require('./all-versions')
|
2020-12-14 19:07:44 +03:00
|
|
|
const supportedVersions = new Set(Object.keys(allVersions))
|
2020-09-27 15:10:11 +03:00
|
|
|
const { getNewVersionedPath } = require('./old-versions-utils')
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// This function constructs an appropriate versioned path for any given HREF.
|
|
|
|
// NOTE: this gets called by findPage and various other functions, and
|
|
|
|
// has to return a proper versioned link given a wide variety of incoming
|
|
|
|
// modern or legacy-formatted links, so it is somewhat overloaded. At some point
|
|
|
|
// this could probably be broken up into separate functions to handle different incoming
|
|
|
|
// paths. But it is currently optimized to handle lots of edge cases.
|
2020-09-27 15:10:11 +03:00
|
|
|
function getVersionedPathWithoutLanguage (href, version) {
|
2020-12-17 18:50:52 +03:00
|
|
|
// Start clean without language code or trailing slash
|
2020-09-27 15:10:11 +03:00
|
|
|
href = getPathWithoutLanguage(href.replace(patterns.trailingSlash, '$1'))
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// If this is an old versioned path that includes a deprecated version, do not change!
|
2020-09-29 20:36:07 +03:00
|
|
|
// example: /enterprise/11.10.340/admin/articles/upgrading-to-the-latest-release
|
|
|
|
const oldEnterpriseVersionNumber = href.match(patterns.getEnterpriseVersionNumber)
|
|
|
|
if (oldEnterpriseVersionNumber && deprecated.includes(oldEnterpriseVersionNumber[1])) {
|
|
|
|
return href
|
2020-09-27 15:10:11 +03:00
|
|
|
}
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// Try to derive the current version from the path
|
2020-09-29 20:36:07 +03:00
|
|
|
// example: enterprise-server@2.22 or free-pro-team@latest
|
|
|
|
let versionFromPath = getVersionStringFromPath(href)
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// If a supported version was found, add it to the path so we can go through the rest of the checks
|
2020-12-17 17:58:16 +03:00
|
|
|
if (supportedVersions.has(versionFromPath)) {
|
|
|
|
href = href.replace(href.split('/')[1], versionFromPath)
|
|
|
|
}
|
2020-12-17 05:24:50 +03:00
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// If a currently supported version was NOT found...
|
2020-11-12 21:28:38 +03:00
|
|
|
let productObjectFromPath
|
2020-12-14 19:07:44 +03:00
|
|
|
if (!supportedVersions.has(versionFromPath)) {
|
2020-12-17 18:50:52 +03:00
|
|
|
// First check if the segment is instead a current product;
|
2020-11-12 21:28:38 +03:00
|
|
|
// example: /admin/foo or /desktop/foo
|
|
|
|
productObjectFromPath = allProducts[versionFromPath]
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// If so, add the first supported version for that product to the href
|
2020-12-17 18:19:44 +03:00
|
|
|
// (this is just to get a path with all the expected segments; the version will be updated later if needed)
|
2020-11-12 21:28:38 +03:00
|
|
|
if (productObjectFromPath) {
|
|
|
|
href = path.join('/', productObjectFromPath.versions[0], href)
|
|
|
|
versionFromPath = productObjectFromPath.versions[0]
|
|
|
|
} else {
|
2020-12-17 18:50:52 +03:00
|
|
|
// Otherwise, this may be an old path that should be converted to new path;
|
2020-11-12 21:28:38 +03:00
|
|
|
// OLD: /enterprise/2.22/admin/installation OR /enterprise/admin/installation
|
|
|
|
// NEW: /enterprise-server@2.22/admin/installation
|
|
|
|
href = getNewVersionedPath(href)
|
|
|
|
versionFromPath = getVersionStringFromPath(href)
|
|
|
|
}
|
2020-09-29 20:36:07 +03:00
|
|
|
}
|
2020-09-27 15:10:11 +03:00
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// If not previously found, derive the product object from the path (e.g., github or admin)
|
2020-11-12 21:28:38 +03:00
|
|
|
if (!productObjectFromPath) {
|
|
|
|
productObjectFromPath = getProductObjectFromPath(href)
|
|
|
|
}
|
2020-09-27 15:10:11 +03:00
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// If the product's versions don't include the specified version, nothing to change!
|
2020-09-29 20:36:07 +03:00
|
|
|
if (productObjectFromPath && !productObjectFromPath.versions.includes(version)) {
|
|
|
|
return slash(href)
|
2020-09-27 15:10:11 +03:00
|
|
|
}
|
2020-09-29 20:36:07 +03:00
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// Update the version and return the path
|
2020-09-29 20:36:07 +03:00
|
|
|
return slash(href.replace(versionFromPath, version))
|
2020-09-27 15:10:11 +03:00
|
|
|
}
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// Add language code to a versioned path
|
2020-09-27 15:10:11 +03:00
|
|
|
function getVersionedPathWithLanguage (href, version, languageCode) {
|
|
|
|
return getPathWithLanguage(getVersionedPathWithoutLanguage(href, version), languageCode)
|
|
|
|
}
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// Add the language to the given HREF
|
|
|
|
// /articles/foo -> /en/articles/foo
|
2020-09-27 15:10:11 +03:00
|
|
|
function getPathWithLanguage (href, languageCode) {
|
|
|
|
return slash(path.posix.join('/', languageCode, getPathWithoutLanguage(href)))
|
|
|
|
.replace(patterns.trailingSlash, '$1')
|
|
|
|
}
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// Remove the language from the given HREF
|
|
|
|
// /en/articles/foo -> /articles/foo
|
2020-09-27 15:10:11 +03:00
|
|
|
function getPathWithoutLanguage (href) {
|
2020-12-14 18:45:45 +03:00
|
|
|
return slash(href.replace(patterns.hasLanguageCode, '/'))
|
2020-09-27 15:10:11 +03:00
|
|
|
}
|
|
|
|
|
2020-12-17 05:24:50 +03:00
|
|
|
// Remove the version segment from the path
|
2020-09-27 15:10:11 +03:00
|
|
|
function getPathWithoutVersion (href) {
|
2020-09-29 20:36:07 +03:00
|
|
|
return href.replace(`/${getVersionStringFromPath(href)}`, '')
|
2020-09-27 15:10:11 +03:00
|
|
|
}
|
|
|
|
|
2020-12-17 05:24:50 +03:00
|
|
|
// Return the version segment in a path
|
2020-09-27 15:10:11 +03:00
|
|
|
function getVersionStringFromPath (href) {
|
|
|
|
href = getPathWithoutLanguage(href)
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// Return immediately if this is a link to the homepage
|
2020-12-17 18:19:44 +03:00
|
|
|
if (href === '/') {
|
|
|
|
return 'homepage'
|
|
|
|
}
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// Check if the first segment is a supported version
|
2020-12-17 05:24:50 +03:00
|
|
|
const versionFromPath = href.split('/')[1]
|
|
|
|
|
2020-12-17 18:19:44 +03:00
|
|
|
if (supportedVersions.has(versionFromPath)) {
|
2020-12-17 05:24:50 +03:00
|
|
|
return versionFromPath
|
|
|
|
}
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// If the version segment is the latest enterprise-server release, return the latest release
|
2020-12-17 05:24:50 +03:00
|
|
|
if (versionFromPath === 'enterprise-server@latest') {
|
2020-12-17 18:19:44 +03:00
|
|
|
return `enterprise-server@${latest}`
|
2020-12-17 05:24:50 +03:00
|
|
|
}
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// If it's just a plan with no @release (e.g., `enterprise-server`), return the latest release
|
2020-12-17 05:24:50 +03:00
|
|
|
const planObject = Object.values(allVersions).find(v => v.plan === versionFromPath)
|
|
|
|
if (planObject) {
|
|
|
|
return allVersions[planObject.latestVersion].version
|
|
|
|
}
|
|
|
|
|
2020-12-17 18:50:52 +03:00
|
|
|
// Otherwise, return the first segment as-is, which may not be a real supported version,
|
2020-12-17 18:19:44 +03:00
|
|
|
// but additional checks are done on this segment in getVersionedPathWithoutLanguage
|
|
|
|
return versionFromPath
|
2020-09-27 15:10:11 +03:00
|
|
|
}
|
|
|
|
|
2020-12-17 05:24:50 +03:00
|
|
|
// Return the corresponding object for the version segment in a path
|
2020-09-27 15:10:11 +03:00
|
|
|
function getVersionObjectFromPath (href) {
|
2020-12-17 05:24:50 +03:00
|
|
|
const versionFromPath = getVersionStringFromPath(href)
|
2020-09-27 15:10:11 +03:00
|
|
|
|
2020-12-17 05:24:50 +03:00
|
|
|
return allVersions[versionFromPath]
|
2020-09-27 15:10:11 +03:00
|
|
|
}
|
|
|
|
|
2020-12-17 05:24:50 +03:00
|
|
|
// Return the product segment from the path
|
2020-09-27 15:10:11 +03:00
|
|
|
function getProductStringFromPath (href) {
|
|
|
|
href = getPathWithoutLanguage(href)
|
|
|
|
const productString = href.split('/')[2]
|
|
|
|
|
|
|
|
return productString || 'homepage'
|
|
|
|
}
|
|
|
|
|
2020-12-17 05:24:50 +03:00
|
|
|
// Return the corresponding object for the product segment in a path
|
2020-09-27 15:10:11 +03:00
|
|
|
function getProductObjectFromPath (href) {
|
2020-12-17 05:24:50 +03:00
|
|
|
const productFromPath = getProductStringFromPath(href)
|
|
|
|
|
|
|
|
return allProducts[productFromPath]
|
2020-09-27 15:10:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
getVersionedPathWithLanguage,
|
|
|
|
getVersionedPathWithoutLanguage,
|
|
|
|
getPathWithLanguage,
|
|
|
|
getPathWithoutLanguage,
|
|
|
|
getPathWithoutVersion,
|
|
|
|
getVersionStringFromPath,
|
|
|
|
getVersionObjectFromPath,
|
|
|
|
getProductStringFromPath,
|
|
|
|
getProductObjectFromPath
|
|
|
|
}
|