feat(docs): allow to configure noIndex per doc version (#7963)

This commit is contained in:
Sébastien Lorber 2022-08-17 16:55:49 +02:00 committed by GitHub
parent a335a69982
commit eac3239757
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 103 additions and 42 deletions

View file

@ -901,6 +901,7 @@ exports[`simple website content: data 1`] = `
"label": "Next", "label": "Next",
"banner": null, "banner": null,
"badge": false, "badge": false,
"noIndex": false,
"className": "docs-version-current", "className": "docs-version-current",
"isLast": true, "isLast": true,
"docsSidebars": { "docsSidebars": {
@ -2608,6 +2609,7 @@ exports[`versioned website (community) content: data 1`] = `
"label": "1.0.0", "label": "1.0.0",
"banner": null, "banner": null,
"badge": true, "badge": true,
"noIndex": false,
"className": "docs-version-1.0.0", "className": "docs-version-1.0.0",
"isLast": true, "isLast": true,
"docsSidebars": { "docsSidebars": {
@ -2635,6 +2637,7 @@ exports[`versioned website (community) content: data 1`] = `
"label": "Next", "label": "Next",
"banner": "unreleased", "banner": "unreleased",
"badge": true, "badge": true,
"noIndex": false,
"className": "docs-version-current", "className": "docs-version-current",
"isLast": false, "isLast": false,
"docsSidebars": { "docsSidebars": {
@ -3477,6 +3480,7 @@ exports[`versioned website content: data 1`] = `
"label": "1.0.0", "label": "1.0.0",
"banner": "unmaintained", "banner": "unmaintained",
"badge": true, "badge": true,
"noIndex": false,
"className": "docs-version-1.0.0", "className": "docs-version-1.0.0",
"isLast": false, "isLast": false,
"docsSidebars": { "docsSidebars": {
@ -3544,6 +3548,7 @@ exports[`versioned website content: data 1`] = `
"label": "1.0.1", "label": "1.0.1",
"banner": null, "banner": null,
"badge": true, "badge": true,
"noIndex": true,
"className": "docs-version-1.0.1", "className": "docs-version-1.0.1",
"isLast": true, "isLast": true,
"docsSidebars": { "docsSidebars": {
@ -3599,6 +3604,7 @@ exports[`versioned website content: data 1`] = `
"label": "Next", "label": "Next",
"banner": "unreleased", "banner": "unreleased",
"badge": true, "badge": true,
"noIndex": false,
"className": "docs-version-current", "className": "docs-version-current",
"isLast": false, "isLast": false,
"docsSidebars": { "docsSidebars": {
@ -3674,6 +3680,7 @@ exports[`versioned website content: data 1`] = `
"label": "withSlugs", "label": "withSlugs",
"banner": "unmaintained", "banner": "unmaintained",
"badge": true, "badge": true,
"noIndex": false,
"className": "docs-version-withSlugs", "className": "docs-version-withSlugs",
"isLast": false, "isLast": false,
"docsSidebars": { "docsSidebars": {

View file

@ -362,6 +362,11 @@ describe('versioned website', () => {
options: { options: {
routeBasePath, routeBasePath,
sidebarPath, sidebarPath,
versions: {
'1.0.1': {
noIndex: true,
},
},
}, },
}); });
const plugin = await pluginContentDocs(context, options); const plugin = await pluginContentDocs(context, options);

View file

@ -76,6 +76,7 @@ describe('normalizeDocsPluginOptions', () => {
version1: { version1: {
path: 'hello', path: 'hello',
label: 'world', label: 'world',
noIndex: true,
}, },
}, },
sidebarCollapsible: false, sidebarCollapsible: false,

View file

@ -59,6 +59,7 @@ const VersionOptionsSchema = Joi.object({
banner: Joi.string().equal('none', 'unreleased', 'unmaintained').optional(), banner: Joi.string().equal('none', 'unreleased', 'unmaintained').optional(),
badge: Joi.boolean().optional(), badge: Joi.boolean().optional(),
className: Joi.string().optional(), className: Joi.string().optional(),
noIndex: Joi.boolean().optional(),
}); });
const VersionsOptionsSchema = Joi.object() const VersionsOptionsSchema = Joi.object()

View file

@ -125,6 +125,25 @@ declare module '@docusaurus/plugin-content-docs' {
// TODO support custom version banner? // TODO support custom version banner?
// {type: "error", content: "html content"} // {type: "error", content: "html content"}
export type VersionBanner = 'unreleased' | 'unmaintained'; export type VersionBanner = 'unreleased' | 'unmaintained';
export type VersionOptions = {
/**
* The base path of the version, will be appended to `baseUrl` +
* `routeBasePath`.
*/
path?: string;
/** The label of the version to be used in badges, dropdowns, etc. */
label?: string;
/** The banner to show at the top of a doc of that version. */
banner?: 'none' | VersionBanner;
/** Show a badge with the version label at the top of each doc. */
badge?: boolean;
/** Prevents search engines from indexing this version */
noIndex?: boolean;
/** Add a custom class name to the <html> element of each doc. */
className?: string;
};
export type VersionsOptions = { export type VersionsOptions = {
/** /**
* The version navigated to in priority and displayed by default for docs * The version navigated to in priority and displayed by default for docs
@ -144,23 +163,7 @@ declare module '@docusaurus/plugin-content-docs' {
/** Include the current version of your docs. */ /** Include the current version of your docs. */
includeCurrentVersion: boolean; includeCurrentVersion: boolean;
/** Independent customization of each version's properties. */ /** Independent customization of each version's properties. */
versions: { versions: {[versionName: string]: VersionOptions};
[versionName: string]: {
/**
* The base path of the version, will be appended to `baseUrl` +
* `routeBasePath`.
*/
path?: string;
/** The label of the version to be used in badges, dropdowns, etc. */
label?: string;
/** The banner to show at the top of a doc of that version. */
banner?: 'none' | VersionBanner;
/** Show a badge with the version label at the top of each doc. */
badge?: boolean;
/** Add a custom class name to the <html> element of each doc. */
className?: string;
};
};
}; };
export type SidebarOptions = { export type SidebarOptions = {
/** /**
@ -263,6 +266,8 @@ declare module '@docusaurus/plugin-content-docs' {
banner: VersionBanner | null; banner: VersionBanner | null;
/** Show a badge with the version label at the top of each doc. */ /** Show a badge with the version label at the top of each doc. */
badge: boolean; badge: boolean;
/** Prevents search engines from indexing this version */
noIndex: boolean;
/** Add a custom class name to the <html> element of each doc. */ /** Add a custom class name to the <html> element of each doc. */
className: string; className: string;
/** /**
@ -500,7 +505,7 @@ declare module '@docusaurus/plugin-content-docs' {
export type PropVersionMetadata = Pick< export type PropVersionMetadata = Pick<
VersionMetadata, VersionMetadata,
'label' | 'banner' | 'badge' | 'className' | 'isLast' 'label' | 'banner' | 'badge' | 'className' | 'isLast' | 'noIndex'
> & { > & {
/** ID of the docs plugin this version belongs to. */ /** ID of the docs plugin this version belongs to. */
pluginId: string; pluginId: string;

View file

@ -142,6 +142,7 @@ export function toVersionMetadataProp(
label: loadedVersion.label, label: loadedVersion.label,
banner: loadedVersion.banner, banner: loadedVersion.banner,
badge: loadedVersion.badge, badge: loadedVersion.badge,
noIndex: loadedVersion.noIndex,
className: loadedVersion.className, className: loadedVersion.className,
isLast: loadedVersion.isLast, isLast: loadedVersion.isLast,
docsSidebars: toSidebarsProp(loadedVersion), docsSidebars: toSidebarsProp(loadedVersion),

View file

@ -56,6 +56,7 @@ describe('readVersionsMetadata', () => {
path: '/docs', path: '/docs',
banner: null, banner: null,
badge: false, badge: false,
noIndex: false,
className: 'docs-version-current', className: 'docs-version-current',
}; };
return {simpleSiteDir, defaultOptions, defaultContext, vCurrent}; return {simpleSiteDir, defaultOptions, defaultContext, vCurrent};
@ -218,6 +219,7 @@ describe('readVersionsMetadata', () => {
path: '/docs/next', path: '/docs/next',
banner: 'unreleased', banner: 'unreleased',
badge: true, badge: true,
noIndex: false,
className: 'docs-version-current', className: 'docs-version-current',
}; };
@ -242,6 +244,7 @@ describe('readVersionsMetadata', () => {
path: '/docs', path: '/docs',
banner: null, banner: null,
badge: true, badge: true,
noIndex: false,
className: 'docs-version-1.0.1', className: 'docs-version-1.0.1',
}; };
@ -266,6 +269,7 @@ describe('readVersionsMetadata', () => {
path: '/docs/1.0.0', path: '/docs/1.0.0',
banner: 'unmaintained', banner: 'unmaintained',
badge: true, badge: true,
noIndex: false,
className: 'docs-version-1.0.0', className: 'docs-version-1.0.0',
}; };
@ -290,6 +294,7 @@ describe('readVersionsMetadata', () => {
path: '/docs/withSlugs', path: '/docs/withSlugs',
banner: 'unmaintained', banner: 'unmaintained',
badge: true, badge: true,
noIndex: false,
className: 'docs-version-withSlugs', className: 'docs-version-withSlugs',
}; };
@ -657,6 +662,7 @@ describe('readVersionsMetadata', () => {
path: '/communityBasePath/next', path: '/communityBasePath/next',
banner: 'unreleased', banner: 'unreleased',
badge: true, badge: true,
noIndex: false,
className: 'docs-version-current', className: 'docs-version-current',
}; };
@ -681,6 +687,7 @@ describe('readVersionsMetadata', () => {
path: '/communityBasePath', path: '/communityBasePath',
banner: null, banner: null,
badge: true, badge: true,
noIndex: false,
className: 'docs-version-1.0.0', className: 'docs-version-1.0.0',
}; };

View file

@ -122,6 +122,13 @@ export function getVersionBadge({
return options.versions[versionName]?.badge ?? defaultVersionBadge; return options.versions[versionName]?.badge ?? defaultVersionBadge;
} }
export function getVersionNoIndex({
versionName,
options,
}: VersionContext): VersionMetadata['noIndex'] {
return options.versions[versionName]?.noIndex ?? false;
}
function getVersionClassName({ function getVersionClassName({
versionName, versionName,
options, options,
@ -179,6 +186,7 @@ async function createVersionMetadata(
label: getVersionLabel(context), label: getVersionLabel(context),
banner: getVersionBanner(context), banner: getVersionBanner(context),
badge: getVersionBadge(context), badge: getVersionBadge(context),
noIndex: getVersionNoIndex(context),
className: getVersionClassName(context), className: getVersionClassName(context),
path: routePath, path: routePath,
tagsPath: normalizeUrl([routePath, options.tagsBasePath]), tagsPath: normalizeUrl([routePath, options.tagsBasePath]),

View file

@ -7,7 +7,11 @@
import React from 'react'; import React from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
import {HtmlClassNameProvider, ThemeClassNames} from '@docusaurus/theme-common'; import {
HtmlClassNameProvider,
ThemeClassNames,
PageMetadata,
} from '@docusaurus/theme-common';
import { import {
docVersionSearchTag, docVersionSearchTag,
DocsSidebarProvider, DocsSidebarProvider,
@ -19,13 +23,8 @@ import NotFound from '@theme/NotFound';
import SearchMetadata from '@theme/SearchMetadata'; import SearchMetadata from '@theme/SearchMetadata';
import type {Props} from '@theme/DocPage'; import type {Props} from '@theme/DocPage';
export default function DocPage(props: Props): JSX.Element { function DocPageMetadata(props: Props): JSX.Element {
const {versionMetadata} = props; const {versionMetadata} = props;
const currentDocRouteMetadata = useDocRouteMetadata(props);
if (!currentDocRouteMetadata) {
return <NotFound />;
}
const {docElement, sidebarName, sidebarItems} = currentDocRouteMetadata;
return ( return (
<> <>
<SearchMetadata <SearchMetadata
@ -35,6 +34,25 @@ export default function DocPage(props: Props): JSX.Element {
versionMetadata.version, versionMetadata.version,
)} )}
/> />
<PageMetadata>
{versionMetadata.noIndex && (
<meta name="robots" content="noindex, nofollow" />
)}
</PageMetadata>
</>
);
}
export default function DocPage(props: Props): JSX.Element {
const {versionMetadata} = props;
const currentDocRouteMetadata = useDocRouteMetadata(props);
if (!currentDocRouteMetadata) {
return <NotFound />;
}
const {docElement, sidebarName, sidebarItems} = currentDocRouteMetadata;
return (
<>
<DocPageMetadata {...props} />
<HtmlClassNameProvider <HtmlClassNameProvider
className={clsx( className={clsx(
// TODO: it should be removed from here // TODO: it should be removed from here

View file

@ -26,6 +26,11 @@ const dogfoodingPluginInstances = [
id: 'docs-tests', id: 'docs-tests',
routeBasePath: '/tests/docs', routeBasePath: '/tests/docs',
sidebarPath: '_dogfooding/docs-tests-sidebars.js', sidebarPath: '_dogfooding/docs-tests-sidebars.js',
versions: {
current: {
noIndex: true,
},
},
// Using a _ prefix to test against an edge case regarding MDX partials: https://github.com/facebook/docusaurus/discussions/5181#discussioncomment-1018079 // Using a _ prefix to test against an edge case regarding MDX partials: https://github.com/facebook/docusaurus/discussions/5181#discussioncomment-1018079
path: '_dogfooding/_docs tests', path: '_dogfooding/_docs tests',

View file

@ -142,23 +142,25 @@ type CategoryIndexMatcher = (param: {
#### `VersionsConfig` {#VersionsConfig} #### `VersionsConfig` {#VersionsConfig}
```ts ```ts
type VersionsConfig = { type VersionConfig = {
[versionName: string]: { /**
/** * The base path of the version, will be appended to `baseUrl` +
* The base path of the version, will be appended to `baseUrl` + * `routeBasePath`.
* `routeBasePath`. */
*/ path?: string;
path?: string; /** The label of the version to be used in badges, dropdowns, etc. */
/** The label of the version to be used in badges, dropdowns, etc. */ label?: string;
label?: string; /** The banner to show at the top of a doc of that version. */
/** The banner to show at the top of a doc of that version. */ banner?: 'none' | 'unreleased' | 'unmaintained';
banner?: 'none' | 'unreleased' | 'unmaintained'; /** Show a badge with the version label at the top of each doc. */
/** Show a badge with the version label at the top of each doc. */ badge?: boolean;
badge?: boolean; /** Prevents search engines from indexing this version */
/** Add a custom class name to the <html> element of each doc */ noIndex?: boolean;
className?: string; /** Add a custom class name to the <html> element of each doc */
}; className?: string;
}; };
type VersionsConfig = {[versionName: string]: VersionConfig};
``` ```
### Example configuration {#ex-config} ### Example configuration {#ex-config}

View file

@ -360,7 +360,8 @@ const config = {
} }
: undefined, : undefined,
sitemap: { sitemap: {
ignorePatterns: ['/tests/**'], // Note: /tests/docs already has noIndex: true
ignorePatterns: ['/tests/{blog,pages}/**'],
}, },
}), }),
], ],