mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-13 17:17:28 +02:00
feat(v2): docs options.onlyIncludeVersions (#3373)
* docs options.onlyIncludeVersions * adapt docsVersionDropdown if we render a single version * fix bad error message * fix netlify deploy when versioning is disabled
This commit is contained in:
parent
149d82c730
commit
d8cfabb66a
8 changed files with 144 additions and 22 deletions
|
@ -146,7 +146,7 @@ describe('simple site', () => {
|
||||||
context: defaultContext,
|
context: defaultContext,
|
||||||
}),
|
}),
|
||||||
).toThrowErrorMatchingInlineSnapshot(
|
).toThrowErrorMatchingInlineSnapshot(
|
||||||
`"Docs versions option provided configuration for unknown versions: unknownVersionName1,unknownVersionName2. Available version names are: current"`,
|
`"Bad docs options.versions: unknown versions found: unknownVersionName1,unknownVersionName2. Available version names are: current"`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -297,6 +297,19 @@ describe('versioned site, pluginId=default', () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('readVersionsMetadata versioned site with onlyIncludeVersions option', () => {
|
||||||
|
const versionsMetadata = readVersionsMetadata({
|
||||||
|
options: {
|
||||||
|
...defaultOptions,
|
||||||
|
// Order reversed on purpose: should not have any impact
|
||||||
|
onlyIncludeVersions: [vwithSlugs.versionName, v101.versionName],
|
||||||
|
},
|
||||||
|
context: defaultContext,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(versionsMetadata).toEqual([v101, vwithSlugs]);
|
||||||
|
});
|
||||||
|
|
||||||
test('readVersionsMetadata versioned site with disableVersioning', () => {
|
test('readVersionsMetadata versioned site with disableVersioning', () => {
|
||||||
const versionsMetadata = readVersionsMetadata({
|
const versionsMetadata = readVersionsMetadata({
|
||||||
options: {...defaultOptions, disableVersioning: true},
|
options: {...defaultOptions, disableVersioning: true},
|
||||||
|
@ -323,6 +336,49 @@ describe('versioned site, pluginId=default', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('readVersionsMetadata versioned site with empty onlyIncludeVersions', () => {
|
||||||
|
expect(() =>
|
||||||
|
readVersionsMetadata({
|
||||||
|
options: {
|
||||||
|
...defaultOptions,
|
||||||
|
onlyIncludeVersions: [],
|
||||||
|
},
|
||||||
|
context: defaultContext,
|
||||||
|
}),
|
||||||
|
).toThrowErrorMatchingInlineSnapshot(
|
||||||
|
`"Bad docs options.onlyIncludeVersions: an empty array is not allowed, at least one version is needed"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('readVersionsMetadata versioned site with unknown versions in onlyIncludeVersions', () => {
|
||||||
|
expect(() =>
|
||||||
|
readVersionsMetadata({
|
||||||
|
options: {
|
||||||
|
...defaultOptions,
|
||||||
|
onlyIncludeVersions: ['unknownVersion1', 'unknownVersion2'],
|
||||||
|
},
|
||||||
|
context: defaultContext,
|
||||||
|
}),
|
||||||
|
).toThrowErrorMatchingInlineSnapshot(
|
||||||
|
`"Bad docs options.onlyIncludeVersions: unknown versions found: unknownVersion1,unknownVersion2. Available version names are: current, 1.0.1, 1.0.0, withSlugs"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('readVersionsMetadata versioned site with lastVersion not in onlyIncludeVersions', () => {
|
||||||
|
expect(() =>
|
||||||
|
readVersionsMetadata({
|
||||||
|
options: {
|
||||||
|
...defaultOptions,
|
||||||
|
lastVersion: '1.0.1',
|
||||||
|
onlyIncludeVersions: ['current', '1.0.0'],
|
||||||
|
},
|
||||||
|
context: defaultContext,
|
||||||
|
}),
|
||||||
|
).toThrowErrorMatchingInlineSnapshot(
|
||||||
|
`"Bad docs options.lastVersion: if you use both the onlyIncludeVersions and lastVersion options, then lastVersion must be present in the provided onlyIncludeVersions array"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('readVersionsMetadata versioned site with invalid versions.json file', () => {
|
test('readVersionsMetadata versioned site with invalid versions.json file', () => {
|
||||||
const mock = jest.spyOn(JSON, 'parse').mockImplementationOnce(() => {
|
const mock = jest.spyOn(JSON, 'parse').mockImplementationOnce(() => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -68,6 +68,7 @@ export const OptionsSchema = Joi.object({
|
||||||
includeCurrentVersion: Joi.bool().default(
|
includeCurrentVersion: Joi.bool().default(
|
||||||
DEFAULT_OPTIONS.includeCurrentVersion,
|
DEFAULT_OPTIONS.includeCurrentVersion,
|
||||||
),
|
),
|
||||||
|
onlyIncludeVersions: Joi.array().items(Joi.string().required()).optional(),
|
||||||
disableVersioning: Joi.bool().default(DEFAULT_OPTIONS.disableVersioning),
|
disableVersioning: Joi.bool().default(DEFAULT_OPTIONS.disableVersioning),
|
||||||
lastVersion: Joi.string().optional(),
|
lastVersion: Joi.string().optional(),
|
||||||
versions: VersionsOptionsSchema,
|
versions: VersionsOptionsSchema,
|
||||||
|
|
|
@ -47,6 +47,7 @@ export type VersionOptions = {
|
||||||
export type VersionsOptions = {
|
export type VersionsOptions = {
|
||||||
lastVersion?: string;
|
lastVersion?: string;
|
||||||
versions: Record<string, VersionOptions>;
|
versions: Record<string, VersionOptions>;
|
||||||
|
onlyIncludeVersions?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PluginOptions = MetadataOptions &
|
export type PluginOptions = MetadataOptions &
|
||||||
|
|
|
@ -257,17 +257,60 @@ function checkVersionsOptions(
|
||||||
`Docs option lastVersion=${options.lastVersion} is invalid. ${availableVersionNamesMsg}`,
|
`Docs option lastVersion=${options.lastVersion} is invalid. ${availableVersionNamesMsg}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const unknownVersionNames = difference(
|
const unknownVersionConfigNames = difference(
|
||||||
Object.keys(options.versions),
|
Object.keys(options.versions),
|
||||||
availableVersionNames,
|
availableVersionNames,
|
||||||
);
|
);
|
||||||
if (unknownVersionNames.length > 0) {
|
if (unknownVersionConfigNames.length > 0) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Docs versions option provided configuration for unknown versions: ${unknownVersionNames.join(
|
`Bad docs options.versions: unknown versions found: ${unknownVersionConfigNames.join(
|
||||||
',',
|
',',
|
||||||
)}. ${availableVersionNamesMsg}`,
|
)}. ${availableVersionNamesMsg}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.onlyIncludeVersions) {
|
||||||
|
if (options.onlyIncludeVersions.length === 0) {
|
||||||
|
throw new Error(
|
||||||
|
`Bad docs options.onlyIncludeVersions: an empty array is not allowed, at least one version is needed`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const unknownOnlyIncludeVersionNames = difference(
|
||||||
|
options.onlyIncludeVersions,
|
||||||
|
availableVersionNames,
|
||||||
|
);
|
||||||
|
if (unknownOnlyIncludeVersionNames.length > 0) {
|
||||||
|
throw new Error(
|
||||||
|
`Bad docs options.onlyIncludeVersions: unknown versions found: ${unknownOnlyIncludeVersionNames.join(
|
||||||
|
',',
|
||||||
|
)}. ${availableVersionNamesMsg}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
options.lastVersion &&
|
||||||
|
!options.onlyIncludeVersions.includes(options.lastVersion)
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
`Bad docs options.lastVersion: if you use both the onlyIncludeVersions and lastVersion options, then lastVersion must be present in the provided onlyIncludeVersions array`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter versions according to provided options
|
||||||
|
// Note: we preserve the order in which versions are provided
|
||||||
|
// the order of the onlyIncludeVersions array does not matter
|
||||||
|
function filterVersions(
|
||||||
|
versionNamesUnfiltered: string[],
|
||||||
|
options: Pick<PluginOptions, 'onlyIncludeVersions'>,
|
||||||
|
) {
|
||||||
|
if (options.onlyIncludeVersions) {
|
||||||
|
return versionNamesUnfiltered.filter((name) =>
|
||||||
|
options.onlyIncludeVersions!.includes(name),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return versionNamesUnfiltered;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readVersionsMetadata({
|
export function readVersionsMetadata({
|
||||||
|
@ -285,11 +328,14 @@ export function readVersionsMetadata({
|
||||||
| 'disableVersioning'
|
| 'disableVersioning'
|
||||||
| 'lastVersion'
|
| 'lastVersion'
|
||||||
| 'versions'
|
| 'versions'
|
||||||
|
| 'onlyIncludeVersions'
|
||||||
>;
|
>;
|
||||||
}): VersionMetadata[] {
|
}): VersionMetadata[] {
|
||||||
const versionNames = readVersionNames(context.siteDir, options);
|
const versionNamesUnfiltered = readVersionNames(context.siteDir, options);
|
||||||
|
|
||||||
checkVersionsOptions(versionNames, options);
|
checkVersionsOptions(versionNamesUnfiltered, options);
|
||||||
|
|
||||||
|
const versionNames = filterVersions(versionNamesUnfiltered, options);
|
||||||
|
|
||||||
const lastVersionName =
|
const lastVersionName =
|
||||||
options.lastVersion ?? getDefaultLastVersionName(versionNames);
|
options.lastVersion ?? getDefaultLastVersionName(versionNames);
|
||||||
|
|
|
@ -26,7 +26,15 @@ export default function DocsVersionDropdownNavbarItem({
|
||||||
const versions = useVersions(docsPluginId);
|
const versions = useVersions(docsPluginId);
|
||||||
const latestVersion = useLatestVersion(docsPluginId);
|
const latestVersion = useLatestVersion(docsPluginId);
|
||||||
|
|
||||||
const items = versions.map((version) => {
|
function getItems() {
|
||||||
|
// We don't want to render a version dropdown with 0 or 1 item
|
||||||
|
// If we build the site with a single docs version (onlyIncludeVersions: ['1.0.0'])
|
||||||
|
// We'd rather render a buttonb instead of a dropdown
|
||||||
|
if (versions.length <= 2) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return versions.map((version) => {
|
||||||
// We try to link to the same doc, in another version
|
// We try to link to the same doc, in another version
|
||||||
// When not possible, fallback to the "main doc" of the version
|
// When not possible, fallback to the "main doc" of the version
|
||||||
const versionDoc =
|
const versionDoc =
|
||||||
|
@ -39,6 +47,7 @@ export default function DocsVersionDropdownNavbarItem({
|
||||||
isActive: () => version === activeDocContext?.activeVersion,
|
isActive: () => version === activeDocContext?.activeVersion,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const dropdownVersion = activeDocContext.activeVersion ?? latestVersion;
|
const dropdownVersion = activeDocContext.activeVersion ?? latestVersion;
|
||||||
|
|
||||||
|
@ -54,7 +63,7 @@ export default function DocsVersionDropdownNavbarItem({
|
||||||
mobile={mobile}
|
mobile={mobile}
|
||||||
label={dropdownLabel}
|
label={dropdownLabel}
|
||||||
to={dropdownTo}
|
to={dropdownTo}
|
||||||
items={items}
|
items={getItems()}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,6 +362,11 @@ module.exports = {
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Sometimes you only want to include a subset of all available versions.
|
||||||
|
* Tip: limit to 2 or 3 versions to improve startup and build time in dev and deploy previews
|
||||||
|
*/
|
||||||
|
onlyIncludeVersions: undefined, // ex: ["current", "1.0.0", "2.0.0"]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
|
@ -178,6 +178,10 @@ module.exports = {
|
||||||
remarkPlugins: [require('./src/plugins/remark-npm2yarn')],
|
remarkPlugins: [require('./src/plugins/remark-npm2yarn')],
|
||||||
disableVersioning: isVersioningDisabled,
|
disableVersioning: isVersioningDisabled,
|
||||||
lastVersion: isDev || isDeployPreview ? 'current' : undefined,
|
lastVersion: isDev || isDeployPreview ? 'current' : undefined,
|
||||||
|
onlyIncludeVersions:
|
||||||
|
!isVersioningDisabled && (isDev || isDeployPreview)
|
||||||
|
? ['current', ...versions.slice(0, 2)]
|
||||||
|
: undefined,
|
||||||
versions: {
|
versions: {
|
||||||
current: {
|
current: {
|
||||||
// path: isDev || isDeployPreview ? '' : 'next',
|
// path: isDev || isDeployPreview ? '' : 'next',
|
||||||
|
|
|
@ -17722,7 +17722,7 @@ react-dev-utils@^9.1.0:
|
||||||
strip-ansi "5.2.0"
|
strip-ansi "5.2.0"
|
||||||
text-table "0.2.0"
|
text-table "0.2.0"
|
||||||
|
|
||||||
react-dom@^16.10.2, react-dom@^16.8.4:
|
react-dom@^16.8.4:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
|
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
|
||||||
integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==
|
integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==
|
||||||
|
@ -17902,7 +17902,7 @@ react-waypoint@^9.0.2:
|
||||||
prop-types "^15.0.0"
|
prop-types "^15.0.0"
|
||||||
react-is "^16.6.3"
|
react-is "^16.6.3"
|
||||||
|
|
||||||
react@^16.10.2, react@^16.8.4:
|
react@^16.8.4:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
|
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
|
||||||
integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
|
integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue