diff --git a/lib/find-page.js b/lib/find-page.js index 9c2c9ee0e5..d461a965bb 100644 --- a/lib/find-page.js +++ b/lib/find-page.js @@ -1,14 +1,14 @@ import { getLanguageCode } from './patterns.js' import getRedirect from './get-redirect.js' -export default function findPage(href, pageMap, redirects) { +export default function findPage(href, pages, redirects) { // remove any fragments href = href.replace(/#.*$/, '') - const redirectsContext = { redirects, pages: pageMap } + const redirectsContext = { redirects, pages } // find the page - const page = pageMap[href] || pageMap[getRedirect(href, redirectsContext)] + const page = pages[href] || pages[getRedirect(href, redirectsContext)] if (page) return page // get the current language @@ -16,5 +16,5 @@ export default function findPage(href, pageMap, redirects) { // try to fall back to English if the translated page can't be found const englishHref = href.replace(`/${currentLang}/`, '/en/') - return pageMap[englishHref] || pageMap[getRedirect(englishHref, redirectsContext)] + return pages[englishHref] || pages[getRedirect(englishHref, redirectsContext)] } diff --git a/lib/render-content/create-processor.js b/lib/render-content/create-processor.js index 13d53b7256..21f968b6e9 100644 --- a/lib/render-content/create-processor.js +++ b/lib/render-content/create-processor.js @@ -44,10 +44,7 @@ export default function createProcessor(context) { .use(raw) .use(wrapInElement, { selector: 'ol > li img', wrapper: 'span.procedural-image-wrapper' }) .use(rewriteImgSources) - .use(rewriteLocalLinks, { - languageCode: context.currentLanguage, - version: context.currentVersion, - }) + .use(rewriteLocalLinks, context) .use(html) } @@ -58,9 +55,6 @@ export function createMinimalProcessor(context) { .use(remark2rehype, { allowDangerousHtml: true }) .use(slug) .use(raw) - .use(rewriteLocalLinks, { - languageCode: context.currentLanguage, - version: context.currentVersion, - }) + .use(rewriteLocalLinks, context) .use(html) } diff --git a/lib/render-content/plugins/rewrite-local-links.js b/lib/render-content/plugins/rewrite-local-links.js index b2b6fe2a5d..4a43d2bfac 100644 --- a/lib/render-content/plugins/rewrite-local-links.js +++ b/lib/render-content/plugins/rewrite-local-links.js @@ -8,10 +8,14 @@ import nonEnterpriseDefaultVersion from '../../non-enterprise-default-version.js import { allVersions } from '../../all-versions.js' import removeFPTFromPath from '../../remove-fpt-from-path.js' import readJsonFile from '../../read-json-file.js' +import findPage from '../../find-page.js' const supportedPlans = new Set(Object.values(allVersions).map((v) => v.plan)) const externalRedirects = readJsonFile('./lib/redirects/external-sites.json') +// Meaning it can be 'AUTOTITLE ' or ' AUTOTITLE' or 'AUTOTITLE' +const AUTOTITLE = /^\s*AUTOTITLE\s*$/ + // Matches any tags with an href that starts with `/` const matcher = (node) => node.type === 'element' && @@ -22,20 +26,34 @@ const matcher = (node) => // Content authors write links like `/some/article/path`, but they need to be // rewritten on the fly to match the current language and page version -export default function rewriteLocalLinks({ languageCode, version }) { +export default function rewriteLocalLinks(context) { + const { currentLanguage, currentVersion } = context // There's no languageCode or version passed, so nothing to do - if (!languageCode || !version) return + if (!currentLanguage || !currentVersion) return return (tree) => { visit(tree, matcher, (node) => { - const newHref = getNewHref(node, languageCode, version) + const newHref = getNewHref(node, currentLanguage, currentVersion) if (newHref) { node.properties.href = newHref } + for (const child of node.children) { + if (child.value && AUTOTITLE.test(child.value)) { + child.value = getNewTitle(node.properties.href, context) + } + } }) } } +function getNewTitle(href, context) { + const page = findPage(href, context.pages, context.redirects) + if (!page) { + throw new Error(`Unable to find Page by href '${href}'`) + } + return page.title +} + function getNewHref(node, languageCode, version) { const { href } = node.properties // Exceptions to link rewriting diff --git a/lib/rewrite-local-links.js b/lib/rewrite-local-links.js deleted file mode 100644 index 2deb2e3055..0000000000 --- a/lib/rewrite-local-links.js +++ /dev/null @@ -1,92 +0,0 @@ -import assert from 'assert' -import path from 'path' -import { getPathWithoutLanguage, getVersionStringFromPath } from './path-utils.js' -import { getNewVersionedPath } from './old-versions-utils.js' -import patterns from './patterns.js' -import { deprecated, latest } from './enterprise-server-releases.js' -import nonEnterpriseDefaultVersion from './non-enterprise-default-version.js' -import { allVersions } from './all-versions.js' -import removeFPTFromPath from './remove-fpt-from-path.js' -import readJsonFile from './read-json-file.js' -const supportedVersions = Object.keys(allVersions) -const supportedPlans = Object.values(allVersions).map((v) => v.plan) -const externalRedirects = readJsonFile('./lib/redirects/external-sites.json') - -// Content authors write links like `/some/article/path`, but they need to be -// rewritten on the fly to match the current language and page version -export default function rewriteLocalLinks($, version, languageCode) { - assert(languageCode, 'languageCode is required') - - $('a[href^="/"]').each((i, el) => { - getNewHref($(el), languageCode, version) - }) -} - -function getNewHref(link, languageCode, version) { - const href = link.attr('href') - - // Exceptions to link rewriting - if (href.startsWith('/assets/')) return - if (href.startsWith('/public/')) return - if (Object.keys(externalRedirects).includes(href)) return - - let newHref = href - // If the link has a hardcoded plan or version in it, do not update other than adding a language code - // Examples: - // /enterprise-server@2.20/rest/reference/oauth-authorizations - // /enterprise-server/rest/reference/oauth-authorizations (this redirects to the latest version) - // /enterprise-server@latest/rest/reference/oauth-authorizations (this redirects to the latest version) - const firstLinkSegment = href.split('/')[1] - if ( - [...supportedPlans, ...supportedVersions, 'enterprise-server@latest'].includes(firstLinkSegment) - ) { - newHref = path.join('/', languageCode, href) - } - - // If the link includes a deprecated version, do not update other than adding a language code - // Example: /enterprise/11.10.340/admin/articles/upgrading-to-the-latest-release - const oldEnterpriseVersionNumber = href.match(patterns.getEnterpriseVersionNumber) - if (oldEnterpriseVersionNumber && deprecated.includes(oldEnterpriseVersionNumber[1])) { - newHref = path.join('/', languageCode, href) - } - - if (newHref === href) { - // start clean with no language (TOC pages already include the lang codes via lib/liquid-tags/link.js) - const hrefWithoutLang = getPathWithoutLanguage(href) - - // normalize any legacy links so they conform to new link structure - newHref = path.posix.join('/', languageCode, getNewVersionedPath(hrefWithoutLang)) - - // get the current version from the link - const versionFromHref = getVersionStringFromPath(newHref) - - // ------ BEGIN ONE-OFF OVERRIDES ------// - // dotcom-only links always point to dotcom - if (link.hasClass('dotcom-only')) { - version = nonEnterpriseDefaultVersion - } - - // desktop links always point to dotcom - if (patterns.desktop.test(hrefWithoutLang)) { - version = nonEnterpriseDefaultVersion - } - - // admin links on dotcom always point to Enterprise - if (patterns.adminProduct.test(hrefWithoutLang) && version === nonEnterpriseDefaultVersion) { - version = `enterprise-server@${latest}` - } - - // insights links on dotcom always point to Enterprise - if (patterns.insightsProduct.test(hrefWithoutLang) && version === nonEnterpriseDefaultVersion) { - version = `enterprise-server@${latest}` - } - // ------ END ONE-OFF OVERRIDES ------// - - // update the version in the link - newHref = removeFPTFromPath(newHref.replace(versionFromHref, version)) - } - - newHref = newHref.replace(patterns.trailingSlash, '$1') - - if (href !== newHref) link.attr('href', newHref) -} diff --git a/middleware/context.js b/middleware/context.js index 5f1fd2151f..812acb7416 100644 --- a/middleware/context.js +++ b/middleware/context.js @@ -8,6 +8,7 @@ import warmServer from '../lib/warm-server.js' import searchVersions from '../lib/search/versions.js' import nonEnterpriseDefaultVersion from '../lib/non-enterprise-default-version.js' import { getDataByLanguage, getUIDataMerged } from '../lib/get-data.js' + const activeProducts = Object.values(productMap).filter( (product) => !product.wip && !product.hidden ) @@ -90,5 +91,6 @@ export default async function contextualize(req, res, next) { return context.enPage } } + return next() }