diff --git a/packages/create-docusaurus/templates/facebook/sidebars.js b/packages/create-docusaurus/templates/facebook/sidebars.js index be7a480ce62a..7c923fa366ee 100644 --- a/packages/create-docusaurus/templates/facebook/sidebars.js +++ b/packages/create-docusaurus/templates/facebook/sidebars.js @@ -25,10 +25,12 @@ module.exports = { // But you can create a sidebar manually /* tutorialSidebar: [ + 'intro', + 'hello', { type: 'category', label: 'Tutorial', - items: ['hello'], + items: ['tutorial-basics/create-a-document'], }, ], */ diff --git a/packages/create-docusaurus/templates/shared/docs/tutorial-basics/congratulations.md b/packages/create-docusaurus/templates/shared/docs/tutorial-basics/congratulations.md index 9ef99bbadd93..04771a00b72f 100644 --- a/packages/create-docusaurus/templates/shared/docs/tutorial-basics/congratulations.md +++ b/packages/create-docusaurus/templates/shared/docs/tutorial-basics/congratulations.md @@ -14,7 +14,9 @@ Anything **unclear** or **buggy** in this tutorial? [Please report it!](https:// ## What's next? -- Read the [official documentation](https://docusaurus.io/). +- Read the [official documentation](https://docusaurus.io/) +- Modify your site configuration with [`docusaurus.config.js`](https://docusaurus.io/docs/api/docusaurus-config) +- Add navbar and footer items with [`themeConfig`](https://docusaurus.io/docs/api/themes/configuration) - Add a custom [Design and Layout](https://docusaurus.io/docs/styling-layout) - Add a [search bar](https://docusaurus.io/docs/search) - Find inspirations in the [Docusaurus showcase](https://docusaurus.io/showcase) diff --git a/packages/create-docusaurus/templates/shared/docs/tutorial-basics/create-a-document.md b/packages/create-docusaurus/templates/shared/docs/tutorial-basics/create-a-document.md index 3c92695c517e..ffddfa8eb8ac 100644 --- a/packages/create-docusaurus/templates/shared/docs/tutorial-basics/create-a-document.md +++ b/packages/create-docusaurus/templates/shared/docs/tutorial-basics/create-a-document.md @@ -44,11 +44,13 @@ It is also possible to create your sidebar explicitly in `sidebars.js`: ```js title="sidebars.js" module.exports = { tutorialSidebar: [ + 'intro', + // highlight-next-line + 'hello', { type: 'category', label: 'Tutorial', - // highlight-next-line - items: ['hello'], + items: ['tutorial-basics/create-a-document'], }, ], }; diff --git a/packages/create-docusaurus/templates/shared/sidebars.js b/packages/create-docusaurus/templates/shared/sidebars.js index fd342f2cdb2b..9ab54c2459c4 100644 --- a/packages/create-docusaurus/templates/shared/sidebars.js +++ b/packages/create-docusaurus/templates/shared/sidebars.js @@ -19,10 +19,12 @@ const sidebars = { // But you can create a sidebar manually /* tutorialSidebar: [ + 'intro', + 'hello', { type: 'category', label: 'Tutorial', - items: ['hello'], + items: ['tutorial-basics/create-a-document'], }, ], */ diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json index d76976a1201c..0e5e58054d5e 100644 --- a/packages/docusaurus-plugin-content-blog/package.json +++ b/packages/docusaurus-plugin-content-blog/package.json @@ -36,7 +36,6 @@ "webpack": "^5.73.0" }, "devDependencies": { - "@docusaurus/types": "2.0.0-beta.21", "escape-string-regexp": "^4.0.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-content-docs/package.json b/packages/docusaurus-plugin-content-docs/package.json index 4b4c12ea6c7f..ae6ca56ca9d8 100644 --- a/packages/docusaurus-plugin-content-docs/package.json +++ b/packages/docusaurus-plugin-content-docs/package.json @@ -52,7 +52,6 @@ "webpack": "^5.73.0" }, "devDependencies": { - "@docusaurus/types": "2.0.0-beta.21", "@types/js-yaml": "^4.0.5", "@types/picomatch": "^2.3.0", "commander": "^5.1.0", diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap index c428a6c55e86..3072419e03ef 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap @@ -901,6 +901,7 @@ exports[`simple website content: data 1`] = ` "label": "Next", "banner": null, "badge": false, + "noIndex": false, "className": "docs-version-current", "isLast": true, "docsSidebars": { @@ -2608,6 +2609,7 @@ exports[`versioned website (community) content: data 1`] = ` "label": "1.0.0", "banner": null, "badge": true, + "noIndex": false, "className": "docs-version-1.0.0", "isLast": true, "docsSidebars": { @@ -2635,6 +2637,7 @@ exports[`versioned website (community) content: data 1`] = ` "label": "Next", "banner": "unreleased", "badge": true, + "noIndex": false, "className": "docs-version-current", "isLast": false, "docsSidebars": { @@ -3477,6 +3480,7 @@ exports[`versioned website content: data 1`] = ` "label": "1.0.0", "banner": "unmaintained", "badge": true, + "noIndex": false, "className": "docs-version-1.0.0", "isLast": false, "docsSidebars": { @@ -3544,6 +3548,7 @@ exports[`versioned website content: data 1`] = ` "label": "1.0.1", "banner": null, "badge": true, + "noIndex": true, "className": "docs-version-1.0.1", "isLast": true, "docsSidebars": { @@ -3599,6 +3604,7 @@ exports[`versioned website content: data 1`] = ` "label": "Next", "banner": "unreleased", "badge": true, + "noIndex": false, "className": "docs-version-current", "isLast": false, "docsSidebars": { @@ -3674,6 +3680,7 @@ exports[`versioned website content: data 1`] = ` "label": "withSlugs", "banner": "unmaintained", "badge": true, + "noIndex": false, "className": "docs-version-withSlugs", "isLast": false, "docsSidebars": { diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts index 11e54417d884..f7672377404f 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts @@ -362,6 +362,11 @@ describe('versioned website', () => { options: { routeBasePath, sidebarPath, + versions: { + '1.0.1': { + noIndex: true, + }, + }, }, }); const plugin = await pluginContentDocs(context, options); diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/options.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/options.test.ts index 69ce0b9a597e..0cfa5aa02637 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/options.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/options.test.ts @@ -76,6 +76,7 @@ describe('normalizeDocsPluginOptions', () => { version1: { path: 'hello', label: 'world', + noIndex: true, }, }, sidebarCollapsible: false, diff --git a/packages/docusaurus-plugin-content-docs/src/options.ts b/packages/docusaurus-plugin-content-docs/src/options.ts index f81479baff7a..7ef8c417a65d 100644 --- a/packages/docusaurus-plugin-content-docs/src/options.ts +++ b/packages/docusaurus-plugin-content-docs/src/options.ts @@ -59,6 +59,7 @@ const VersionOptionsSchema = Joi.object({ banner: Joi.string().equal('none', 'unreleased', 'unmaintained').optional(), badge: Joi.boolean().optional(), className: Joi.string().optional(), + noIndex: Joi.boolean().optional(), }); const VersionsOptionsSchema = Joi.object() diff --git a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts index 35f1224c3b56..7bd8bbf3cbf0 100644 --- a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts +++ b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts @@ -125,6 +125,25 @@ declare module '@docusaurus/plugin-content-docs' { // TODO support custom version banner? // {type: "error", content: "html content"} 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 element of each doc. */ + className?: string; + }; + export type VersionsOptions = { /** * 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. */ includeCurrentVersion: boolean; /** Independent customization of each version's properties. */ - versions: { - [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 element of each doc. */ - className?: string; - }; - }; + versions: {[versionName: string]: VersionOptions}; }; export type SidebarOptions = { /** @@ -263,6 +266,8 @@ declare module '@docusaurus/plugin-content-docs' { banner: VersionBanner | null; /** 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 element of each doc. */ className: string; /** @@ -500,7 +505,7 @@ declare module '@docusaurus/plugin-content-docs' { export type PropVersionMetadata = Pick< VersionMetadata, - 'label' | 'banner' | 'badge' | 'className' | 'isLast' + 'label' | 'banner' | 'badge' | 'className' | 'isLast' | 'noIndex' > & { /** ID of the docs plugin this version belongs to. */ pluginId: string; diff --git a/packages/docusaurus-plugin-content-docs/src/props.ts b/packages/docusaurus-plugin-content-docs/src/props.ts index d279e13f1f4c..e8f05ba4ebe4 100644 --- a/packages/docusaurus-plugin-content-docs/src/props.ts +++ b/packages/docusaurus-plugin-content-docs/src/props.ts @@ -142,6 +142,7 @@ export function toVersionMetadataProp( label: loadedVersion.label, banner: loadedVersion.banner, badge: loadedVersion.badge, + noIndex: loadedVersion.noIndex, className: loadedVersion.className, isLast: loadedVersion.isLast, docsSidebars: toSidebarsProp(loadedVersion), diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts index 1a8746574a5e..555004846ea4 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts @@ -44,6 +44,7 @@ export type SidebarItemLink = SidebarItemBase & { type: 'link'; href: string; label: string; + autoAddBaseUrl?: boolean; }; export type SidebarItemAutogenerated = SidebarItemBase & { diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/validation.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/validation.ts index f1cc5a168e3c..0273132360d1 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/validation.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/validation.ts @@ -59,6 +59,7 @@ const sidebarItemHtmlSchema = sidebarItemBaseSchema.append({ const sidebarItemLinkSchema = sidebarItemBaseSchema.append({ type: 'link', href: URISchema.required(), + autoAddBaseUrl: Joi.boolean(), label: Joi.string() .required() .messages({'any.unknown': '"label" must be a string'}), diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts index a52ba1b7d186..26173cb91e0c 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts @@ -56,6 +56,7 @@ describe('readVersionsMetadata', () => { path: '/docs', banner: null, badge: false, + noIndex: false, className: 'docs-version-current', }; return {simpleSiteDir, defaultOptions, defaultContext, vCurrent}; @@ -218,6 +219,7 @@ describe('readVersionsMetadata', () => { path: '/docs/next', banner: 'unreleased', badge: true, + noIndex: false, className: 'docs-version-current', }; @@ -242,6 +244,7 @@ describe('readVersionsMetadata', () => { path: '/docs', banner: null, badge: true, + noIndex: false, className: 'docs-version-1.0.1', }; @@ -266,6 +269,7 @@ describe('readVersionsMetadata', () => { path: '/docs/1.0.0', banner: 'unmaintained', badge: true, + noIndex: false, className: 'docs-version-1.0.0', }; @@ -290,6 +294,7 @@ describe('readVersionsMetadata', () => { path: '/docs/withSlugs', banner: 'unmaintained', badge: true, + noIndex: false, className: 'docs-version-withSlugs', }; @@ -657,6 +662,7 @@ describe('readVersionsMetadata', () => { path: '/communityBasePath/next', banner: 'unreleased', badge: true, + noIndex: false, className: 'docs-version-current', }; @@ -681,6 +687,7 @@ describe('readVersionsMetadata', () => { path: '/communityBasePath', banner: null, badge: true, + noIndex: false, className: 'docs-version-1.0.0', }; diff --git a/packages/docusaurus-plugin-content-docs/src/versions/index.ts b/packages/docusaurus-plugin-content-docs/src/versions/index.ts index d39bee56198d..39edeba0e092 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/index.ts @@ -122,6 +122,13 @@ export function getVersionBadge({ return options.versions[versionName]?.badge ?? defaultVersionBadge; } +export function getVersionNoIndex({ + versionName, + options, +}: VersionContext): VersionMetadata['noIndex'] { + return options.versions[versionName]?.noIndex ?? false; +} + function getVersionClassName({ versionName, options, @@ -179,6 +186,7 @@ async function createVersionMetadata( label: getVersionLabel(context), banner: getVersionBanner(context), badge: getVersionBadge(context), + noIndex: getVersionNoIndex(context), className: getVersionClassName(context), path: routePath, tagsPath: normalizeUrl([routePath, options.tagsBasePath]), diff --git a/packages/docusaurus-plugin-content-pages/package.json b/packages/docusaurus-plugin-content-pages/package.json index e56c596ac690..31498684d00e 100644 --- a/packages/docusaurus-plugin-content-pages/package.json +++ b/packages/docusaurus-plugin-content-pages/package.json @@ -27,9 +27,6 @@ "tslib": "^2.4.0", "webpack": "^5.73.0" }, - "devDependencies": { - "@docusaurus/types": "2.0.0-beta.21" - }, "peerDependencies": { "react": "^16.8.4 || ^17.0.0", "react-dom": "^16.8.4 || ^17.0.0" diff --git a/packages/docusaurus-plugin-debug/package.json b/packages/docusaurus-plugin-debug/package.json index a48caa76b1c1..c4b6ca6e2659 100644 --- a/packages/docusaurus-plugin-debug/package.json +++ b/packages/docusaurus-plugin-debug/package.json @@ -27,9 +27,6 @@ "react-json-view": "^1.21.3", "tslib": "^2.4.0" }, - "devDependencies": { - "@docusaurus/types": "2.0.0-beta.21" - }, "peerDependencies": { "react": "^16.8.4 || ^17.0.0", "react-dom": "^16.8.4 || ^17.0.0" diff --git a/packages/docusaurus-plugin-google-analytics/package.json b/packages/docusaurus-plugin-google-analytics/package.json index b3a9cd197012..3814ccb6cdd1 100644 --- a/packages/docusaurus-plugin-google-analytics/package.json +++ b/packages/docusaurus-plugin-google-analytics/package.json @@ -23,9 +23,6 @@ "@docusaurus/utils-validation": "2.0.1", "tslib": "^2.4.0" }, - "devDependencies": { - "@docusaurus/types": "2.0.0-beta.21" - }, "peerDependencies": { "react": "^16.8.4 || ^17.0.0", "react-dom": "^16.8.4 || ^17.0.0" diff --git a/packages/docusaurus-plugin-google-gtag/package.json b/packages/docusaurus-plugin-google-gtag/package.json index 9a6a4924737f..5b3ef833caef 100644 --- a/packages/docusaurus-plugin-google-gtag/package.json +++ b/packages/docusaurus-plugin-google-gtag/package.json @@ -23,9 +23,6 @@ "@docusaurus/utils-validation": "2.0.1", "tslib": "^2.4.0" }, - "devDependencies": { - "@docusaurus/types": "2.0.0-beta.21" - }, "peerDependencies": { "react": "^16.8.4 || ^17.0.0", "react-dom": "^16.8.4 || ^17.0.0" diff --git a/packages/docusaurus-plugin-ideal-image/package.json b/packages/docusaurus-plugin-ideal-image/package.json index 120bc1b50084..18da96437cab 100644 --- a/packages/docusaurus-plugin-ideal-image/package.json +++ b/packages/docusaurus-plugin-ideal-image/package.json @@ -34,7 +34,6 @@ }, "devDependencies": { "@docusaurus/module-type-aliases": "2.0.1", - "@docusaurus/types": "2.0.0-beta.21", "fs-extra": "^10.1.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-sitemap/package.json b/packages/docusaurus-plugin-sitemap/package.json index 87489bcee159..6f1717eed921 100644 --- a/packages/docusaurus-plugin-sitemap/package.json +++ b/packages/docusaurus-plugin-sitemap/package.json @@ -28,9 +28,6 @@ "sitemap": "^7.1.1", "tslib": "^2.4.0" }, - "devDependencies": { - "@docusaurus/types": "2.0.0-beta.21" - }, "peerDependencies": { "react": "^16.8.4 || ^17.0.0", "react-dom": "^16.8.4 || ^17.0.0" diff --git a/packages/docusaurus-plugin-sitemap/src/__tests__/createSitemap.test.ts b/packages/docusaurus-plugin-sitemap/src/__tests__/createSitemap.test.ts index 9d42f781baaa..8a4fa2ac553d 100644 --- a/packages/docusaurus-plugin-sitemap/src/__tests__/createSitemap.test.ts +++ b/packages/docusaurus-plugin-sitemap/src/__tests__/createSitemap.test.ts @@ -158,7 +158,10 @@ describe('createSitemap', () => { meta: { // @ts-expect-error: bad lib def toComponent: () => [ - React.createElement('meta', {name: 'robots', content: 'noindex'}), + React.createElement('meta', { + name: 'robots', + content: 'NoFolloW, NoiNDeX', + }), ], }, }, diff --git a/packages/docusaurus-plugin-sitemap/src/createSitemap.ts b/packages/docusaurus-plugin-sitemap/src/createSitemap.ts index 536f2ecfc6bd..2c9166739733 100644 --- a/packages/docusaurus-plugin-sitemap/src/createSitemap.ts +++ b/packages/docusaurus-plugin-sitemap/src/createSitemap.ts @@ -13,6 +13,40 @@ import type {DocusaurusConfig} from '@docusaurus/types'; import type {HelmetServerState} from 'react-helmet-async'; import type {PluginOptions} from './options'; +function isNoIndexMetaRoute({ + head, + route, +}: { + head: {[location: string]: HelmetServerState}; + route: string; +}) { + const isNoIndexMetaTag = ({ + name, + content, + }: { + name?: string; + content?: string; + }): boolean => { + if (!name || !content) { + return false; + } + return ( + // meta name is not case-sensitive + name.toLowerCase() === 'robots' && + // Robots directives are not case-sensitive + content.toLowerCase().includes('noindex') + ); + }; + + // https://github.com/staylor/react-helmet-async/pull/167 + const meta = head[route]?.meta.toComponent() as unknown as + | ReactElement<{name?: string; content?: string}>[] + | undefined; + return meta?.some((tag) => + isNoIndexMetaTag({name: tag.props.name, content: tag.props.content}), + ); +} + export default async function createSitemap( siteConfig: DocusaurusConfig, routesPaths: string[], @@ -27,18 +61,15 @@ export default async function createSitemap( const ignoreMatcher = createMatcher(ignorePatterns); - const includedRoutes = routesPaths.filter((route) => { - if (route.endsWith('404.html') || ignoreMatcher(route)) { - return false; - } - // https://github.com/staylor/react-helmet-async/pull/167 - const meta = head[route]?.meta.toComponent() as unknown as - | ReactElement<{name?: string; content?: string}>[] - | undefined; - return !meta?.some( - (tag) => tag.props.name === 'robots' && tag.props.content === 'noindex', + function isRouteExcluded(route: string) { + return ( + route.endsWith('404.html') || + ignoreMatcher(route) || + isNoIndexMetaRoute({head, route}) ); - }); + } + + const includedRoutes = routesPaths.filter((route) => !isRouteExcluded(route)); if (includedRoutes.length === 0) { return null; diff --git a/packages/docusaurus-preset-classic/src/index.ts b/packages/docusaurus-preset-classic/src/index.ts index a695121c9d0f..c7fe1c825a3e 100644 --- a/packages/docusaurus-preset-classic/src/index.ts +++ b/packages/docusaurus-preset-classic/src/index.ts @@ -87,7 +87,7 @@ export default function preset( throw new Error( `Unrecognized keys ${Object.keys(rest).join( ', ', - )} found in preset-classic configuration. The allowed keys are debug, docs, blog, pages, sitemap, theme, googleAnalytics, gtag. Check the documentation: https://docusaurus.io/docs/presets#docusauruspreset-classic for more information on how to configure individual plugins.`, + )} found in preset-classic configuration. The allowed keys are debug, docs, blog, pages, sitemap, theme, googleAnalytics, gtag. Check the documentation: https://docusaurus.io/docs/using-plugins#docusauruspreset-classic for more information on how to configure individual plugins.`, ); } diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index c823f6adf246..deb25f68b706 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -47,8 +47,6 @@ "utility-types": "^3.10.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "2.0.0-beta.21", - "@docusaurus/types": "2.0.0-beta.21", "@types/mdx-js__react": "^1.5.5", "@types/nprogress": "^0.2.0", "@types/prismjs": "^1.26.0", diff --git a/packages/docusaurus-theme-classic/src/getSwizzleConfig.ts b/packages/docusaurus-theme-classic/src/getSwizzleConfig.ts index 72356f78e7c7..29f89dbb4903 100644 --- a/packages/docusaurus-theme-classic/src/getSwizzleConfig.ts +++ b/packages/docusaurus-theme-classic/src/getSwizzleConfig.ts @@ -28,6 +28,14 @@ export default function getSwizzleConfig(): SwizzleConfig { description: 'The color mode toggle to switch between light and dark mode.', }, + DocCardList: { + actions: { + eject: 'safe', + wrap: 'safe', + }, + description: + 'The component responsible for rendering a list of sidebar items cards.\nNotable used on the category generated-index pages.', + }, DocSidebar: { actions: { eject: 'unsafe', // Too much technical code in sidebar, not very safe atm diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index e0f864266cf0..3bb92790db91 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -55,6 +55,22 @@ declare module '@theme/AnnouncementBar' { export default function AnnouncementBar(): JSX.Element | null; } +declare module '@theme/AnnouncementBar/Content' { + import type {ComponentProps} from 'react'; + + export interface Props extends ComponentProps<'div'> {} + + export default function AnnouncementBarContent(props: Props): JSX.Element; +} + +declare module '@theme/AnnouncementBar/CloseButton' { + import type {ComponentProps} from 'react'; + + export interface Props extends ComponentProps<'button'> {} + + export default function AnnouncementBarCloseButton(props: Props): JSX.Element; +} + declare module '@theme/BackToTopButton' { export default function BackToTopButton(): JSX.Element; } @@ -320,7 +336,7 @@ declare module '@theme/DocCardList' { import type {PropSidebarItem} from '@docusaurus/plugin-content-docs'; export interface Props { - readonly items: PropSidebarItem[]; + readonly items?: PropSidebarItem[]; readonly className?: string; } diff --git a/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/CloseButton/index.tsx b/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/CloseButton/index.tsx new file mode 100644 index 000000000000..5ae3135bf9f7 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/CloseButton/index.tsx @@ -0,0 +1,31 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import clsx from 'clsx'; +import {translate} from '@docusaurus/Translate'; +import IconClose from '@theme/Icon/Close'; +import type {Props} from '@theme/AnnouncementBar/CloseButton'; +import styles from './styles.module.css'; + +export default function AnnouncementBarCloseButton( + props: Props, +): JSX.Element | null { + return ( + + ); +} diff --git a/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/CloseButton/styles.module.css b/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/CloseButton/styles.module.css new file mode 100644 index 000000000000..46f38c1a3344 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/CloseButton/styles.module.css @@ -0,0 +1,11 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +.closeButton { + padding: 0; + line-height: 0; +} diff --git a/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/Content/index.tsx b/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/Content/index.tsx new file mode 100644 index 000000000000..4feb2bc2b7d7 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/Content/index.tsx @@ -0,0 +1,28 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import clsx from 'clsx'; +import {useThemeConfig} from '@docusaurus/theme-common'; +import type {Props} from '@theme/AnnouncementBar/Content'; +import styles from './styles.module.css'; + +export default function AnnouncementBarContent( + props: Props, +): JSX.Element | null { + const {announcementBar} = useThemeConfig(); + const {content} = announcementBar!; + return ( +
+ ); +} diff --git a/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/Content/styles.module.css b/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/Content/styles.module.css new file mode 100644 index 000000000000..38b818db915f --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/Content/styles.module.css @@ -0,0 +1,17 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +.content { + font-size: 85%; + text-align: center; + padding: 5px 0; +} + +.content a { + color: inherit; + text-decoration: underline; +} diff --git a/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/index.tsx b/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/index.tsx index 1cf1b377bbc2..aaa766c35134 100644 --- a/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/index.tsx @@ -6,49 +6,33 @@ */ import React from 'react'; -import clsx from 'clsx'; import {useThemeConfig} from '@docusaurus/theme-common'; import {useAnnouncementBar} from '@docusaurus/theme-common/internal'; -import {translate} from '@docusaurus/Translate'; -import IconClose from '@theme/Icon/Close'; +import AnnouncementBarCloseButton from '@theme/AnnouncementBar/CloseButton'; +import AnnouncementBarContent from '@theme/AnnouncementBar/Content'; import styles from './styles.module.css'; export default function AnnouncementBar(): JSX.Element | null { - const {isActive, close} = useAnnouncementBar(); const {announcementBar} = useThemeConfig(); - + const {isActive, close} = useAnnouncementBar(); if (!isActive) { return null; } - - const {content, backgroundColor, textColor, isCloseable} = announcementBar!; - + const {backgroundColor, textColor, isCloseable} = announcementBar!; return (
{isCloseable &&
} -
- {isCloseable ? ( - - ) : null} + className={styles.announcementBarClose} + /> + )}
); } diff --git a/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/styles.module.css b/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/styles.module.css index 74969ee6515c..f81f61ea8770 100644 --- a/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/styles.module.css +++ b/packages/docusaurus-theme-classic/src/theme/AnnouncementBar/styles.module.css @@ -15,7 +15,8 @@ height: var(--docusaurus-announcement-bar-height); background-color: var(--ifm-color-white); color: var(--ifm-color-black); - border-bottom: 1px solid var(--ifm-color-emphasis-100); + box-shadow: var(--ifm-global-shadow-lw); + z-index: calc(var(--ifm-z-index-fixed) + 1); /* just above the navbar */ } html[data-announcement-bar-initially-dismissed='true'] .announcementBar { @@ -29,15 +30,10 @@ html[data-announcement-bar-initially-dismissed='true'] .announcementBar { .announcementBarClose { flex: 0 0 30px; align-self: stretch; - padding: 0; - line-height: 0; } .announcementBarContent { flex: 1 1 auto; - font-size: 85%; - text-align: center; - padding: 5px 0; } @media print { @@ -46,11 +42,6 @@ html[data-announcement-bar-initially-dismissed='true'] .announcementBar { } } -.announcementBarContent a { - color: inherit; - text-decoration: underline; -} - @media (min-width: 997px) { :root { --docusaurus-announcement-bar-height: 30px; diff --git a/packages/docusaurus-theme-classic/src/theme/CodeBlock/Line/styles.module.css b/packages/docusaurus-theme-classic/src/theme/CodeBlock/Line/styles.module.css index c769c64f403b..454874ff256d 100644 --- a/packages/docusaurus-theme-classic/src/theme/CodeBlock/Line/styles.module.css +++ b/packages/docusaurus-theme-classic/src/theme/CodeBlock/Line/styles.module.css @@ -35,6 +35,7 @@ the background in custom CSS file due bug https://github.com/facebook/docusaurus left: 0; padding: 0 var(--ifm-pre-padding); background: var(--ifm-pre-background); + overflow-wrap: normal; } .codeLineNumber::before { diff --git a/packages/docusaurus-theme-classic/src/theme/DocCardList/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocCardList/index.tsx index c4ace5f5ee6c..cde4b22a74da 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocCardList/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocCardList/index.tsx @@ -7,25 +7,27 @@ import React from 'react'; import clsx from 'clsx'; -import {findFirstCategoryLink} from '@docusaurus/theme-common/internal'; +import { + useCurrentSidebarCategory, + filterDocCardListItems, +} from '@docusaurus/theme-common'; import DocCard from '@theme/DocCard'; import type {Props} from '@theme/DocCardList'; -import type {PropSidebarItem} from '@docusaurus/plugin-content-docs'; -// Filter categories that don't have a link. -function filterItems(items: PropSidebarItem[]): PropSidebarItem[] { - return items.filter((item) => { - if (item.type === 'category') { - return !!findFirstCategoryLink(item); - } - return true; - }); +function DocCardListForCurrentSidebarCategory({className}: Props) { + const category = useCurrentSidebarCategory(); + return ; } -export default function DocCardList({items, className}: Props): JSX.Element { +export default function DocCardList(props: Props): JSX.Element { + const {items, className} = props; + if (!items) { + return ; + } + const filteredItems = filterDocCardListItems(items); return (
- {filterItems(items).map((item, index) => ( + {filteredItems.map((item, index) => (
diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx index 506fd5c72aa7..61a289c30f3d 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx @@ -7,7 +7,11 @@ import React from 'react'; import clsx from 'clsx'; -import {HtmlClassNameProvider, ThemeClassNames} from '@docusaurus/theme-common'; +import { + HtmlClassNameProvider, + ThemeClassNames, + PageMetadata, +} from '@docusaurus/theme-common'; import { docVersionSearchTag, DocsSidebarProvider, @@ -19,13 +23,8 @@ import NotFound from '@theme/NotFound'; import SearchMetadata from '@theme/SearchMetadata'; import type {Props} from '@theme/DocPage'; -export default function DocPage(props: Props): JSX.Element { +function DocPageMetadata(props: Props): JSX.Element { const {versionMetadata} = props; - const currentDocRouteMetadata = useDocRouteMetadata(props); - if (!currentDocRouteMetadata) { - return ; - } - const {docElement, sidebarName, sidebarItems} = currentDocRouteMetadata; return ( <> + + {versionMetadata.noIndex && ( + + )} + + + ); +} + +export default function DocPage(props: Props): JSX.Element { + const {versionMetadata} = props; + const currentDocRouteMetadata = useDocRouteMetadata(props); + if (!currentDocRouteMetadata) { + return ; + } + const {docElement, sidebarName, sidebarItems} = currentDocRouteMetadata; + return ( + <> + { if ( collapsible && - expandedItem && + expandedItem != null && expandedItem !== index && autoCollapseCategories ) { diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Link/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Link/index.tsx index a61ac7a02793..ffa8b0e89602 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Link/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Link/index.tsx @@ -24,7 +24,7 @@ export default function DocSidebarItemLink({ index, ...props }: Props): JSX.Element { - const {href, label, className} = item; + const {href, label, className, autoAddBaseUrl} = item; const isActive = isActiveSidebarItem(item, activePath); const isInternalLink = isInternalUrl(href); return ( @@ -44,6 +44,7 @@ export default function DocSidebarItemLink({ 'menu__link--active': isActive, }, )} + autoAddBaseUrl={autoAddBaseUrl} aria-current={isActive ? 'page' : undefined} to={href} {...(isInternalLink && { diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx index f91ef9eb9d87..53f887789c3c 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx @@ -34,6 +34,7 @@ export default function LocaleDropdownNavbarItem({ })}`; return { label: localeConfigs[locale]!.label, + lang: localeConfigs[locale]!.htmlLang, to, target: '_self', autoAddBaseUrl: false, diff --git a/packages/docusaurus-theme-classic/src/theme/SkipToContent/index.tsx b/packages/docusaurus-theme-classic/src/theme/SkipToContent/index.tsx index 0efd066e409f..174f813a3ae8 100644 --- a/packages/docusaurus-theme-classic/src/theme/SkipToContent/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/SkipToContent/index.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import Translate from '@docusaurus/Translate'; +import Translate, {translate} from '@docusaurus/Translate'; import {useSkipToContent} from '@docusaurus/theme-common/internal'; import styles from './styles.module.css'; @@ -14,7 +14,10 @@ import styles from './styles.module.css'; export default function SkipToContent(): JSX.Element { const {containerRef, handleSkip} = useSkipToContent(); return ( -
+
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} { ), }).result.current; - it('works', () => { - const category: PropSidebarItemCategory = { - type: 'category', - label: 'Category', + + it('works for sidebar category', () => { + const category: PropSidebarItemCategory = testCategory({ href: '/cat', - collapsible: true, - collapsed: false, - items: [ - {type: 'link', href: '/cat/foo', label: 'Foo'}, - {type: 'link', href: '/cat/bar', label: 'Bar'}, - {type: 'link', href: '/baz', label: 'Baz'}, - ], - }; - const mockUseCurrentSidebarCategory = createUseCurrentSidebarCategoryMock([ - {type: 'link', href: '/cat/fake', label: 'Fake'}, + }); + const sidebar: PropSidebar = [ + testLink(), + testLink(), category, - ]); + testCategory(), + ]; + + const mockUseCurrentSidebarCategory = + createUseCurrentSidebarCategoryMock(sidebar); + expect(mockUseCurrentSidebarCategory('/cat')).toEqual(category); }); + it('works for nested sidebar category', () => { + const category2: PropSidebarItemCategory = testCategory({ + href: '/cat2', + }); + const category1: PropSidebarItemCategory = testCategory({ + href: '/cat1', + items: [testLink(), testLink(), category2, testCategory()], + }); + const sidebar: PropSidebar = [ + testLink(), + testLink(), + category1, + testCategory(), + ]; + + const mockUseCurrentSidebarCategory = + createUseCurrentSidebarCategoryMock(sidebar); + + expect(mockUseCurrentSidebarCategory('/cat2')).toEqual(category2); + }); + + it('works for category link item', () => { + const link = testLink({href: '/my/link/path'}); + const category: PropSidebarItemCategory = testCategory({ + href: '/cat1', + items: [testLink(), testLink(), link, testCategory()], + }); + const sidebar: PropSidebar = [ + testLink(), + testLink(), + category, + testCategory(), + ]; + + const mockUseCurrentSidebarCategory = + createUseCurrentSidebarCategoryMock(sidebar); + + expect(mockUseCurrentSidebarCategory('/my/link/path')).toEqual(category); + }); + + it('works for nested category link item', () => { + const link = testLink({href: '/my/link/path'}); + const category2: PropSidebarItemCategory = testCategory({ + href: '/cat2', + items: [testLink(), testLink(), link, testCategory()], + }); + const category1: PropSidebarItemCategory = testCategory({ + href: '/cat1', + items: [testLink(), testLink(), category2, testCategory()], + }); + const sidebar: PropSidebar = [ + testLink(), + testLink(), + category1, + testCategory(), + ]; + + const mockUseCurrentSidebarCategory = + createUseCurrentSidebarCategoryMock(sidebar); + + expect(mockUseCurrentSidebarCategory('/my/link/path')).toEqual(category2); + }); + it('throws for non-category index page', () => { const category: PropSidebarItemCategory = { type: 'category', diff --git a/packages/docusaurus-theme-common/src/utils/docsUtils.tsx b/packages/docusaurus-theme-common/src/utils/docsUtils.tsx index 7ce3222df3e1..726946be9e6c 100644 --- a/packages/docusaurus-theme-common/src/utils/docsUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/docsUtils.tsx @@ -110,15 +110,18 @@ export function useCurrentSidebarCategory(): PropSidebarItemCategory { if (!sidebar) { throw new Error('Unexpected: cant find current sidebar in context'); } - const category = findSidebarCategory(sidebar.items, (item) => - isSamePath(item.href, pathname), - ); - if (!category) { + const categoryBreadcrumbs = getSidebarBreadcrumbs({ + sidebarItems: sidebar.items, + pathname, + onlyCategories: true, + }); + const deepestCategory = categoryBreadcrumbs.slice(-1)[0]; + if (!deepestCategory) { throw new Error( `${pathname} is not associated with a category. useCurrentSidebarCategory() should only be used on category index pages.`, ); } - return category; + return deepestCategory; } const isActive = (testedPath: string | undefined, activePath: string) => @@ -149,29 +152,43 @@ export function isActiveSidebarItem( return false; } -/** - * Gets the breadcrumbs of the current doc page, based on its sidebar location. - * Returns `null` if there's no sidebar or breadcrumbs are disabled. - */ -export function useSidebarBreadcrumbs(): PropSidebarBreadcrumbsItem[] | null { - const sidebar = useDocsSidebar(); - const {pathname} = useLocation(); - const breadcrumbsOption = useActivePlugin()?.pluginData.breadcrumbs; +function getSidebarBreadcrumbs(param: { + sidebarItems: PropSidebar; + pathname: string; + onlyCategories: true; +}): PropSidebarItemCategory[]; - if (breadcrumbsOption === false || !sidebar) { - return null; - } +function getSidebarBreadcrumbs(param: { + sidebarItems: PropSidebar; + pathname: string; +}): PropSidebarBreadcrumbsItem[]; +/** + * Get the sidebar the breadcrumbs for a given pathname + * Ordered from top to bottom + */ +function getSidebarBreadcrumbs({ + sidebarItems, + pathname, + onlyCategories = false, +}: { + sidebarItems: PropSidebar; + pathname: string; + onlyCategories?: boolean; +}): PropSidebarBreadcrumbsItem[] { const breadcrumbs: PropSidebarBreadcrumbsItem[] = []; - function extract(items: PropSidebar) { + function extract(items: PropSidebarItem[]) { for (const item of items) { if ( (item.type === 'category' && (isSamePath(item.href, pathname) || extract(item.items))) || (item.type === 'link' && isSamePath(item.href, pathname)) ) { - breadcrumbs.push(item); + const filtered = onlyCategories && item.type !== 'category'; + if (!filtered) { + breadcrumbs.unshift(item); + } return true; } } @@ -179,9 +196,23 @@ export function useSidebarBreadcrumbs(): PropSidebarBreadcrumbsItem[] | null { return false; } - extract(sidebar.items); + extract(sidebarItems); + + return breadcrumbs; +} - return breadcrumbs.reverse(); +/** + * Gets the breadcrumbs of the current doc page, based on its sidebar location. + * Returns `null` if there's no sidebar or breadcrumbs are disabled. + */ +export function useSidebarBreadcrumbs(): PropSidebarBreadcrumbsItem[] | null { + const sidebar = useDocsSidebar(); + const {pathname} = useLocation(); + const breadcrumbsOption = useActivePlugin()?.pluginData.breadcrumbs; + if (breadcrumbsOption === false || !sidebar) { + return null; + } + return getSidebarBreadcrumbs({sidebarItems: sidebar.items, pathname}); } /** @@ -332,3 +363,18 @@ export function useDocRouteMetadata({ sidebarItems, }; } + +/** + * Filter categories that don't have a link. + * @param items + */ +export function filterDocCardListItems( + items: PropSidebarItem[], +): PropSidebarItem[] { + return items.filter((item) => { + if (item.type === 'category') { + return !!findFirstCategoryLink(item); + } + return true; + }); +} diff --git a/packages/docusaurus-theme-translations/locales/uk/plugin-ideal-image.json b/packages/docusaurus-theme-translations/locales/uk/plugin-ideal-image.json new file mode 100644 index 000000000000..e4010fdc0ca7 --- /dev/null +++ b/packages/docusaurus-theme-translations/locales/uk/plugin-ideal-image.json @@ -0,0 +1,7 @@ +{ + "theme.IdealImageMessage.404error": "404. Зображення не знайдено", + "theme.IdealImageMessage.error": "Помилка. Натисніть, щоб перезавантажити", + "theme.IdealImageMessage.load": "Натисніть, щоб завантажити {sizeMessage}", + "theme.IdealImageMessage.loading": "Завантаження...", + "theme.IdealImageMessage.offline": "Ваш браузер перебуває в автономному режимі. Зображення не завантажено" +} diff --git a/packages/docusaurus-theme-translations/locales/uk/plugin-pwa.json b/packages/docusaurus-theme-translations/locales/uk/plugin-pwa.json new file mode 100644 index 000000000000..cc51eaf5f9b5 --- /dev/null +++ b/packages/docusaurus-theme-translations/locales/uk/plugin-pwa.json @@ -0,0 +1,5 @@ +{ + "theme.PwaReloadPopup.closeButtonAriaLabel": "Закрити", + "theme.PwaReloadPopup.info": "Доступна нова версія", + "theme.PwaReloadPopup.refreshButtonText": "Оновити" +} diff --git a/packages/docusaurus-theme-translations/locales/uk/theme-common.json b/packages/docusaurus-theme-translations/locales/uk/theme-common.json new file mode 100644 index 000000000000..67663024c8d4 --- /dev/null +++ b/packages/docusaurus-theme-translations/locales/uk/theme-common.json @@ -0,0 +1,66 @@ +{ + "theme.AnnouncementBar.closeButtonAriaLabel": "Закрити", + "theme.BackToTopButton.buttonAriaLabel": "Прокрутити до початку", + "theme.CodeBlock.copied": "Скопійовано", + "theme.CodeBlock.copy": "Копіювати", + "theme.CodeBlock.copyButtonAriaLabel": "Копіювати в буфер обміну", + "theme.CodeBlock.wordWrapToggle": "Перемикання обведення слів", + "theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel": "Згорнути/розгорнути категорію '{label}'", + "theme.ErrorPageContent.title": "На сторінці стався збій.", + "theme.ErrorPageContent.tryAgain": "Спробуйте ще раз", + "theme.NotFound.p1": "На жаль, ми не змогли знайти сторінку, яку ви запитували.", + "theme.NotFound.p2": "Будь ласка, зверніться до власника сайту, з якого ви перейшли на це посилання, щоб повідомити, що посилання не працює.", + "theme.NotFound.title": "Сторінку не знайдено", + "theme.TOCCollapsible.toggleButtonLabel": "Зміст цієї сторінки", + "theme.admonition.caution": "обережно", + "theme.admonition.danger": "небезпека", + "theme.admonition.info": "інформація", + "theme.admonition.note": "примітка", + "theme.admonition.tip": "порада", + "theme.blog.archive.description": "Архів", + "theme.blog.archive.title": "Архів", + "theme.blog.paginator.navAriaLabel": "Навігація по сторінці списку блогів", + "theme.blog.paginator.newerEntries": "Наступні записи", + "theme.blog.paginator.olderEntries": "Попередні записи", + "theme.blog.post.paginator.navAriaLabel": "Навігація по сторінці посту блогу", + "theme.blog.post.paginator.newerPost": "Наступний пост", + "theme.blog.post.paginator.olderPost": "Попередній пост", + "theme.blog.post.plurals": "{count} запис|{count} записи|{count} записів", + "theme.blog.post.readMore": "Читати далі", + "theme.blog.post.readMoreLabel": "Докладніше про {title}", + "theme.blog.post.readingTime.plurals": "{readingTime} хв. читання", + "theme.blog.sidebar.navAriaLabel": "Навігація за останніми постами у блозі", + "theme.blog.tagTitle": "{nPosts} з тегом \"{tagName}\"", + "theme.colorToggle.ariaLabel": "Перемикання між темним та світлим режимом (зараз використовується {mode})", + "theme.colorToggle.ariaLabel.mode.dark": "Темний режим", + "theme.colorToggle.ariaLabel.mode.light": "Світлий режим", + "theme.common.editThisPage": "Відредагувати цю сторінку", + "theme.common.headingLinkTitle": "Пряме посилання на цей заголовок", + "theme.common.skipToMainContent": "Перейти до основного вмісту", + "theme.docs.DocCard.categoryDescription": "{count} елемент|{count} елементи|{count} елементів", + "theme.docs.breadcrumbs.home": "Головна сторінка", + "theme.docs.breadcrumbs.navAriaLabel": "Навігаційний ланцюжок поточної сторінки", + "theme.docs.paginator.navAriaLabel": "Навігація по сторінці документації", + "theme.docs.paginator.next": "Наступна сторінка", + "theme.docs.paginator.previous": "Попередня сторінка", + "theme.docs.sidebar.collapseButtonAriaLabel": "Згорнути сайдбар", + "theme.docs.sidebar.collapseButtonTitle": "Згорнути сайдбар", + "theme.docs.sidebar.expandButtonAriaLabel": "Розгорнути сайдбар", + "theme.docs.sidebar.expandButtonTitle": "Розгорнути сайдбар", + "theme.docs.tagDocListPageTitle": "{nDocsTagged} з тегом \"{tagName}\"", + "theme.docs.tagDocListPageTitle.nDocsTagged": "Одна сторінка|{count} сторінки|{count} сторінок", + "theme.docs.versionBadge.label": "Версія: {versionLabel}", + "theme.docs.versions.latestVersionLinkLabel": "остання версія", + "theme.docs.versions.latestVersionSuggestionLabel": "Актуальна документація знаходиться на сторінці {latestVersionLink} ({versionLabel}).", + "theme.docs.versions.unmaintainedVersionLabel": "Це документація {siteTitle} для версії {versionLabel}, яка вже не підтримується.", + "theme.docs.versions.unreleasedVersionLabel": "Це документація для майбутньої версії {siteTitle} {versionLabel}.", + "theme.lastUpdated.atDate": " {date}", + "theme.lastUpdated.byUser": " від {user}", + "theme.lastUpdated.lastUpdatedAtBy": "Останнє оновлення{atDate}{byUser}", + "theme.navbar.mobileLanguageDropdown.label": "Мови", + "theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": "← Перейти до головного меню", + "theme.navbar.mobileVersionsDropdown.label": "Версії", + "theme.tags.tagsListLabel": "Теги:", + "theme.tags.tagsPageLink": "Переглянути всі теги", + "theme.tags.tagsPageTitle": "Теги" +} diff --git a/packages/docusaurus-theme-translations/locales/uk/theme-live-codeblock.json b/packages/docusaurus-theme-translations/locales/uk/theme-live-codeblock.json new file mode 100644 index 000000000000..8eafd4d4274b --- /dev/null +++ b/packages/docusaurus-theme-translations/locales/uk/theme-live-codeblock.json @@ -0,0 +1,4 @@ +{ + "theme.Playground.liveEditor": "Інтерактивний редактор", + "theme.Playground.result": "Результат" +} diff --git a/packages/docusaurus-theme-translations/locales/uk/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/uk/theme-search-algolia.json new file mode 100644 index 000000000000..263ee92511e0 --- /dev/null +++ b/packages/docusaurus-theme-translations/locales/uk/theme-search-algolia.json @@ -0,0 +1,35 @@ +{ + "theme.SearchBar.label": "Пошук", + "theme.SearchBar.seeAll": "Переглянути всі результати ({count})", + "theme.SearchModal.errorScreen.helpText": "Перевірте підключення до мережі.", + "theme.SearchModal.errorScreen.titleText": "Не вдалося отримати результати", + "theme.SearchModal.footer.closeKeyAriaLabel": "Клавіша Escape", + "theme.SearchModal.footer.closeText": "закрити", + "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Стрілка вниз", + "theme.SearchModal.footer.navigateText": "до навігації", + "theme.SearchModal.footer.navigateUpKeyAriaLabel": "Стрілка вгору", + "theme.SearchModal.footer.searchByText": "Пошук за допомогою", + "theme.SearchModal.footer.selectKeyAriaLabel": "Клавіша Enter", + "theme.SearchModal.footer.selectText": "обрати", + "theme.SearchModal.noResultsScreen.noResultsText": "Немає результатів для", + "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Дайте нам знати.", + "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Чи вважаєте ви, що цей запит має повернути результати?", + "theme.SearchModal.noResultsScreen.suggestedQueryText": "Спробуйте пошукати", + "theme.SearchModal.placeholder": "Пошук документів", + "theme.SearchModal.searchBox.cancelButtonText": "Скасувати", + "theme.SearchModal.searchBox.resetButtonTitle": "Очистити запит", + "theme.SearchModal.startScreen.favoriteSearchesTitle": "Обране", + "theme.SearchModal.startScreen.noRecentSearchesText": "Немає останніх пошуків", + "theme.SearchModal.startScreen.recentSearchesTitle": "Останні", + "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Видалити цей пошук з обраного", + "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Видалити цей пошук з історії", + "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Зберегти цей пошук", + "theme.SearchPage.algoliaLabel": "Пошук за допомогою Algolia", + "theme.SearchPage.documentsFound.plurals": "{count} документ|{count} документи|{count} документів", + "theme.SearchPage.emptyResultsTitle": "Пошук по сайту", + "theme.SearchPage.existingResultsTitle": "Результати пошуку за запитом \"{query}\"", + "theme.SearchPage.fetchingNewResults": "Завантаження нових результатів пошуку...", + "theme.SearchPage.inputLabel": "Пошук", + "theme.SearchPage.inputPlaceholder": "Введіть фразу для пошуку", + "theme.SearchPage.noResultsText": "За запитом нічого не знайдено" +} diff --git a/packages/docusaurus-theme-translations/locales/vi/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/vi/theme-search-algolia.json index 6b445316b938..72d0efb2d229 100644 --- a/packages/docusaurus-theme-translations/locales/vi/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/vi/theme-search-algolia.json @@ -1,29 +1,29 @@ { "theme.SearchBar.label": "Tìm kiếm", "theme.SearchBar.seeAll": "Xem tất cả {count} kết quả", - "theme.SearchModal.errorScreen.helpText": "You might want to check your network connection.", - "theme.SearchModal.errorScreen.titleText": "Unable to fetch results", - "theme.SearchModal.footer.closeKeyAriaLabel": "Escape key", - "theme.SearchModal.footer.closeText": "to close", - "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Arrow down", - "theme.SearchModal.footer.navigateText": "to navigate", - "theme.SearchModal.footer.navigateUpKeyAriaLabel": "Arrow up", - "theme.SearchModal.footer.searchByText": "Search by", - "theme.SearchModal.footer.selectKeyAriaLabel": "Enter key", - "theme.SearchModal.footer.selectText": "to select", - "theme.SearchModal.noResultsScreen.noResultsText": "No results for", - "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Let us know.", - "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Believe this query should return results?", - "theme.SearchModal.noResultsScreen.suggestedQueryText": "Try searching for", - "theme.SearchModal.placeholder": "Search docs", - "theme.SearchModal.searchBox.cancelButtonText": "Cancel", - "theme.SearchModal.searchBox.resetButtonTitle": "Clear the query", - "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorite", - "theme.SearchModal.startScreen.noRecentSearchesText": "No recent searches", - "theme.SearchModal.startScreen.recentSearchesTitle": "Recent", - "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", - "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", - "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Save this search", + "theme.SearchModal.errorScreen.helpText": "Bạn nên kiểm tra lại kết nối mạng của mình.", + "theme.SearchModal.errorScreen.titleText": "Không thể tìm nạp dữ liệu", + "theme.SearchModal.footer.closeKeyAriaLabel": "Phím thoát", + "theme.SearchModal.footer.closeText": "để đóng", + "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Mũi tên xuống", + "theme.SearchModal.footer.navigateText": "để điều hướng", + "theme.SearchModal.footer.navigateUpKeyAriaLabel": "Mũi tên lên", + "theme.SearchModal.footer.searchByText": "Tìm kiếm theo", + "theme.SearchModal.footer.selectKeyAriaLabel": "Nhập khóa", + "theme.SearchModal.footer.selectText": "để chọn", + "theme.SearchModal.noResultsScreen.noResultsText": "Không có kết quả dành cho", + "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Hãy để chúng tôi biết.", + "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Tin rằng truy vấn này sẽ trả về kết quả?", + "theme.SearchModal.noResultsScreen.suggestedQueryText": "Thử tìm kiếm", + "theme.SearchModal.placeholder": "Tìm kiếm tài liệu", + "theme.SearchModal.searchBox.cancelButtonText": "Hủy bỏ", + "theme.SearchModal.searchBox.resetButtonTitle": "Xóa truy vấn", + "theme.SearchModal.startScreen.favoriteSearchesTitle": "Yêu thích", + "theme.SearchModal.startScreen.noRecentSearchesText": "Không có tìm kiếm nào gần đây", + "theme.SearchModal.startScreen.recentSearchesTitle": "Gần đây", + "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Xóa tìm kiếm này khỏi danh sách yêu thích", + "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Xóa tìm kiếm này khỏi lịch sử", + "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Lưu tìm kiếm này", "theme.SearchPage.algoliaLabel": "Tìm kiếm với Algolia", "theme.SearchPage.documentsFound.plurals": "Tìm thấy một kết quả|Tìm thấy {count} kết quả", "theme.SearchPage.emptyResultsTitle": "Tìm kiếm", diff --git a/packages/docusaurus-types/src/i18n.d.ts b/packages/docusaurus-types/src/i18n.d.ts index 50b1bc0d9036..f8ddf15b837f 100644 --- a/packages/docusaurus-types/src/i18n.d.ts +++ b/packages/docusaurus-types/src/i18n.d.ts @@ -11,8 +11,9 @@ export type I18nLocaleConfig = { /** The label displayed for this locale in the locales dropdown. */ label: string; /** - * BCP 47 language tag to use in `` and in - * `` + * BCP 47 language tag to use in: + * - `` (or any other DOM tag name) + * - `` */ htmlLang: string; /** Used to select the locale's CSS and html meta attribute. */ diff --git a/packages/docusaurus-utils/src/webpackUtils.ts b/packages/docusaurus-utils/src/webpackUtils.ts index fa579e06b470..c73193da1cd4 100644 --- a/packages/docusaurus-utils/src/webpackUtils.ts +++ b/packages/docusaurus-utils/src/webpackUtils.ts @@ -86,7 +86,7 @@ export function getFileLoaderUtils(): FileLoaderUtils { */ images: () => ({ use: [loaders.url({folder: 'images'})], - test: /\.(?:ico|jpe?g|png|gif|webp)(?:\?.*)?$/i, + test: /\.(?:ico|jpe?g|png|gif|webp|avif)(?:\?.*)?$/i, }), fonts: () => ({ @@ -100,7 +100,7 @@ export function getFileLoaderUtils(): FileLoaderUtils { */ media: () => ({ use: [loaders.url({folder: 'medias'})], - test: /\.(?:mp4|webm|ogv|wav|mp3|m4a|aac|oga|flac)$/i, + test: /\.(?:mp4|avi|mov|mkv|mpg|mpeg|vob|wmv|m4v|webm|ogv|wav|mp3|m4a|aac|oga|flac)$/i, }), svg: () => ({ diff --git a/packages/docusaurus/src/client/SiteMetadataDefaults.tsx b/packages/docusaurus/src/client/SiteMetadataDefaults.tsx index e3ba631fbbe5..1f49959d3536 100644 --- a/packages/docusaurus/src/client/SiteMetadataDefaults.tsx +++ b/packages/docusaurus/src/client/SiteMetadataDefaults.tsx @@ -12,7 +12,7 @@ import useBaseUrl from '@docusaurus/useBaseUrl'; export default function SiteMetadataDefaults(): JSX.Element { const { - siteConfig: {favicon, title}, + siteConfig: {favicon, title, noIndex}, i18n: {currentLocale, localeConfigs}, } = useDocusaurusContext(); const faviconUrl = useBaseUrl(favicon); @@ -20,9 +20,17 @@ export default function SiteMetadataDefaults(): JSX.Element { return ( + {/* + charSet + generator are handled in the html templates + See https://github.com/facebook/docusaurus/pull/7952 + + + */} {title} + + {noIndex && } {favicon && } ); diff --git a/packages/docusaurus/src/client/preload.ts b/packages/docusaurus/src/client/preload.ts index fec374ad4b6b..1411581742fc 100644 --- a/packages/docusaurus/src/client/preload.ts +++ b/packages/docusaurus/src/client/preload.ts @@ -17,7 +17,9 @@ import {matchRoutes} from 'react-router-config'; * @returns Promise object represents whether pathname has been preloaded */ export default function preload(pathname: string): Promise { - const matches = matchRoutes(routes, pathname); + const matches = Array.from(new Set([pathname, decodeURI(pathname)])) + .map((p) => matchRoutes(routes, p)) + .flat(); return Promise.all(matches.map((match) => match.route.component.preload?.())); } diff --git a/packages/docusaurus/src/commands/writeTranslations.ts b/packages/docusaurus/src/commands/writeTranslations.ts index 6bda39cd5776..6247f04902dc 100644 --- a/packages/docusaurus/src/commands/writeTranslations.ts +++ b/packages/docusaurus/src/commands/writeTranslations.ts @@ -29,6 +29,14 @@ export type WriteTranslationsCLIOptions = Pick< > & WriteTranslationsOptions; +function resolveThemeCommonLibDir(): string | undefined { + try { + return path.dirname(require.resolve('@docusaurus/theme-common')); + } catch { + return undefined; + } +} + /** * This is a hack, so that @docusaurus/theme-common translations are extracted! * A theme doesn't have a way to express that one of its dependency (like @@ -37,14 +45,11 @@ export type WriteTranslationsCLIOptions = Pick< * We just make an exception and assume that user is using an official theme */ async function getExtraSourceCodeFilePaths(): Promise { - try { - const themeCommonSourceDir = path.dirname( - require.resolve('@docusaurus/theme-common/lib'), - ); - return globSourceCodeFilePaths([themeCommonSourceDir]); - } catch { + const themeCommonLibDir = resolveThemeCommonLibDir(); + if (!themeCommonLibDir) { return []; // User may not use a Docusaurus official theme? Quite unlikely... } + return globSourceCodeFilePaths([themeCommonLibDir]); } async function writePluginTranslationFiles({ @@ -108,6 +113,7 @@ Available locales are: ${context.i18n.locales.join(',')}.`, babelOptions, await getExtraSourceCodeFilePaths(), ); + const defaultCodeMessages = await getPluginsDefaultCodeTranslationMessages( plugins, ); diff --git a/packages/docusaurus/src/webpack/templates/index.html.template.ejs b/packages/docusaurus/src/webpack/templates/index.html.template.ejs index 233efa98a3f4..ee6270b0e4e6 100644 --- a/packages/docusaurus/src/webpack/templates/index.html.template.ejs +++ b/packages/docusaurus/src/webpack/templates/index.html.template.ejs @@ -2,7 +2,6 @@ - <%= htmlWebpackPlugin.options.title %> <%= htmlWebpackPlugin.options.headTags %> diff --git a/packages/docusaurus/src/webpack/templates/ssr.html.template.ts b/packages/docusaurus/src/webpack/templates/ssr.html.template.ts index fbbe7fad8a72..ee1f8f1b4716 100644 --- a/packages/docusaurus/src/webpack/templates/ssr.html.template.ts +++ b/packages/docusaurus/src/webpack/templates/ssr.html.template.ts @@ -10,15 +10,11 @@ export default ` > - - <% if (it.noIndex) { %> - - <% } %> - <%~ it.headTags %> <% it.metaAttributes.forEach((metaAttribute) => { %> <%~ metaAttribute %> <% }); %> + <%~ it.headTags %> <% it.stylesheets.forEach((stylesheet) => { %> <% }); %> diff --git a/website/_dogfooding/_pages tests/code-block-tests.mdx b/website/_dogfooding/_pages tests/code-block-tests.mdx index 44db91d49094..2c955e110cb4 100644 --- a/website/_dogfooding/_pages tests/code-block-tests.mdx +++ b/website/_dogfooding/_pages tests/code-block-tests.mdx @@ -249,3 +249,21 @@ echo "short_initially_hidden_string" [// spell-checker:enable]: # + +```jsx showLineNumbers +import React from 'react'; +import Layout from '@theme/Layout'; + +export default function MyReactPage() { + return ( + +

My React page

+

+ This is a React page. Let's make this sentence bit long. Some more words + to make sure... Some more words to make sure... Some more words to make + sure... +

+
+ ); +} +``` diff --git a/website/_dogfooding/_pages tests/head-metadata.md b/website/_dogfooding/_pages tests/head-metadata.md new file mode 100644 index 000000000000..8e16df7033d8 --- /dev/null +++ b/website/_dogfooding/_pages tests/head-metadata.md @@ -0,0 +1,17 @@ +## Head Metadata tests + +This page declares the following custom head metadata: + +```html + + + + + +``` + + + + + + diff --git a/website/_dogfooding/_pages tests/index.md b/website/_dogfooding/_pages tests/index.md index d54f03fcd3f6..e8bb7fdc7df4 100644 --- a/website/_dogfooding/_pages tests/index.md +++ b/website/_dogfooding/_pages tests/index.md @@ -29,3 +29,4 @@ import Readme from "../README.md" - [TOC tests](/tests/pages/page-toc-tests) - [Tabs tests](/tests/pages/tabs-tests) - [z-index tests](/tests/pages/z-index-tests) +- [Head metadata tests](/tests/pages/head-metadata) diff --git a/website/_dogfooding/docs-tests-sidebars.js b/website/_dogfooding/docs-tests-sidebars.js index 0c2783feeda3..d458e7eb517d 100644 --- a/website/_dogfooding/docs-tests-sidebars.js +++ b/website/_dogfooding/docs-tests-sidebars.js @@ -71,10 +71,27 @@ const sidebars = { ], }, { - type: 'link', - label: 'External link', - href: 'https://github.com/facebook/docusaurus', + type: 'category', + label: 'Link tests', className: 'red', + items: [ + { + type: 'link', + label: 'External link absolute', + href: 'https://github.com/facebook/docusaurus', + }, + { + type: 'link', + label: 'pathname:/// link', + href: 'pathname:///some/local/path', + }, + { + type: 'link', + label: 'pathname:/// link (no baseUrl)', + href: 'pathname:///some/local/path', + autoAddBaseUrl: false, + }, + ], }, { type: 'category', diff --git a/website/_dogfooding/dogfooding.config.js b/website/_dogfooding/dogfooding.config.js index f8a4e7007f0e..e961bca132a5 100644 --- a/website/_dogfooding/dogfooding.config.js +++ b/website/_dogfooding/dogfooding.config.js @@ -26,6 +26,11 @@ const dogfoodingPluginInstances = [ id: 'docs-tests', routeBasePath: '/tests/docs', 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 path: '_dogfooding/_docs tests', diff --git a/website/docs/advanced/index.md b/website/docs/advanced/index.md index afe7f1a57050..47fc3f8bc902 100644 --- a/website/docs/advanced/index.md +++ b/website/docs/advanced/index.md @@ -4,9 +4,8 @@ This section is not going to be very structured, but we will cover the following ```mdx-code-block import DocCardList from '@theme/DocCardList'; -import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; - + ``` We will assume that you have finished the guides, and know the basics like how to configure plugins, how to write React components, etc. These sections will have plugin authors and code contributors in mind, so we may occasionally refer to [plugin APIs](../api/plugin-methods/README.md) or other architecture details. Don't panic if you don't understand everything😉 diff --git a/website/docs/api/docusaurus.config.js.md b/website/docs/api/docusaurus.config.js.md index 6aea4f53b140..254bdc0a2d38 100644 --- a/website/docs/api/docusaurus.config.js.md +++ b/website/docs/api/docusaurus.config.js.md @@ -157,7 +157,7 @@ module.exports = { - `localeConfigs`: Individual options for each locale. - `label`: The label displayed for this locale in the locales dropdown. - `direction`: `ltr` (default) or `rtl` (for [right-to-left languages](https://developer.mozilla.org/en-US/docs/Glossary/rtl) like Farsi, Arabic, Hebrew, etc.). Used to select the locale's CSS and HTML meta attribute. - - `htmlLang`: BCP 47 language tag to use in `` and in `` + - `htmlLang`: BCP 47 language tag to use in `` (or any other DOM tag name) and in `` - `calendar`: the [calendar](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar) used to calculate the date era. Note that it doesn't control the actual string displayed: `MM/DD/YYYY` and `DD/MM/YYYY` are both `gregory`. To choose the format (`DD/MM/YYYY` or `MM/DD/YYYY`), set your locale name to `en-GB` or `en-US` (`en` means `en-US`). - `path`: Root folder that all plugin localization folders of this locale are relative to. Will be resolved against `i18n.path`. Defaults to the locale's name. Note: this has no effect on the locale's `baseUrl`—customization of base URL is a work-in-progress. @@ -509,15 +509,11 @@ module.exports = { > - - <% if (it.noIndex) { %> - - <% } %> - <%~ it.headTags %> <% it.metaAttributes.forEach((metaAttribute) => { %> <%~ metaAttribute %> <% }); %> + <%~ it.headTags %> <% it.stylesheets.forEach((stylesheet) => { %> <% }); %> diff --git a/website/docs/api/plugins/plugin-content-docs.md b/website/docs/api/plugins/plugin-content-docs.md index d645f726738f..6e60b02e9176 100644 --- a/website/docs/api/plugins/plugin-content-docs.md +++ b/website/docs/api/plugins/plugin-content-docs.md @@ -142,23 +142,25 @@ type CategoryIndexMatcher = (param: { #### `VersionsConfig` {#VersionsConfig} ```ts -type VersionsConfig = { - [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' | 'unreleased' | 'unmaintained'; - /** Show a badge with the version label at the top of each doc. */ - badge?: boolean; - /** Add a custom class name to the element of each doc */ - className?: string; - }; +type VersionConfig = { + /** + * 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' | 'unreleased' | 'unmaintained'; + /** 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 element of each doc */ + className?: string; }; + +type VersionsConfig = {[versionName: string]: VersionConfig}; ``` ### Example configuration {#ex-config} diff --git a/website/docs/guides/docs/sidebar/index.md b/website/docs/guides/docs/sidebar/index.md index 06eb5a91b3b9..8e8817b54375 100644 --- a/website/docs/guides/docs/sidebar/index.md +++ b/website/docs/guides/docs/sidebar/index.md @@ -35,9 +35,8 @@ This section serves as an overview of miscellaneous features of the doc sidebar. ```mdx-code-block import DocCardList from '@theme/DocCardList'; -import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; - + ``` ## Default sidebar {#default-sidebar} diff --git a/website/docs/guides/docs/sidebar/items.md b/website/docs/guides/docs/sidebar/items.md index fa7af72ca9be..1e5d8ffdf9ab 100644 --- a/website/docs/guides/docs/sidebar/items.md +++ b/website/docs/guides/docs/sidebar/items.md @@ -8,6 +8,7 @@ slug: /sidebar/items ```mdx-code-block import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +import BrowserWindow from '@site/src/components/BrowserWindow'; ``` We have introduced three types of item types in the example in the previous section: `doc`, `category`, and `link`, whose usages are fairly intuitive. We will formally introduce their APIs. There's also a fourth type: `autogenerated`, which we will explain in detail later. @@ -291,18 +292,23 @@ See it in action on the [i18n introduction page](../../../i18n/i18n-introduction #### Embedding generated index in doc page {#embedding-generated-index-in-doc-page} -You can embed the generated cards list in a normal doc page as well, as long as the doc is used as a category index page. To do so, you need to use the `DocCardList` component, paired with the `useCurrentSidebarCategory` hook. +You can embed the generated cards list in a normal doc page as well with the `DocCardList` component. It will display all the sidebar items of the parent category of the current document. -```jsx title="a-category-index-page.md" +```md title="docs/sidebar/index.md" import DocCardList from '@theme/DocCardList'; -import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; -In this section, we will introduce the following concepts: - - + ``` -See this in action on the [sidebar guides page](index.md). +```mdx-code-block + + +import DocCardList from '@theme/DocCardList'; + + + + +``` ### Collapsible categories {#collapsible-categories} diff --git a/website/docs/introduction.md b/website/docs/introduction.md index 894f88e8269a..c8a0768c46f8 100644 --- a/website/docs/introduction.md +++ b/website/docs/introduction.md @@ -65,11 +65,9 @@ import LiteYouTubeEmbed from 'react-lite-youtube-embed';
``` -## Disclaimer {#disclaimer} +## Migrating from v1 {#migrating-from-v1} -Docusaurus v2 is **beta** but already quite stable and widely used. - -We highly encourage you to **use Docusaurus v2 over Docusaurus v1**, as Docusaurus v1 will be deprecated soon. +Docusaurus v2 has been a total rewrite from Docusaurus v1, taking advantage of a completely modernized toolchain. After [v2's official release](https://docusaurus.io/blog/2022/08/01/announcing-docusaurus-2.0), we highly encourage you to **use Docusaurus v2 over Docusaurus v1**, as Docusaurus v1 has been deprecated. A [lot of users](/showcase) are already using Docusaurus v2 ([trends](https://www.npmtrends.com/docusaurus-vs-@docusaurus/core)). @@ -83,7 +81,9 @@ A [lot of users](/showcase) are already using Docusaurus v2 ([trends](https://ww **Use [Docusaurus v1](https://v1.docusaurus.io/) if:** - :x: You don't want a single-page application (SPA) -- :x: You need support for IE11 +- :x: You need support for IE11 (...do you? IE [has already reached end-of-life](https://docs.microsoft.com/en-us/lifecycle/products/internet-explorer-11) and is no longer officially supported) + +For existing v1 users that are seeking to upgrade to v2, you can follow our [migration guide](./migration/migration-overview.md). ## Features {#features} diff --git a/website/docs/seo.md b/website/docs/seo.md index 578bb7761c30..f252889cdf54 100644 --- a/website/docs/seo.md +++ b/website/docs/seo.md @@ -124,7 +124,11 @@ Read more about the robots file in [the Google documentation](https://developers :::caution -**Important**: the `robots.txt` file does **not** prevent HTML pages from being indexed. Use `` as [page metadata](#single-page-metadata) to prevent it from appearing in search results entirely. +**Important**: the `robots.txt` file does **not** prevent HTML pages from being indexed. + +To prevent your whole Docusaurus site from being indexed, use the [`noIndex`](./api/docusaurus.config.js.md#noIndex) site config. Some [hosting providers](./deployment.mdx) may also let you configure a `X-Robots-Tag: noindex` HTTP header (GitHub Pages does not support this). + +To prevent a single page from being indexed, use `` as [page metadata](#single-page-metadata). Read more about the [robots meta tag](https://developers.google.com/search/docs/advanced/robots/robots_meta_tag). ::: @@ -132,6 +136,20 @@ Read more about the robots file in [the Google documentation](https://developers Docusaurus provides the [`@docusaurus/plugin-sitemap`](./api/plugins/plugin-sitemap.md) plugin, which is shipped with `preset-classic` by default. It autogenerates a `sitemap.xml` file which will be available at `https://example.com/[baseUrl]/sitemap.xml` after the production build. This sitemap metadata helps search engine crawlers crawl your site more accurately. +:::tip + +The sitemap plugin automatically filters pages containing a `noindex` [robots meta directive](https://developers.google.com/search/docs/advanced/robots/robots_meta_tag). + +For example, [`/examples/noIndex`](/examples/noIndex) is not included in the [Docusaurus sitemap.xml file](pathname:///sitemap.xml) because it contains the following [page metadata](#single-page-metadata): + +```html + + + +``` + +::: + ## Human readable links {#human-readable-links} Docusaurus uses your file names as links, but you can always change that using slugs, see this [tutorial](./guides/docs/docs-introduction.md#document-id) for more details. diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 5f9f7da058e6..2472d5e0fe6e 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -356,7 +356,8 @@ const config = { } : undefined, sitemap: { - ignorePatterns: ['/tests/**'], + // Note: /tests/docs already has noIndex: true + ignorePatterns: ['/tests/{blog,pages}/**'], }, }), ], diff --git a/website/src/pages/examples/noIndex.md b/website/src/pages/examples/noIndex.md new file mode 100644 index 000000000000..b4df30e2f883 --- /dev/null +++ b/website/src/pages/examples/noIndex.md @@ -0,0 +1,25 @@ +# No Index Page example + + + + + +This page will not be indexed by search engines because it contains the page following [page metadata](/docs/seo#single-page-metadata) markup: + +```html + + + +``` + +:::tip + +The sitemap plugin filters pages containing a `noindex` content value. This page doesn't appear in Docusaurus [sitemap.xml](pathname:///sitemap.xml) file. + +::: + +:::note + +Robots directives are [case-insensitive](https://developers.google.com/search/docs/advanced/robots/robots_meta_tag#directives). + +::: diff --git a/website/versioned_docs/version-2.0.0-beta.22/introduction.md b/website/versioned_docs/version-2.0.0-beta.22/introduction.md index 894f88e8269a..c8a0768c46f8 100644 --- a/website/versioned_docs/version-2.0.0-beta.22/introduction.md +++ b/website/versioned_docs/version-2.0.0-beta.22/introduction.md @@ -65,11 +65,9 @@ import LiteYouTubeEmbed from 'react-lite-youtube-embed';
``` -## Disclaimer {#disclaimer} +## Migrating from v1 {#migrating-from-v1} -Docusaurus v2 is **beta** but already quite stable and widely used. - -We highly encourage you to **use Docusaurus v2 over Docusaurus v1**, as Docusaurus v1 will be deprecated soon. +Docusaurus v2 has been a total rewrite from Docusaurus v1, taking advantage of a completely modernized toolchain. After [v2's official release](https://docusaurus.io/blog/2022/08/01/announcing-docusaurus-2.0), we highly encourage you to **use Docusaurus v2 over Docusaurus v1**, as Docusaurus v1 has been deprecated. A [lot of users](/showcase) are already using Docusaurus v2 ([trends](https://www.npmtrends.com/docusaurus-vs-@docusaurus/core)). @@ -83,7 +81,9 @@ A [lot of users](/showcase) are already using Docusaurus v2 ([trends](https://ww **Use [Docusaurus v1](https://v1.docusaurus.io/) if:** - :x: You don't want a single-page application (SPA) -- :x: You need support for IE11 +- :x: You need support for IE11 (...do you? IE [has already reached end-of-life](https://docs.microsoft.com/en-us/lifecycle/products/internet-explorer-11) and is no longer officially supported) + +For existing v1 users that are seeking to upgrade to v2, you can follow our [migration guide](./migration/migration-overview.md). ## Features {#features}