diff --git a/docusaurus.config.js b/docusaurus.config.js index d3dbf6d1..2dda7af7 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -11,11 +11,7 @@ import { themes as prismThemes } from "prism-react-renderer"; const organizationName = "pantsbuild"; const projectName = "pantsbuild.org"; -function getCurrentVersion() { - const lastReleasedVersion = versions[0]; - const version = parseInt(lastReleasedVersion.replace("2.", ""), 10); - return `2.${version + 1}`; -} +const numberOfSupportedStableVersions = 2; // Controls for how much to build: // - (No env vars set) -> Just uses the docs from `/docs/` (Docusaurus calls this "current version"), and no blog. @@ -23,8 +19,8 @@ function getCurrentVersion() { // - PANTSBUILD_ORG_INCLUDE_BLOG=1 -> Include the blog. // Note that `NODE_ENV === 'production' builds _everything_. const isDev = process.env.NODE_ENV === "development"; -const disableVersioning = - isDev && process.env.PANTSBUILD_ORG_INCLUDE_VERSIONS === undefined; + +// Versions const onlyIncludeVersions = isDev ? process.env.PANTSBUILD_ORG_INCLUDE_VERSIONS ? ["current"].concat( @@ -32,32 +28,23 @@ const onlyIncludeVersions = isDev ) : ["current"] : undefined; -const currentVersion = getCurrentVersion(); -const includeBlog = process.env.PANTSBUILD_ORG_INCLUDE_BLOG === "1" || !isDev; -const formatCopyright = () => { - const makeLink = (href, text) => `${text}`; - - const repoUrl = `https://github.com/${organizationName}/${projectName}`; - const repoLink = makeLink(repoUrl, "Website source"); +function getCurrentVersion() { + const lastReleasedVersion = versions[0]; + const version = parseInt(lastReleasedVersion.replace("2.", ""), 10); + return `2.${version + 1}`; +} - // Only set by CI, so fallback to just `local` for local dev - const docsCommit = process.env.GITHUB_SHA; - const commitLink = docsCommit - ? makeLink(`${repoUrl}/commit/${docsCommit}`, docsCommit.slice(0, 6)) - : "local"; +const currentVersion = getCurrentVersion(); - return `Copyright © Pants project contributors. ${repoLink} @ ${commitLink}.`; -}; +const isCurrentVersion = (shortVersion) => shortVersion === currentVersion; -const isPrerelease = (version) => { - const reference_dir = path.join( - "versioned_docs", - `version-${version}`, - "reference" - ); +const getFullVersion = (shortVersion) => { + const parentDir = isCurrentVersion(shortVersion) + ? "docs" + : path.join("versioned_docs", `version-${shortVersion}`); const helpAll = JSON.parse( - fs.readFileSync(path.join(reference_dir, "help-all.json"), "utf8") + fs.readFileSync(path.join(parentDir, "reference", "help-all.json"), "utf8") ); const pantsVersion = helpAll["scope_to_help_info"][""]["advanced"].find( @@ -68,12 +55,106 @@ const isPrerelease = (version) => { (value) => value["rank"] == "HARDCODED" ); + return hardcoded["value"]; +}; + +const isPrereleaseVersion = (fullVersion) => { // Check if it's one of xx.xx.0.dev0, xx.xx.0a0, xx.xx.0b0, xx.xx.0rc0, etc. // We don't treat patch versions pre-releases as pre-releases, since it looks weird. // Optimally we shouldn't sync those either way, but some have ended up here by accident. const rex = /^(\d+\.\d+\.0)(\.dev|a|b|rc)\d+$/; - return rex.test(hardcoded["value"]); + return rex.test(fullVersion); +}; + +const getVersionDetails = () => { + const versionDetails = []; + + let seenStableVersions = 0; + + // Construct the configuration for each version. NB. iterating from newest to oldest is important, + // to be able to label too-old stable versions as unsupported. + for (const shortVersion of [currentVersion, ...versions]) { + const fullVersion = getFullVersion(shortVersion); + + // NB. "maintained" versions includes pre-releases + const isMaintained = seenStableVersions < numberOfSupportedStableVersions; + const isPrerelease = isPrereleaseVersion(fullVersion); + const isCurrent = isCurrentVersion(shortVersion); + + // compute the appropriate configuration this version + let config; + if (isCurrent) { + // current version => dev + config = { + label: `${shortVersion} (dev)`, + }; + } else if (isPrerelease) { + // prerelease => prerelease + config = { + label: `${shortVersion} (prerelease)`, + banner: "unreleased", + noIndex: false, + }; + } else if (isMaintained) { + // a new-enough stable version => so still supported + config = { + label: shortVersion, + banner: "none", + noIndex: false, + }; + } else { + // stable, but too old => deprecated + config = { + label: `${shortVersion} (deprecated)`, + banner: "unmaintained", + noIndex: true, + }; + } + + versionDetails.push({ + shortVersion, + fullVersion, + isMaintained, + isPrerelease, + isCurrent, + config: { + ...config, + path: shortVersion, + }, + }); + + if (!isPrerelease) { + seenStableVersions += 1; + } + } + + return versionDetails; +}; + +const versionDetails = getVersionDetails(); + +const mostRecentStableVersion = versionDetails.find( + ({ isPrerelease }) => !isPrerelease +); + +// Blog +const includeBlog = process.env.PANTSBUILD_ORG_INCLUDE_BLOG === "1" || !isDev; + +// Other information +const formatCopyright = () => { + const makeLink = (href, text) => `${text}`; + + const repoUrl = `https://github.com/${organizationName}/${projectName}`; + const repoLink = makeLink(repoUrl, "Website source"); + + // Only set by CI, so fallback to just `local` for local dev + const docsCommit = process.env.GITHUB_SHA; + const commitLink = docsCommit + ? makeLink(`${repoUrl}/commit/${docsCommit}`, docsCommit.slice(0, 6)) + : "local"; + + return `Copyright © Pants project contributors. ${repoLink} @ ${commitLink}.`; }; const config = { @@ -331,36 +412,16 @@ const config = { { sidebarPath: require.resolve("./sidebars.js"), routeBasePath: "/", - disableVersioning, onlyIncludeVersions, lastVersion: onlyIncludeVersions ? undefined - : versions.find((v) => !isPrerelease(v)), - versions: { - current: { - label: `${currentVersion} (dev)`, - path: currentVersion, - }, - ...(disableVersioning - ? {} - : versions.reduce((acc, version, index) => { - acc[version] = { - label: isPrerelease(version) - ? `${version} (prerelease)` - : index < 2 + (isPrerelease(versions[0]) ? 1 : 0) - ? version - : `${version} (deprecated)`, - banner: isPrerelease(version) - ? "unreleased" - : index < 2 + (isPrerelease(versions[0]) ? 1 : 0) - ? "none" - : "unmaintained", - noIndex: index >= 2 + (isPrerelease(versions[0]) ? 1 : 0), - path: version, - }; - return acc; - }, {})), - }, + : mostRecentStableVersion.shortVersion, + versions: Object.fromEntries( + versionDetails.map(({ isCurrent, shortVersion, config }) => [ + isCurrent ? "current" : shortVersion, + config, + ]) + ), remarkPlugins: [captionedCode, tabBlocks], editUrl: ({ docPath }) => { if (docPath.startsWith("reference/")) {