feat(v2): docs version banner configuration option (#5052)

* refactor DocVersionBanner => versionMetadata prop should be forwarded instead of using "useActiveVersion" + global data

* docs version banner configuration

* add doc for versions.banner

* fix tests

* improve docs plugin option api doc
This commit is contained in:
Sébastien Lorber 2021-06-24 18:04:16 +02:00 committed by GitHub
parent f47826297c
commit 364051f232
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 187 additions and 83 deletions

View file

@ -405,6 +405,7 @@ Object {
\\"pluginId\\": \\"default\\", \\"pluginId\\": \\"default\\",
\\"version\\": \\"current\\", \\"version\\": \\"current\\",
\\"label\\": \\"Next\\", \\"label\\": \\"Next\\",
\\"banner\\": \\"none\\",
\\"isLast\\": true, \\"isLast\\": true,
\\"docsSidebars\\": { \\"docsSidebars\\": {
\\"docs\\": [ \\"docs\\": [
@ -872,6 +873,7 @@ Object {
\\"pluginId\\": \\"community\\", \\"pluginId\\": \\"community\\",
\\"version\\": \\"1.0.0\\", \\"version\\": \\"1.0.0\\",
\\"label\\": \\"1.0.0\\", \\"label\\": \\"1.0.0\\",
\\"banner\\": \\"none\\",
\\"isLast\\": true, \\"isLast\\": true,
\\"docsSidebars\\": { \\"docsSidebars\\": {
\\"version-1.0.0/community\\": [ \\"version-1.0.0/community\\": [
@ -890,6 +892,7 @@ Object {
\\"pluginId\\": \\"community\\", \\"pluginId\\": \\"community\\",
\\"version\\": \\"current\\", \\"version\\": \\"current\\",
\\"label\\": \\"Next\\", \\"label\\": \\"Next\\",
\\"banner\\": \\"unreleased\\",
\\"isLast\\": false, \\"isLast\\": false,
\\"docsSidebars\\": { \\"docsSidebars\\": {
\\"community\\": [ \\"community\\": [
@ -1402,6 +1405,7 @@ Object {
\\"pluginId\\": \\"default\\", \\"pluginId\\": \\"default\\",
\\"version\\": \\"1.0.0\\", \\"version\\": \\"1.0.0\\",
\\"label\\": \\"1.0.0\\", \\"label\\": \\"1.0.0\\",
\\"banner\\": \\"unmaintained\\",
\\"isLast\\": false, \\"isLast\\": false,
\\"docsSidebars\\": { \\"docsSidebars\\": {
\\"version-1.0.0/docs\\": [ \\"version-1.0.0/docs\\": [
@ -1446,6 +1450,7 @@ Object {
\\"pluginId\\": \\"default\\", \\"pluginId\\": \\"default\\",
\\"version\\": \\"1.0.1\\", \\"version\\": \\"1.0.1\\",
\\"label\\": \\"1.0.1\\", \\"label\\": \\"1.0.1\\",
\\"banner\\": \\"none\\",
\\"isLast\\": true, \\"isLast\\": true,
\\"docsSidebars\\": { \\"docsSidebars\\": {
\\"version-1.0.1/docs\\": [ \\"version-1.0.1/docs\\": [
@ -1484,6 +1489,7 @@ Object {
\\"pluginId\\": \\"default\\", \\"pluginId\\": \\"default\\",
\\"version\\": \\"current\\", \\"version\\": \\"current\\",
\\"label\\": \\"Next\\", \\"label\\": \\"Next\\",
\\"banner\\": \\"unreleased\\",
\\"isLast\\": false, \\"isLast\\": false,
\\"docsSidebars\\": { \\"docsSidebars\\": {
\\"docs\\": [ \\"docs\\": [
@ -1522,6 +1528,7 @@ Object {
\\"pluginId\\": \\"default\\", \\"pluginId\\": \\"default\\",
\\"version\\": \\"withSlugs\\", \\"version\\": \\"withSlugs\\",
\\"label\\": \\"withSlugs\\", \\"label\\": \\"withSlugs\\",
\\"banner\\": \\"unmaintained\\",
\\"isLast\\": false, \\"isLast\\": false,
\\"docsSidebars\\": { \\"docsSidebars\\": {
\\"version-1.0.1/docs\\": [ \\"version-1.0.1/docs\\": [

View file

@ -21,6 +21,7 @@ const DefaultI18N: I18n = {
currentLocale: 'en', currentLocale: 'en',
locales: ['en'], locales: ['en'],
defaultLocale: 'en', defaultLocale: 'en',
localeConfigs: {},
}; };
describe('version paths', () => { describe('version paths', () => {
@ -79,6 +80,7 @@ describe('simple site', () => {
versionLabel: 'Next', versionLabel: 'Next',
versionName: 'current', versionName: 'current',
versionPath: '/docs', versionPath: '/docs',
versionBanner: 'none',
}; };
return {simpleSiteDir, defaultOptions, defaultContext, vCurrent}; return {simpleSiteDir, defaultOptions, defaultContext, vCurrent};
} }
@ -233,6 +235,7 @@ describe('versioned site, pluginId=default', () => {
versionLabel: 'Next', versionLabel: 'Next',
versionName: 'current', versionName: 'current',
versionPath: '/docs/next', versionPath: '/docs/next',
versionBanner: 'unreleased',
}; };
const v101: VersionMetadata = { const v101: VersionMetadata = {
@ -250,6 +253,7 @@ describe('versioned site, pluginId=default', () => {
versionLabel: '1.0.1', versionLabel: '1.0.1',
versionName: '1.0.1', versionName: '1.0.1',
versionPath: '/docs', versionPath: '/docs',
versionBanner: 'none',
}; };
const v100: VersionMetadata = { const v100: VersionMetadata = {
@ -267,6 +271,7 @@ describe('versioned site, pluginId=default', () => {
versionLabel: '1.0.0', versionLabel: '1.0.0',
versionName: '1.0.0', versionName: '1.0.0',
versionPath: '/docs/1.0.0', versionPath: '/docs/1.0.0',
versionBanner: 'unmaintained',
}; };
const vwithSlugs: VersionMetadata = { const vwithSlugs: VersionMetadata = {
@ -287,6 +292,7 @@ describe('versioned site, pluginId=default', () => {
versionLabel: 'withSlugs', versionLabel: 'withSlugs',
versionName: 'withSlugs', versionName: 'withSlugs',
versionPath: '/docs/withSlugs', versionPath: '/docs/withSlugs',
versionBanner: 'unmaintained',
}; };
return { return {
@ -357,9 +363,11 @@ describe('versioned site, pluginId=default', () => {
versions: { versions: {
current: { current: {
path: 'current-path', path: 'current-path',
banner: 'unmaintained',
}, },
'1.0.0': { '1.0.0': {
label: '1.0.0-label', label: '1.0.0-label',
banner: 'unreleased',
}, },
}, },
}, },
@ -367,12 +375,17 @@ describe('versioned site, pluginId=default', () => {
}); });
expect(versionsMetadata).toEqual([ expect(versionsMetadata).toEqual([
{...vCurrent, versionPath: '/docs/current-path'}, {
...vCurrent,
versionPath: '/docs/current-path',
versionBanner: 'unmaintained',
},
{ {
...v101, ...v101,
isLast: false, isLast: false,
routePriority: undefined, routePriority: undefined,
versionPath: '/docs/1.0.1', versionPath: '/docs/1.0.1',
versionBanner: 'unreleased',
}, },
{ {
...v100, ...v100,
@ -380,6 +393,7 @@ describe('versioned site, pluginId=default', () => {
routePriority: -1, routePriority: -1,
versionLabel: '1.0.0-label', versionLabel: '1.0.0-label',
versionPath: '/docs', versionPath: '/docs',
versionBanner: 'unreleased',
}, },
vwithSlugs, vwithSlugs,
]); ]);
@ -510,7 +524,13 @@ describe('versioned site, pluginId=default', () => {
}); });
expect(versionsMetadata).toEqual([ expect(versionsMetadata).toEqual([
{...vCurrent, isLast: true, routePriority: -1, versionPath: '/docs'}, {
...vCurrent,
isLast: true,
routePriority: -1,
versionPath: '/docs',
versionBanner: 'none',
},
]); ]);
}); });
@ -631,6 +651,7 @@ describe('versioned site, pluginId=community', () => {
versionLabel: 'Next', versionLabel: 'Next',
versionName: 'current', versionName: 'current',
versionPath: '/communityBasePath/next', versionPath: '/communityBasePath/next',
versionBanner: 'unreleased',
}; };
const v100: VersionMetadata = { const v100: VersionMetadata = {
@ -651,6 +672,7 @@ describe('versioned site, pluginId=community', () => {
versionLabel: '1.0.0', versionLabel: '1.0.0',
versionName: '1.0.0', versionName: '1.0.0',
versionPath: '/communityBasePath', versionPath: '/communityBasePath',
versionBanner: 'none',
}; };
return {versionedSiteDir, defaultOptions, defaultContext, vCurrent, v100}; return {versionedSiteDir, defaultOptions, defaultContext, vCurrent, v100};
@ -695,6 +717,7 @@ describe('versioned site, pluginId=community', () => {
isLast: true, isLast: true,
routePriority: -1, routePriority: -1,
versionPath: '/communityBasePath', versionPath: '/communityBasePath',
versionBanner: 'none',
}, },
]); ]);
}); });

View file

@ -350,14 +350,13 @@ describe('docsClientUtils', () => {
latestVersionSuggestion: version2, latestVersionSuggestion: version2,
}); });
// nothing to suggest, we are already on latest version
expect(getDocVersionSuggestions(data, '/docs/')).toEqual({ expect(getDocVersionSuggestions(data, '/docs/')).toEqual({
latestDocSuggestion: undefined, latestDocSuggestion: version2.docs[0],
latestVersionSuggestion: undefined, latestVersionSuggestion: version2,
}); });
expect(getDocVersionSuggestions(data, '/docs/doc2')).toEqual({ expect(getDocVersionSuggestions(data, '/docs/doc2')).toEqual({
latestDocSuggestion: undefined, latestDocSuggestion: version2.docs[1],
latestVersionSuggestion: undefined, latestVersionSuggestion: version2,
}); });
expect(getDocVersionSuggestions(data, '/docs/version1/')).toEqual({ expect(getDocVersionSuggestions(data, '/docs/version1/')).toEqual({

View file

@ -140,10 +140,10 @@ export const getActiveDocContext = (
}; };
export type DocVersionSuggestions = { export type DocVersionSuggestions = {
// suggest the latest version
latestVersionSuggestion: GlobalVersion;
// suggest the same doc, in latest version (if exist) // suggest the same doc, in latest version (if exist)
latestDocSuggestion?: GlobalDoc; latestDocSuggestion?: GlobalDoc;
// suggest the latest version
latestVersionSuggestion?: GlobalVersion;
}; };
export const getDocVersionSuggestions = ( export const getDocVersionSuggestions = (
@ -152,17 +152,7 @@ export const getDocVersionSuggestions = (
): DocVersionSuggestions => { ): DocVersionSuggestions => {
const latestVersion = getLatestVersion(data); const latestVersion = getLatestVersion(data);
const activeDocContext = getActiveDocContext(data, pathname); const activeDocContext = getActiveDocContext(data, pathname);
const latestDocSuggestion: GlobalDoc | undefined =
// We only suggest another doc/version if user is not using the latest version activeDocContext?.alternateDocVersions[latestVersion.name];
const isNotOnLatestVersion = activeDocContext.activeVersion !== latestVersion; return {latestDocSuggestion, latestVersionSuggestion: latestVersion};
const latestDocSuggestion: GlobalDoc | undefined = isNotOnLatestVersion
? activeDocContext?.alternateDocVersions[latestVersion.name]
: undefined;
const latestVersionSuggestion = isNotOnLatestVersion
? latestVersion
: undefined;
return {latestDocSuggestion, latestVersionSuggestion};
}; };

View file

@ -49,6 +49,7 @@ export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'> = {
const VersionOptionsSchema = Joi.object({ const VersionOptionsSchema = Joi.object({
path: Joi.string().allow('').optional(), path: Joi.string().allow('').optional(),
label: Joi.string().optional(), label: Joi.string().optional(),
banner: Joi.string().equal('none', 'unreleased', 'unmaintained').optional(),
}); });
const VersionsOptionsSchema = Joi.object() const VersionsOptionsSchema = Joi.object()
@ -101,6 +102,7 @@ export const OptionsSchema = Joi.object({
showLastUpdateAuthor: Joi.bool().default( showLastUpdateAuthor: Joi.bool().default(
DEFAULT_OPTIONS.showLastUpdateAuthor, DEFAULT_OPTIONS.showLastUpdateAuthor,
), ),
// TODO deprecated, excludeNextVersionDocs replaced by includeCurrentVersion
excludeNextVersionDocs: Joi.bool().default( excludeNextVersionDocs: Joi.bool().default(
DEFAULT_OPTIONS.excludeNextVersionDocs, DEFAULT_OPTIONS.excludeNextVersionDocs,
), ),

View file

@ -8,6 +8,8 @@
/* eslint-disable camelcase */ /* eslint-disable camelcase */
declare module '@docusaurus/plugin-content-docs-types' { declare module '@docusaurus/plugin-content-docs-types' {
import type {VersionBanner} from './types';
export type PermalinkToSidebar = { export type PermalinkToSidebar = {
[permalink: string]: string; [permalink: string]: string;
}; };
@ -16,6 +18,7 @@ declare module '@docusaurus/plugin-content-docs-types' {
pluginId: string; pluginId: string;
version: string; version: string;
label: string; label: string;
banner: VersionBanner;
isLast: boolean; isLast: boolean;
docsSidebars: PropSidebars; docsSidebars: PropSidebars;
permalinkToSidebar: PermalinkToSidebar; permalinkToSidebar: PermalinkToSidebar;
@ -83,6 +86,7 @@ declare module '@theme/DocItem' {
export type Props = { export type Props = {
readonly route: DocumentRoute; readonly route: DocumentRoute;
readonly versionMetadata: PropVersionMetadata;
readonly content: { readonly content: {
readonly frontMatter: FrontMatter; readonly frontMatter: FrontMatter;
readonly metadata: Metadata; readonly metadata: Metadata;
@ -96,6 +100,17 @@ declare module '@theme/DocItem' {
export default DocItem; export default DocItem;
} }
declare module '@theme/DocVersionBanner' {
import type {PropVersionMetadata} from '@docusaurus/plugin-content-docs-types';
export type Props = {
readonly versionMetadata: PropVersionMetadata;
};
const DocVersionBanner: (props: Props) => JSX.Element;
export default DocVersionBanner;
}
declare module '@theme/DocPage' { declare module '@theme/DocPage' {
import type {PropVersionMetadata} from '@docusaurus/plugin-content-docs-types'; import type {PropVersionMetadata} from '@docusaurus/plugin-content-docs-types';
import type {DocumentRoute} from '@theme/DocItem'; import type {DocumentRoute} from '@theme/DocItem';

View file

@ -74,6 +74,7 @@ export function toVersionMetadataProp(
pluginId, pluginId,
version: loadedVersion.versionName, version: loadedVersion.versionName,
label: loadedVersion.versionLabel, label: loadedVersion.versionLabel,
banner: loadedVersion.versionBanner,
isLast: loadedVersion.isLast, isLast: loadedVersion.isLast,
docsSidebars: toSidebarsProp(loadedVersion), docsSidebars: toSidebarsProp(loadedVersion),
permalinkToSidebar: loadedVersion.permalinkToSidebar, permalinkToSidebar: loadedVersion.permalinkToSidebar,

View file

@ -30,6 +30,7 @@ export type VersionMetadata = ContentPaths & {
versionPath: string; // /baseUrl/docs/1.0.0 versionPath: string; // /baseUrl/docs/1.0.0
versionEditUrl?: string | undefined; versionEditUrl?: string | undefined;
versionEditUrlLocalized?: string | undefined; versionEditUrlLocalized?: string | undefined;
versionBanner: VersionBanner;
isLast: boolean; isLast: boolean;
sidebarFilePath: string | false | undefined; // versioned_sidebars/1.0.0.json sidebarFilePath: string | false | undefined; // versioned_sidebars/1.0.0.json
routePriority: number | undefined; // -1 for the latest docs routePriority: number | undefined; // -1 for the latest docs
@ -59,9 +60,13 @@ export type PathOptions = {
sidebarPath?: string | false | undefined; sidebarPath?: string | false | undefined;
}; };
// TODO support custom version banner? {type: "error", content: "html content"}
export type VersionBanner = 'none' | 'unreleased' | 'unmaintained';
export type VersionOptions = { export type VersionOptions = {
path?: string; path?: string;
label?: string; label?: string;
banner?: VersionBanner;
}; };
export type VersionsOptions = { export type VersionsOptions = {

View file

@ -9,6 +9,7 @@ import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import { import {
PluginOptions, PluginOptions,
VersionBanner,
VersionMetadata, VersionMetadata,
VersionOptions, VersionOptions,
VersionsOptions, VersionsOptions,
@ -255,14 +256,64 @@ function getVersionEditUrls({
}; };
} }
function getDefaultVersionBanner({
versionName,
versionNames,
lastVersionName,
}: {
versionName: string;
versionNames: string[];
lastVersionName: string;
}): VersionBanner {
// Current version: good, no banner
if (versionName === lastVersionName) {
return 'none';
}
// Upcoming versions: unreleased banner
else if (
versionNames.indexOf(versionName) < versionNames.indexOf(lastVersionName)
) {
return 'unreleased';
}
// Older versions: display unmaintained banner
else {
return 'unmaintained';
}
}
function getVersionBanner({
versionName,
versionNames,
lastVersionName,
options,
}: {
versionName: string;
versionNames: string[];
lastVersionName: string;
options: Pick<PluginOptions, 'versions'>;
}): VersionBanner {
const versionOptionBanner = options.versions[versionName]?.banner;
return (
versionOptionBanner ??
getDefaultVersionBanner({
versionName,
versionNames,
lastVersionName,
})
);
}
function createVersionMetadata({ function createVersionMetadata({
versionName, versionName,
isLast, versionNames,
lastVersionName,
context, context,
options, options,
}: { }: {
versionName: string; versionName: string;
isLast: boolean; versionNames: string[];
lastVersionName: string;
context: Pick<LoadContext, 'siteDir' | 'baseUrl' | 'i18n'>; context: Pick<LoadContext, 'siteDir' | 'baseUrl' | 'i18n'>;
options: Pick< options: Pick<
PluginOptions, PluginOptions,
@ -285,6 +336,8 @@ function createVersionMetadata({
options, options,
}); });
const isLast = versionName === lastVersionName;
// retro-compatible values // retro-compatible values
const defaultVersionLabel = const defaultVersionLabel =
versionName === CURRENT_VERSION_NAME ? 'Next' : versionName; versionName === CURRENT_VERSION_NAME ? 'Next' : versionName;
@ -321,6 +374,12 @@ function createVersionMetadata({
versionPath, versionPath,
versionEditUrl: versionEditUrls?.versionEditUrl, versionEditUrl: versionEditUrls?.versionEditUrl,
versionEditUrlLocalized: versionEditUrls?.versionEditUrlLocalized, versionEditUrlLocalized: versionEditUrls?.versionEditUrlLocalized,
versionBanner: getVersionBanner({
versionName,
versionNames,
lastVersionName,
options,
}),
isLast, isLast,
routePriority, routePriority,
sidebarFilePath, sidebarFilePath,
@ -486,7 +545,8 @@ export function readVersionsMetadata({
const versionsMetadata = versionNames.map((versionName) => const versionsMetadata = versionNames.map((versionName) =>
createVersionMetadata({ createVersionMetadata({
versionName, versionName,
isLast: versionName === lastVersionName, versionNames,
lastVersionName,
context, context,
options, options,
}), }),

View file

@ -7,7 +7,7 @@
import React from 'react'; import React from 'react';
import DocPaginator from '@theme/DocPaginator'; import DocPaginator from '@theme/DocPaginator';
import DocVersionSuggestions from '@theme/DocVersionSuggestions'; import DocVersionBanner from '@theme/DocVersionBanner';
import Seo from '@theme/Seo'; import Seo from '@theme/Seo';
import LastUpdated from '@theme/LastUpdated'; import LastUpdated from '@theme/LastUpdated';
import type {Props} from '@theme/DocItem'; import type {Props} from '@theme/DocItem';
@ -17,14 +17,10 @@ import {MainHeading} from '@theme/Heading';
import clsx from 'clsx'; import clsx from 'clsx';
import styles from './styles.module.css'; import styles from './styles.module.css';
import { import {useActivePlugin, useVersions} from '@theme/hooks/useDocs';
useActivePlugin,
useVersions,
useActiveVersion,
} from '@theme/hooks/useDocs';
function DocItem(props: Props): JSX.Element { function DocItem(props: Props): JSX.Element {
const {content: DocContent} = props; const {content: DocContent, versionMetadata} = props;
const {metadata, frontMatter} = DocContent; const {metadata, frontMatter} = DocContent;
const { const {
image, image,
@ -43,7 +39,6 @@ function DocItem(props: Props): JSX.Element {
const {pluginId} = useActivePlugin({failfast: true}); const {pluginId} = useActivePlugin({failfast: true});
const versions = useVersions(pluginId); const versions = useVersions(pluginId);
const version = useActiveVersion(pluginId);
// If site is not versioned or only one version is included // If site is not versioned or only one version is included
// we don't show the version badge // we don't show the version badge
@ -65,12 +60,12 @@ function DocItem(props: Props): JSX.Element {
className={clsx('col', { className={clsx('col', {
[styles.docItemCol]: !hideTableOfContents, [styles.docItemCol]: !hideTableOfContents,
})}> })}>
<DocVersionSuggestions /> <DocVersionBanner versionMetadata={versionMetadata} />
<div className={styles.docItemContainer}> <div className={styles.docItemContainer}>
<article> <article>
{showVersionBadge && ( {showVersionBadge && (
<span className="badge badge--secondary"> <span className="badge badge--secondary">
Version: {version.label} Version: {versionMetadata.label}
</span> </span>
)} )}

View file

@ -174,7 +174,7 @@ function DocPage(props: Props): JSX.Element {
<DocPageContent <DocPageContent
currentDocRoute={currentDocRoute} currentDocRoute={currentDocRoute}
versionMetadata={versionMetadata}> versionMetadata={versionMetadata}>
{renderRoutes(docRoutes)} {renderRoutes(docRoutes, {versionMetadata})}
</DocPageContent> </DocPageContent>
); );
} }

View file

@ -5,31 +5,31 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import React from 'react'; import React, {ComponentType} from 'react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
import Translate from '@docusaurus/Translate'; import Translate from '@docusaurus/Translate';
import { import {useActivePlugin, useDocVersionSuggestions} from '@theme/hooks/useDocs';
useActivePlugin,
useActiveVersion,
useDocVersionSuggestions,
} from '@theme/hooks/useDocs';
import {useDocsPreferredVersion} from '@docusaurus/theme-common'; import {useDocsPreferredVersion} from '@docusaurus/theme-common';
import type {Props} from '@theme/DocVersionBanner';
type BannerLabelComponentProps = {
siteTitle: string;
versionMetadata: Props['versionMetadata'];
};
function UnreleasedVersionLabel({ function UnreleasedVersionLabel({
siteTitle, siteTitle,
versionLabel, versionMetadata,
}: { }: BannerLabelComponentProps) {
siteTitle: string;
versionLabel: string;
}) {
return ( return (
<Translate <Translate
id="theme.docs.versions.unreleasedVersionLabel" id="theme.docs.versions.unreleasedVersionLabel"
description="The label used to tell the user that he's browsing an unreleased doc version" description="The label used to tell the user that he's browsing an unreleased doc version"
values={{ values={{
siteTitle, siteTitle,
versionLabel: <b>{versionLabel}</b>, versionLabel: <b>{versionMetadata.label}</b>,
}}> }}>
{ {
'This is unreleased documentation for {siteTitle} {versionLabel} version.' 'This is unreleased documentation for {siteTitle} {versionLabel} version.'
@ -40,18 +40,15 @@ function UnreleasedVersionLabel({
function UnmaintainedVersionLabel({ function UnmaintainedVersionLabel({
siteTitle, siteTitle,
versionLabel, versionMetadata,
}: { }: BannerLabelComponentProps) {
siteTitle: string;
versionLabel: string;
}) {
return ( return (
<Translate <Translate
id="theme.docs.versions.unmaintainedVersionLabel" id="theme.docs.versions.unmaintainedVersionLabel"
description="The label used to tell the user that he's browsing an unmaintained doc version" description="The label used to tell the user that he's browsing an unmaintained doc version"
values={{ values={{
siteTitle, siteTitle,
versionLabel: <b>{versionLabel}</b>, versionLabel: <b>{versionMetadata.label}</b>,
}}> }}>
{ {
'This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained.' 'This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained.'
@ -60,6 +57,20 @@ function UnmaintainedVersionLabel({
); );
} }
const BannerLabelComponents: Record<
Props['versionMetadata']['banner'],
ComponentType<BannerLabelComponentProps>
> = {
unreleased: UnreleasedVersionLabel,
unmaintained: UnmaintainedVersionLabel,
};
function BannerLabel(props: BannerLabelComponentProps) {
const BannerLabelComponent =
BannerLabelComponents[props.versionMetadata.banner];
return <BannerLabelComponent {...props} />;
}
function LatestVersionSuggestionLabel({ function LatestVersionSuggestionLabel({
versionLabel, versionLabel,
to, to,
@ -72,7 +83,7 @@ function LatestVersionSuggestionLabel({
return ( return (
<Translate <Translate
id="theme.docs.versions.latestVersionSuggestionLabel" id="theme.docs.versions.latestVersionSuggestionLabel"
description="The label userd to tell the user that he's browsing an unmaintained doc version" description="The label used to tell the user to check the latest version"
values={{ values={{
versionLabel, versionLabel,
latestVersionLink: ( latestVersionLink: (
@ -94,28 +105,22 @@ function LatestVersionSuggestionLabel({
); );
} }
const getVersionMainDoc = (version) => function DocVersionBannerEnabled({versionMetadata}: Props): JSX.Element {
version.docs.find((doc) => doc.id === version.mainDocId);
function DocVersionSuggestions(): JSX.Element {
const { const {
siteConfig: {title: siteTitle}, siteConfig: {title: siteTitle},
} = useDocusaurusContext(); } = useDocusaurusContext();
const {pluginId} = useActivePlugin({failfast: true}); const {pluginId} = useActivePlugin({failfast: true});
const getVersionMainDoc = (version) =>
version.docs.find((doc) => doc.id === version.mainDocId);
const {savePreferredVersionName} = useDocsPreferredVersion(pluginId); const {savePreferredVersionName} = useDocsPreferredVersion(pluginId);
const activeVersion = useActiveVersion(pluginId);
const { const {
latestDocSuggestion, latestDocSuggestion,
latestVersionSuggestion, latestVersionSuggestion,
} = useDocVersionSuggestions(pluginId); } = useDocVersionSuggestions(pluginId);
// No suggestion to be made
if (!latestVersionSuggestion) {
return <></>;
}
// try to link to same doc in latest version (not always possible) // try to link to same doc in latest version (not always possible)
// fallback to main doc of latest version // fallback to main doc of latest version
const latestVersionSuggestedDoc = const latestVersionSuggestedDoc =
@ -124,17 +129,7 @@ function DocVersionSuggestions(): JSX.Element {
return ( return (
<div className="alert alert--warning margin-bottom--md" role="alert"> <div className="alert alert--warning margin-bottom--md" role="alert">
<div> <div>
{activeVersion.name === 'current' ? ( <BannerLabel siteTitle={siteTitle} versionMetadata={versionMetadata} />
<UnreleasedVersionLabel
siteTitle={siteTitle}
versionLabel={activeVersion.label}
/>
) : (
<UnmaintainedVersionLabel
siteTitle={siteTitle}
versionLabel={activeVersion.label}
/>
)}
</div> </div>
<div className="margin-top--md"> <div className="margin-top--md">
<LatestVersionSuggestionLabel <LatestVersionSuggestionLabel
@ -147,4 +142,12 @@ function DocVersionSuggestions(): JSX.Element {
); );
} }
export default DocVersionSuggestions; function DocVersionBanner({versionMetadata}: Props): JSX.Element {
if (versionMetadata.banner === 'none') {
return <></>;
} else {
return <DocVersionBannerEnabled versionMetadata={versionMetadata} />;
}
}
export default DocVersionBanner;

View file

@ -145,14 +145,14 @@ module.exports = {
/** /**
* By default, versioning is enabled on versioned sites. * By default, versioning is enabled on versioned sites.
* This is a way to explicitly disable the versioning feature. * This is a way to explicitly disable the versioning feature.
* This will only include the "current" version (the `/docs` directory)
*/ */
disableVersioning: false, disableVersioning: false,
/** /**
* Skip the next release docs when versioning is enabled. * Include the "current" version of your docs (the `/docs` directory)
* This will not generate HTML files in the production build for documents * Tip: turn it off if the current version is a work-in-progress, not ready to be published
* in `/docs/next` directory, only versioned docs.
*/ */
excludeNextVersionDocs: false, includeCurrentVersion: true,
/** /**
* The last version is the one we navigate to in priority on versioned sites * The last version is the one we navigate to in priority on versioned sites
* It is the one displayed by default in docs navbar items * It is the one displayed by default in docs navbar items
@ -164,8 +164,10 @@ module.exports = {
lastVersion: undefined, lastVersion: undefined,
/** /**
* The docusaurus versioning defaults don't make sense for all projects * The docusaurus versioning defaults don't make sense for all projects
* This gives the ability customize the label and path of each version * This gives the ability customize the properties of each version independantly
* You may not like that default version * - label: the label of the version
* - path: the route path of the version
* - banner: the banner to show at the top of a doc of that version: "none" | "unreleased" | "unmaintained"
*/ */
versions: { versions: {
/* /*
@ -173,10 +175,12 @@ module.exports = {
current: { current: {
label: 'Android SDK v2.0.0 (WIP)', label: 'Android SDK v2.0.0 (WIP)',
path: 'android-2.0.0', path: 'android-2.0.0',
banner: 'none',
}, },
'1.0.0': { '1.0.0': {
label: 'Android SDK v1.0.0', label: 'Android SDK v1.0.0',
path: 'android-1.0.0', path: 'android-1.0.0',
banner: 'unmaintained',
}, },
*/ */
}, },