1
0
mirror of synced 2025-12-23 03:44:00 -05:00

Compute category versions from combining versions of children (#45685)

This commit is contained in:
Peter Bengtsson
2023-11-15 07:52:26 -05:00
committed by GitHub
parent 1e3adbaccf
commit cf8119207b
5 changed files with 96 additions and 6 deletions

View File

@@ -2,10 +2,11 @@
title: Versioning
intro: 'Testing of pages that only available in *some* versions'
versions:
fpt: '*'
ghes: '*'
ghae: '*'
ghec: '*'
# Note that these here are wrong!
# They deliberately don't match what's set in the versions
# within the children.
ghes: '>=3.99'
ghec: '<1.0'
children:
- /only-fpt
- /only-ghec

View File

@@ -1,4 +1,3 @@
import { expect } from '@jest/globals'
import { getDOM, head } from '#src/tests/helpers/e2etest.js'
import { supported } from '#src/versions/lib/enterprise-server-releases.js'
@@ -47,6 +46,33 @@ describe('article versioning', () => {
})
})
describe('category versioning', () => {
test('category page work in all children versions', async () => {
{
// Note that in the `versions:` of get-started/versioning/index.md
// it *lacks* fpt. It's a deliberate pretend omission/mistake.
// But clearly the page works.
const res = await head('/en/get-started/versioning')
expect(res.statusCode).toBe(200)
}
{
// The actual version number of get-started/versioning/index.md
// does not specify this version of ghes, it still works.
const res = await head('/en/enterprise-server@latest/get-started/versioning')
expect(res.statusCode).toBe(302)
expect(res.headers.location).toMatch(
/\/en\/enterprise-server@[\d.]+\/get-started\/versioning/,
)
}
{
// The actual version number of get-started/versioning/index.md
// does not specify this version of ghec, it still works.
const res = await head('/en/enterprise-cloud@latest/get-started/versioning')
expect(res.statusCode).toBe(200)
}
})
})
describe('home page versioning', () => {
test('invalid language and valid version', async () => {
// Don't use 'latest' here because that will trigger a redirect

View File

@@ -6,6 +6,7 @@ import createTree from './create-tree.js'
import nonEnterpriseDefaultVersion from '#src/versions/lib/non-enterprise-default-version.js'
import readFileContents from './read-file-contents.js'
import Page from './page.js'
import Permalink from './permalink.js'
import frontmatterSchema from './frontmatter.js'
import { correctTranslatedContentStrings } from '#src/languages/lib/correct-translation-content.js'
@@ -42,6 +43,7 @@ export async function loadUnversionedTree(languagesOnly = null) {
}
const unversionedTree = {}
unversionedTree.en = await createTree(path.join(languages.en.dir, 'content'))
setCategoryApplicableVersions(unversionedTree.en)
const languagesValues = Object.entries(languages)
.filter(([language]) => {
@@ -67,6 +69,52 @@ export async function loadUnversionedTree(languagesOnly = null) {
return unversionedTree
}
function setCategoryApplicableVersions(tree) {
// Now that the tree has been fully computed, we can for any node that
// is a category page, re-set its `.applicableVersions` and `.permalinks`
// based on the union set of all its immediate children's
// `.applicableVersions`.
for (const childPage of tree.childPages) {
if (childPage.page.relativePath.endsWith('index.md')) {
const combinedApplicableVersions = []
let moreThanOneChild = false
for (const childChildPage of childPage.childPages || []) {
for (const version of childChildPage.page.applicableVersions) {
if (!combinedApplicableVersions.includes(version)) {
combinedApplicableVersions.push(version)
}
}
setCategoryApplicableVersions(childPage)
moreThanOneChild = true
}
if (
// Some landing pages have no children at all.
// For example the search/index.md page. With no children,
// the combined applicableVersions would be [].
moreThanOneChild &&
!equalSets(
new Set(childPage.page.applicableVersions),
new Set(combinedApplicableVersions),
) &&
!childPage.page.relativePath.startsWith('early-access')
) {
const newPermalinks = Permalink.derive(
childPage.page.languageCode,
childPage.page.relativePath,
childPage.page.title,
combinedApplicableVersions,
)
childPage.page.permalinks = newPermalinks
childPage.page.applicableVersions = combinedApplicableVersions
}
}
}
}
function equalSets(setA, setB) {
return setA.size === setB.size && [...setA].every((x) => setB.has(x))
}
async function translateTree(dir, langObj, enTree) {
const item = {}
const enPage = enTree.page

View File

@@ -23,7 +23,20 @@ export default async function findPage(
let page = req.context.pages[req.pagePath]
if (page && isDev && englishPrefixRegex.test(req.pagePath)) {
// The .applicableVersions and .permalinks properties are computed
// when the page is read in from disk. But when the initial tree
// was created at startup, the pages in the tree were mutated
// based on their context. For example, a category page's versions
// is based on looping through all its children's versions.
const reuseOldVersions = page.relativePath.endsWith('index.md')
const oldApplicableVersions = page.applicableVersions
const oldPermalinks = page.permalinks
page = await rereadByPath(req.pagePath, contentRoot, req.context.currentVersion)
if (reuseOldVersions) {
page.applicableVersions = oldApplicableVersions
page.permalinks = oldPermalinks
}
// This can happen if the page we just re-read has changed which
// versions it's available in (the `versions` frontmatter) meaning

View File

@@ -578,7 +578,9 @@ async function processPermalink(core, permalink, page, pageMap, redirects, opts,
try {
html = await renderInnerHTML(page, permalink)
} catch (error) {
console.warn(`The error happened trying to render ${page.relativePath}`)
console.warn(
`The error happened trying to render ${page.relativePath} (permalink: ${permalink.href})`,
)
throw error
}
const $ = cheerio.load(html, { xmlMode: true })