diff --git a/docusaurus.config.js b/docusaurus.config.js index 84c9add7..e2cdf19a 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -121,6 +121,7 @@ const config = { { to: '/organisations', label: 'Adopters', position: 'left' }, { to: '/contribute', label: 'Contribute', position: 'left' }, { to: '/resources', label: 'Resources', position: 'left' }, + { to: '/docs/latest/Reference/LTS', label: 'Support', position: 'left' }, { type: 'docsVersionDropdown', position: 'right', diff --git a/src/theme/DocItem/Layout/index.js b/src/theme/DocItem/Layout/index.js new file mode 100644 index 00000000..29a36b06 --- /dev/null +++ b/src/theme/DocItem/Layout/index.js @@ -0,0 +1,79 @@ +import React from 'react' +import clsx from 'clsx' +import { useWindowSize } from '@docusaurus/theme-common' +import { useDoc } from '@docusaurus/plugin-content-docs/client' +import DocItemPaginator from '@theme/DocItem/Paginator' +import DocVersionBanner from '@theme/DocVersionBanner' +import DocVersionBadge from '@theme/DocVersionBadge' +import DocItemFooter from '@theme/DocItem/Footer' +import DocItemTOCMobile from '@theme/DocItem/TOC/Mobile' +import DocItemTOCDesktop from '@theme/DocItem/TOC/Desktop' +import DocItemContent from '@theme/DocItem/Content' +import DocBreadcrumbs from '@theme/DocBreadcrumbs' +import ContentVisibility from '@theme/ContentVisibility' +import styles from './styles.module.css' +/** + * Decide if the toc should be rendered, on mobile or desktop viewports + */ +function useDocTOC() { + const { frontMatter, toc } = useDoc() + const windowSize = useWindowSize() + const hidden = frontMatter.hide_table_of_contents + const canRender = !hidden && toc.length > 0 + const mobile = canRender ? : undefined + const desktop = canRender && (windowSize === 'desktop' || windowSize === 'ssr') ? : undefined + return { + hidden, + mobile, + desktop, + } +} +export default function DocItemLayout({ children }) { + const docTOC = useDocTOC() + const { metadata } = useDoc() + + // Show warning only on migration guide pages. + const isMigrationGuide = metadata.permalink.toLowerCase().includes('migration-guide') + const versionNumber = parseVersion(metadata.version) + + return ( +
+
+ + +
+
+ + + {docTOC.mobile} + + {/* Show warning only on current version of documentation pages. + NaN indicates the latest version */} + {isMigrationGuide && (isNaN(versionNumber) || versionNumber === 5) && ( +
+

Version 3 and before of Fastify are no longer maintained.

+ For information about support options for end-of-life versions, see the{' '} + Long Term Support page. +
+ )} + + {children} + +
+ +
+
+ {docTOC.desktop &&
{docTOC.desktop}
} +
+ ) +} + +// Return version. +const parseVersion = (versionString) => { + // Remove 'v' prefix if present + const cleanVersion = versionString.startsWith('v') ? versionString.slice(1) : versionString + // Split the version string and get the first part (major version) + const majorVersion = cleanVersion.split('.')[0] + // Parse the major version to an integer + return parseInt(majorVersion, 10) +} diff --git a/src/theme/DocItem/Layout/styles.module.css b/src/theme/DocItem/Layout/styles.module.css new file mode 100644 index 00000000..d5aaec13 --- /dev/null +++ b/src/theme/DocItem/Layout/styles.module.css @@ -0,0 +1,10 @@ +.docItemContainer header + *, +.docItemContainer article > *:first-child { + margin-top: 0; +} + +@media (min-width: 997px) { + .docItemCol { + max-width: 75% !important; + } +} diff --git a/src/theme/DocVersionBanner/index.js b/src/theme/DocVersionBanner/index.js new file mode 100644 index 00000000..f7261596 --- /dev/null +++ b/src/theme/DocVersionBanner/index.js @@ -0,0 +1,128 @@ +import React from 'react' +import clsx from 'clsx' +import useDocusaurusContext from '@docusaurus/useDocusaurusContext' +import Link from '@docusaurus/Link' +import Translate from '@docusaurus/Translate' +import { useActivePlugin, useDocVersionSuggestions } from '@docusaurus/plugin-content-docs/client' +import { ThemeClassNames } from '@docusaurus/theme-common' +import { useDocsPreferredVersion, useDocsVersion } from '@docusaurus/plugin-content-docs/client' + +function UnreleasedVersionLabel({ siteTitle, versionMetadata }) { + return ( + {versionMetadata.label}, + }}> + {'This is unreleased documentation for {siteTitle} {versionLabel} version.'} + + ) +} +function UnmaintainedVersionLabel({ siteTitle, versionMetadata }) { + const versionNumber = parseInt(versionMetadata.label.replace(/^v/, '').split('.')[0], 10) + + // Return the label only if the version number is 3 or lower. + if (versionNumber <= 3) { + return ( + {versionMetadata.label}, + }}> + {'This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained.'} + + ) + } + return null +} +const BannerLabelComponents = { + unreleased: UnreleasedVersionLabel, + unmaintained: UnmaintainedVersionLabel, +} +function BannerLabel(props) { + const BannerLabelComponent = BannerLabelComponents[props.versionMetadata.banner] + return +} +function LatestVersionSuggestionLabel({ versionLabel, to, onClick }) { + return ( + + + + latest version + + + + ), + }}> + {'For up-to-date documentation, see the {latestVersionLink} ({versionLabel}).'} + + ) +} +function DocVersionBannerEnabled({ className, versionMetadata }) { + const { + siteConfig: { title: siteTitle }, + } = useDocusaurusContext() + const { pluginId } = useActivePlugin({ failfast: true }) + const getVersionMainDoc = (version) => version.docs.find((doc) => doc.id === version.mainDocId) + const { savePreferredVersionName } = useDocsPreferredVersion(pluginId) + const { latestDocSuggestion, latestVersionSuggestion } = useDocVersionSuggestions(pluginId) + + // Parse the version number + const versionNumber = parseVersion(versionMetadata.version) + + // Try to link to same doc in latest version (not always possible), falling + // back to main doc of latest version + const latestVersionSuggestedDoc = latestDocSuggestion ?? getVersionMainDoc(latestVersionSuggestion) + return ( +
+
+ +
+
+ savePreferredVersionName(latestVersionSuggestion.name)} + /> +
+ {/* When a new version is released, increment the value below. */} + {versionNumber < 4 && ( +
+ For information about support options for end-of-life versions, see the{' '} + Long Term Support page. +
+ )} +
+ ) +} +export default function DocVersionBanner({ className }) { + const versionMetadata = useDocsVersion() + if (versionMetadata.banner) { + return + } + return null +} + +// Returns version. +const parseVersion = (versionString) => { + // Remove 'v' prefix if present + const cleanVersion = versionString.startsWith('v') ? versionString.slice(1) : versionString + // Split the version string and get the first part (major version) + const majorVersion = cleanVersion.split('.')[0] + // Parse the major version to an integer + return parseInt(majorVersion, 10) +}