mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-07 13:22:26 +02:00
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:
parent
f47826297c
commit
364051f232
13 changed files with 187 additions and 83 deletions
|
@ -405,6 +405,7 @@ Object {
|
|||
\\"pluginId\\": \\"default\\",
|
||||
\\"version\\": \\"current\\",
|
||||
\\"label\\": \\"Next\\",
|
||||
\\"banner\\": \\"none\\",
|
||||
\\"isLast\\": true,
|
||||
\\"docsSidebars\\": {
|
||||
\\"docs\\": [
|
||||
|
@ -872,6 +873,7 @@ Object {
|
|||
\\"pluginId\\": \\"community\\",
|
||||
\\"version\\": \\"1.0.0\\",
|
||||
\\"label\\": \\"1.0.0\\",
|
||||
\\"banner\\": \\"none\\",
|
||||
\\"isLast\\": true,
|
||||
\\"docsSidebars\\": {
|
||||
\\"version-1.0.0/community\\": [
|
||||
|
@ -890,6 +892,7 @@ Object {
|
|||
\\"pluginId\\": \\"community\\",
|
||||
\\"version\\": \\"current\\",
|
||||
\\"label\\": \\"Next\\",
|
||||
\\"banner\\": \\"unreleased\\",
|
||||
\\"isLast\\": false,
|
||||
\\"docsSidebars\\": {
|
||||
\\"community\\": [
|
||||
|
@ -1402,6 +1405,7 @@ Object {
|
|||
\\"pluginId\\": \\"default\\",
|
||||
\\"version\\": \\"1.0.0\\",
|
||||
\\"label\\": \\"1.0.0\\",
|
||||
\\"banner\\": \\"unmaintained\\",
|
||||
\\"isLast\\": false,
|
||||
\\"docsSidebars\\": {
|
||||
\\"version-1.0.0/docs\\": [
|
||||
|
@ -1446,6 +1450,7 @@ Object {
|
|||
\\"pluginId\\": \\"default\\",
|
||||
\\"version\\": \\"1.0.1\\",
|
||||
\\"label\\": \\"1.0.1\\",
|
||||
\\"banner\\": \\"none\\",
|
||||
\\"isLast\\": true,
|
||||
\\"docsSidebars\\": {
|
||||
\\"version-1.0.1/docs\\": [
|
||||
|
@ -1484,6 +1489,7 @@ Object {
|
|||
\\"pluginId\\": \\"default\\",
|
||||
\\"version\\": \\"current\\",
|
||||
\\"label\\": \\"Next\\",
|
||||
\\"banner\\": \\"unreleased\\",
|
||||
\\"isLast\\": false,
|
||||
\\"docsSidebars\\": {
|
||||
\\"docs\\": [
|
||||
|
@ -1522,6 +1528,7 @@ Object {
|
|||
\\"pluginId\\": \\"default\\",
|
||||
\\"version\\": \\"withSlugs\\",
|
||||
\\"label\\": \\"withSlugs\\",
|
||||
\\"banner\\": \\"unmaintained\\",
|
||||
\\"isLast\\": false,
|
||||
\\"docsSidebars\\": {
|
||||
\\"version-1.0.1/docs\\": [
|
||||
|
|
|
@ -21,6 +21,7 @@ const DefaultI18N: I18n = {
|
|||
currentLocale: 'en',
|
||||
locales: ['en'],
|
||||
defaultLocale: 'en',
|
||||
localeConfigs: {},
|
||||
};
|
||||
|
||||
describe('version paths', () => {
|
||||
|
@ -79,6 +80,7 @@ describe('simple site', () => {
|
|||
versionLabel: 'Next',
|
||||
versionName: 'current',
|
||||
versionPath: '/docs',
|
||||
versionBanner: 'none',
|
||||
};
|
||||
return {simpleSiteDir, defaultOptions, defaultContext, vCurrent};
|
||||
}
|
||||
|
@ -233,6 +235,7 @@ describe('versioned site, pluginId=default', () => {
|
|||
versionLabel: 'Next',
|
||||
versionName: 'current',
|
||||
versionPath: '/docs/next',
|
||||
versionBanner: 'unreleased',
|
||||
};
|
||||
|
||||
const v101: VersionMetadata = {
|
||||
|
@ -250,6 +253,7 @@ describe('versioned site, pluginId=default', () => {
|
|||
versionLabel: '1.0.1',
|
||||
versionName: '1.0.1',
|
||||
versionPath: '/docs',
|
||||
versionBanner: 'none',
|
||||
};
|
||||
|
||||
const v100: VersionMetadata = {
|
||||
|
@ -267,6 +271,7 @@ describe('versioned site, pluginId=default', () => {
|
|||
versionLabel: '1.0.0',
|
||||
versionName: '1.0.0',
|
||||
versionPath: '/docs/1.0.0',
|
||||
versionBanner: 'unmaintained',
|
||||
};
|
||||
|
||||
const vwithSlugs: VersionMetadata = {
|
||||
|
@ -287,6 +292,7 @@ describe('versioned site, pluginId=default', () => {
|
|||
versionLabel: 'withSlugs',
|
||||
versionName: 'withSlugs',
|
||||
versionPath: '/docs/withSlugs',
|
||||
versionBanner: 'unmaintained',
|
||||
};
|
||||
|
||||
return {
|
||||
|
@ -357,9 +363,11 @@ describe('versioned site, pluginId=default', () => {
|
|||
versions: {
|
||||
current: {
|
||||
path: 'current-path',
|
||||
banner: 'unmaintained',
|
||||
},
|
||||
'1.0.0': {
|
||||
label: '1.0.0-label',
|
||||
banner: 'unreleased',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -367,12 +375,17 @@ describe('versioned site, pluginId=default', () => {
|
|||
});
|
||||
|
||||
expect(versionsMetadata).toEqual([
|
||||
{...vCurrent, versionPath: '/docs/current-path'},
|
||||
{
|
||||
...vCurrent,
|
||||
versionPath: '/docs/current-path',
|
||||
versionBanner: 'unmaintained',
|
||||
},
|
||||
{
|
||||
...v101,
|
||||
isLast: false,
|
||||
routePriority: undefined,
|
||||
versionPath: '/docs/1.0.1',
|
||||
versionBanner: 'unreleased',
|
||||
},
|
||||
{
|
||||
...v100,
|
||||
|
@ -380,6 +393,7 @@ describe('versioned site, pluginId=default', () => {
|
|||
routePriority: -1,
|
||||
versionLabel: '1.0.0-label',
|
||||
versionPath: '/docs',
|
||||
versionBanner: 'unreleased',
|
||||
},
|
||||
vwithSlugs,
|
||||
]);
|
||||
|
@ -510,7 +524,13 @@ describe('versioned site, pluginId=default', () => {
|
|||
});
|
||||
|
||||
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',
|
||||
versionName: 'current',
|
||||
versionPath: '/communityBasePath/next',
|
||||
versionBanner: 'unreleased',
|
||||
};
|
||||
|
||||
const v100: VersionMetadata = {
|
||||
|
@ -651,6 +672,7 @@ describe('versioned site, pluginId=community', () => {
|
|||
versionLabel: '1.0.0',
|
||||
versionName: '1.0.0',
|
||||
versionPath: '/communityBasePath',
|
||||
versionBanner: 'none',
|
||||
};
|
||||
|
||||
return {versionedSiteDir, defaultOptions, defaultContext, vCurrent, v100};
|
||||
|
@ -695,6 +717,7 @@ describe('versioned site, pluginId=community', () => {
|
|||
isLast: true,
|
||||
routePriority: -1,
|
||||
versionPath: '/communityBasePath',
|
||||
versionBanner: 'none',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
|
@ -350,14 +350,13 @@ describe('docsClientUtils', () => {
|
|||
latestVersionSuggestion: version2,
|
||||
});
|
||||
|
||||
// nothing to suggest, we are already on latest version
|
||||
expect(getDocVersionSuggestions(data, '/docs/')).toEqual({
|
||||
latestDocSuggestion: undefined,
|
||||
latestVersionSuggestion: undefined,
|
||||
latestDocSuggestion: version2.docs[0],
|
||||
latestVersionSuggestion: version2,
|
||||
});
|
||||
expect(getDocVersionSuggestions(data, '/docs/doc2')).toEqual({
|
||||
latestDocSuggestion: undefined,
|
||||
latestVersionSuggestion: undefined,
|
||||
latestDocSuggestion: version2.docs[1],
|
||||
latestVersionSuggestion: version2,
|
||||
});
|
||||
|
||||
expect(getDocVersionSuggestions(data, '/docs/version1/')).toEqual({
|
||||
|
|
|
@ -140,10 +140,10 @@ export const getActiveDocContext = (
|
|||
};
|
||||
|
||||
export type DocVersionSuggestions = {
|
||||
// suggest the latest version
|
||||
latestVersionSuggestion: GlobalVersion;
|
||||
// suggest the same doc, in latest version (if exist)
|
||||
latestDocSuggestion?: GlobalDoc;
|
||||
// suggest the latest version
|
||||
latestVersionSuggestion?: GlobalVersion;
|
||||
};
|
||||
|
||||
export const getDocVersionSuggestions = (
|
||||
|
@ -152,17 +152,7 @@ export const getDocVersionSuggestions = (
|
|||
): DocVersionSuggestions => {
|
||||
const latestVersion = getLatestVersion(data);
|
||||
const activeDocContext = getActiveDocContext(data, pathname);
|
||||
|
||||
// We only suggest another doc/version if user is not using the latest version
|
||||
const isNotOnLatestVersion = activeDocContext.activeVersion !== latestVersion;
|
||||
|
||||
const latestDocSuggestion: GlobalDoc | undefined = isNotOnLatestVersion
|
||||
? activeDocContext?.alternateDocVersions[latestVersion.name]
|
||||
: undefined;
|
||||
|
||||
const latestVersionSuggestion = isNotOnLatestVersion
|
||||
? latestVersion
|
||||
: undefined;
|
||||
|
||||
return {latestDocSuggestion, latestVersionSuggestion};
|
||||
const latestDocSuggestion: GlobalDoc | undefined =
|
||||
activeDocContext?.alternateDocVersions[latestVersion.name];
|
||||
return {latestDocSuggestion, latestVersionSuggestion: latestVersion};
|
||||
};
|
||||
|
|
|
@ -49,6 +49,7 @@ export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'> = {
|
|||
const VersionOptionsSchema = Joi.object({
|
||||
path: Joi.string().allow('').optional(),
|
||||
label: Joi.string().optional(),
|
||||
banner: Joi.string().equal('none', 'unreleased', 'unmaintained').optional(),
|
||||
});
|
||||
|
||||
const VersionsOptionsSchema = Joi.object()
|
||||
|
@ -101,6 +102,7 @@ export const OptionsSchema = Joi.object({
|
|||
showLastUpdateAuthor: Joi.bool().default(
|
||||
DEFAULT_OPTIONS.showLastUpdateAuthor,
|
||||
),
|
||||
// TODO deprecated, excludeNextVersionDocs replaced by includeCurrentVersion
|
||||
excludeNextVersionDocs: Joi.bool().default(
|
||||
DEFAULT_OPTIONS.excludeNextVersionDocs,
|
||||
),
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
/* eslint-disable camelcase */
|
||||
|
||||
declare module '@docusaurus/plugin-content-docs-types' {
|
||||
import type {VersionBanner} from './types';
|
||||
|
||||
export type PermalinkToSidebar = {
|
||||
[permalink: string]: string;
|
||||
};
|
||||
|
@ -16,6 +18,7 @@ declare module '@docusaurus/plugin-content-docs-types' {
|
|||
pluginId: string;
|
||||
version: string;
|
||||
label: string;
|
||||
banner: VersionBanner;
|
||||
isLast: boolean;
|
||||
docsSidebars: PropSidebars;
|
||||
permalinkToSidebar: PermalinkToSidebar;
|
||||
|
@ -83,6 +86,7 @@ declare module '@theme/DocItem' {
|
|||
|
||||
export type Props = {
|
||||
readonly route: DocumentRoute;
|
||||
readonly versionMetadata: PropVersionMetadata;
|
||||
readonly content: {
|
||||
readonly frontMatter: FrontMatter;
|
||||
readonly metadata: Metadata;
|
||||
|
@ -96,6 +100,17 @@ declare module '@theme/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' {
|
||||
import type {PropVersionMetadata} from '@docusaurus/plugin-content-docs-types';
|
||||
import type {DocumentRoute} from '@theme/DocItem';
|
||||
|
|
|
@ -74,6 +74,7 @@ export function toVersionMetadataProp(
|
|||
pluginId,
|
||||
version: loadedVersion.versionName,
|
||||
label: loadedVersion.versionLabel,
|
||||
banner: loadedVersion.versionBanner,
|
||||
isLast: loadedVersion.isLast,
|
||||
docsSidebars: toSidebarsProp(loadedVersion),
|
||||
permalinkToSidebar: loadedVersion.permalinkToSidebar,
|
||||
|
|
|
@ -30,6 +30,7 @@ export type VersionMetadata = ContentPaths & {
|
|||
versionPath: string; // /baseUrl/docs/1.0.0
|
||||
versionEditUrl?: string | undefined;
|
||||
versionEditUrlLocalized?: string | undefined;
|
||||
versionBanner: VersionBanner;
|
||||
isLast: boolean;
|
||||
sidebarFilePath: string | false | undefined; // versioned_sidebars/1.0.0.json
|
||||
routePriority: number | undefined; // -1 for the latest docs
|
||||
|
@ -59,9 +60,13 @@ export type PathOptions = {
|
|||
sidebarPath?: string | false | undefined;
|
||||
};
|
||||
|
||||
// TODO support custom version banner? {type: "error", content: "html content"}
|
||||
export type VersionBanner = 'none' | 'unreleased' | 'unmaintained';
|
||||
|
||||
export type VersionOptions = {
|
||||
path?: string;
|
||||
label?: string;
|
||||
banner?: VersionBanner;
|
||||
};
|
||||
|
||||
export type VersionsOptions = {
|
||||
|
|
|
@ -9,6 +9,7 @@ import path from 'path';
|
|||
import fs from 'fs-extra';
|
||||
import {
|
||||
PluginOptions,
|
||||
VersionBanner,
|
||||
VersionMetadata,
|
||||
VersionOptions,
|
||||
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({
|
||||
versionName,
|
||||
isLast,
|
||||
versionNames,
|
||||
lastVersionName,
|
||||
context,
|
||||
options,
|
||||
}: {
|
||||
versionName: string;
|
||||
isLast: boolean;
|
||||
versionNames: string[];
|
||||
lastVersionName: string;
|
||||
context: Pick<LoadContext, 'siteDir' | 'baseUrl' | 'i18n'>;
|
||||
options: Pick<
|
||||
PluginOptions,
|
||||
|
@ -285,6 +336,8 @@ function createVersionMetadata({
|
|||
options,
|
||||
});
|
||||
|
||||
const isLast = versionName === lastVersionName;
|
||||
|
||||
// retro-compatible values
|
||||
const defaultVersionLabel =
|
||||
versionName === CURRENT_VERSION_NAME ? 'Next' : versionName;
|
||||
|
@ -321,6 +374,12 @@ function createVersionMetadata({
|
|||
versionPath,
|
||||
versionEditUrl: versionEditUrls?.versionEditUrl,
|
||||
versionEditUrlLocalized: versionEditUrls?.versionEditUrlLocalized,
|
||||
versionBanner: getVersionBanner({
|
||||
versionName,
|
||||
versionNames,
|
||||
lastVersionName,
|
||||
options,
|
||||
}),
|
||||
isLast,
|
||||
routePriority,
|
||||
sidebarFilePath,
|
||||
|
@ -486,7 +545,8 @@ export function readVersionsMetadata({
|
|||
const versionsMetadata = versionNames.map((versionName) =>
|
||||
createVersionMetadata({
|
||||
versionName,
|
||||
isLast: versionName === lastVersionName,
|
||||
versionNames,
|
||||
lastVersionName,
|
||||
context,
|
||||
options,
|
||||
}),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue