From 1c454a94306cc02af05f8ed44801f359a26608b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 30 May 2025 19:22:56 +0200 Subject: [PATCH 001/103] fix(types): fix future flags public types (#11221) --- packages/docusaurus-types/src/config.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-types/src/config.d.ts b/packages/docusaurus-types/src/config.d.ts index d77975a06b..684aa3992e 100644 --- a/packages/docusaurus-types/src/config.d.ts +++ b/packages/docusaurus-types/src/config.d.ts @@ -463,8 +463,8 @@ export type Config = Overwrite< future?: Overwrite< DeepPartial, { - v4?: boolean | FutureV4Config; - experimental_faster?: boolean | FasterConfig; + v4?: boolean | Partial; + experimental_faster?: boolean | Partial; } >; } From ffa7525ff94a8a54adf8191694ad4a051566bb13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 30 May 2025 21:07:11 +0200 Subject: [PATCH 002/103] fix(bundler): fix `docusaurus start` using `concatenateModules: true` (#11222) --- packages/docusaurus/src/webpack/base.ts | 7 ------- packages/docusaurus/src/webpack/server.ts | 10 ++++++++++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/docusaurus/src/webpack/base.ts b/packages/docusaurus/src/webpack/base.ts index c05e022fcf..32e75f3953 100644 --- a/packages/docusaurus/src/webpack/base.ts +++ b/packages/docusaurus/src/webpack/base.ts @@ -253,13 +253,6 @@ export async function createBaseConfig({ modules: ['node_modules', path.join(siteDir, 'node_modules')], }, optimization: { - // The optimization.concatenateModules is expensive - // - On the server, it's not useful to run it at all - // - On the client, it leads to a ~3% JS assets total size decrease - // Let's keep it by default, but large sites may prefer faster builds - // See also https://github.com/facebook/docusaurus/pull/11176 - concatenateModules: !isServer, - // The optimization.mergeDuplicateChunks is expensive // - On the server, it's not useful to run it at all // - On the client, we compared assets/js before/after and see 0 change diff --git a/packages/docusaurus/src/webpack/server.ts b/packages/docusaurus/src/webpack/server.ts index 96454dfb45..740c322c48 100644 --- a/packages/docusaurus/src/webpack/server.ts +++ b/packages/docusaurus/src/webpack/server.ts @@ -52,6 +52,16 @@ export default async function createServerConfig({ color: 'yellow', }), ], + optimization: { + // The optimization.concatenateModules is expensive + // - On the server, it's not useful to run it at all + // - On the client, it leads to a ~3% JS assets total size decrease + // Let's keep it by default, but large sites may prefer faster builds + // See also https://github.com/facebook/docusaurus/pull/11176 + // Note: we don't want to enable it on the client for "docusaurus start" + // See also https://github.com/facebook/docusaurus/pull/11222 + concatenateModules: false, + }, }); return {config, serverBundlePath}; From dacfc17fb4e937893ba7983475f4ad1856f18e8a Mon Sep 17 00:00:00 2001 From: Phil Parsons Date: Mon, 2 Jun 2025 11:40:25 +0100 Subject: [PATCH 003/103] fix(website): ensure feedback widget renders with correct theme (#11224) Co-authored-by: Phil Parsons Co-authored-by: sebastien --- .../featureRequests/FeatureRequestsPage.tsx | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/website/src/plugins/featureRequests/FeatureRequestsPage.tsx b/website/src/plugins/featureRequests/FeatureRequestsPage.tsx index 7cc1099bc3..502e9afd72 100644 --- a/website/src/plugins/featureRequests/FeatureRequestsPage.tsx +++ b/website/src/plugins/featureRequests/FeatureRequestsPage.tsx @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import React, {type ReactNode, useEffect} from 'react'; +import React, {type ReactNode, useEffect, useState} from 'react'; import clsx from 'clsx'; import {useColorMode} from '@docusaurus/theme-common'; import Layout from '@theme/Layout'; @@ -15,8 +15,25 @@ import styles from './styles.module.css'; const BOARD_TOKEN = '054e0e53-d951-b14c-7e74-9eb8f9ed2f91'; +// TODO useColorMode() hook is not reliable on first call +// To ensure we always init Canny with the correct theme, we prefer to delay +// initialization until we know the theme is correct +// See also https://github.com/facebook/docusaurus/issues/7986 +// See also https://github.com/facebook/docusaurus/pull/11224 +function useIsColorModeReliable() { + const [isColorModeReliable, setIsColorModeReliable] = useState(false); + useEffect(() => { + setIsColorModeReliable(true); + }, []); + return isColorModeReliable; +} + function useCannyTheme() { const {colorMode} = useColorMode(); + const isColorModeReliable = useIsColorModeReliable(); + if (!isColorModeReliable) { + return null; + } return colorMode === 'light' ? 'light' : 'dark'; } @@ -27,6 +44,9 @@ function CannyWidget({basePath}: {basePath: string}) { const theme = useCannyTheme(); useEffect(() => { + if (!theme) { + return; + } // eslint-disable-next-line @typescript-eslint/no-explicit-any const {Canny} = window as any; Canny('render', { @@ -35,6 +55,7 @@ function CannyWidget({basePath}: {basePath: string}) { theme, }); }, [basePath, theme]); + return (
Date: Mon, 2 Jun 2025 18:44:07 +0200 Subject: [PATCH 004/103] refactor(docs): extract `loadVersion()` without changing the behavior (#11230) * refactor, extract loadVersion() without changing behavior * Add minimal test case for loadVersion() * Add minimal test case for loadVersion() * more refactor, rename index.ts to version.ts * fix tests * empty --- .../src/__tests__/docs.test.ts | 2 +- .../src/index.ts | 131 +++--------------- .../src/server-export.ts | 2 +- .../__fixtures__/minimal-site/docs/hello.md | 4 + .../__snapshots__/loadVersion.test.ts.snap | 53 +++++++ .../versions/__tests__/loadVersion.test.ts | 73 ++++++++++ .../{index.test.ts => version.test.ts} | 2 +- .../src/versions/files.ts | 2 +- .../src/versions/loadVersion.ts | 130 +++++++++++++++++ .../src/versions/{index.ts => version.ts} | 3 +- 10 files changed, 281 insertions(+), 121 deletions(-) create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs/hello.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__snapshots__/loadVersion.test.ts.snap create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts rename packages/docusaurus-plugin-content-docs/src/versions/__tests__/{index.test.ts => version.test.ts} (99%) create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts rename packages/docusaurus-plugin-content-docs/src/versions/{index.ts => version.ts} (99%) diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts index 2e033b2f1c..6b1815ee25 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts @@ -25,7 +25,7 @@ import { type DocEnv, } from '../docs'; import {loadSidebars} from '../sidebars'; -import {readVersionsMetadata} from '../versions'; +import {readVersionsMetadata} from '../versions/version'; import {DEFAULT_OPTIONS} from '../options'; import type {Sidebars} from '../sidebars/types'; import type {DocFile} from '../types'; diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index 6c0b93f7b3..a740b7f5e2 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -7,7 +7,6 @@ import path from 'path'; import fs from 'fs-extra'; -import _ from 'lodash'; import logger from '@docusaurus/logger'; import { normalizeUrl, @@ -17,30 +16,19 @@ import { posixPath, addTrailingPathSeparator, createAbsoluteFilePathMatcher, - createSlugger, resolveMarkdownLinkPathname, DEFAULT_PLUGIN_ID, - type TagsFile, } from '@docusaurus/utils'; -import { - getTagsFile, - getTagsFilePathsToWatch, -} from '@docusaurus/utils-validation'; +import {getTagsFilePathsToWatch} from '@docusaurus/utils-validation'; import {createMDXLoaderRule} from '@docusaurus/mdx-loader'; -import {loadSidebars, resolveSidebarPathOption} from './sidebars'; +import {resolveSidebarPathOption} from './sidebars'; import {CategoryMetadataFilenamePattern} from './sidebars/generator'; -import { - readVersionDocs, - processDocMetadata, - addDocNavigation, - type DocEnv, - createDocsByIdIndex, -} from './docs'; +import {type DocEnv} from './docs'; import { getVersionFromSourceFilePath, readVersionsMetadata, toFullVersion, -} from './versions'; +} from './versions/version'; import cliDocs from './cli'; import {VERSIONS_JSON_FILE} from './constants'; import {toGlobalDataVersion} from './globalData'; @@ -49,19 +37,17 @@ import { getLoadedContentTranslationFiles, } from './translations'; import {createAllRoutes} from './routes'; -import {createSidebarsUtils} from './sidebars/utils'; import {createContentHelpers} from './contentHelpers'; +import {loadVersion} from './versions/loadVersion'; import type { PluginOptions, - DocMetadataBase, VersionMetadata, DocFrontMatter, LoadedContent, - LoadedVersion, } from '@docusaurus/plugin-content-docs'; import type {LoadContext, Plugin} from '@docusaurus/types'; -import type {DocFile, FullVersion} from './types'; +import type {FullVersion} from './types'; import type {RuleSetRule} from 'webpack'; // MDX loader is not 100% deterministic, leading to cache invalidation issue @@ -243,102 +229,17 @@ export default async function pluginContentDocs( }, async loadContent() { - async function loadVersionDocsBase( - versionMetadata: VersionMetadata, - tagsFile: TagsFile | null, - ): Promise { - const docFiles = await readVersionDocs(versionMetadata, options); - if (docFiles.length === 0) { - throw new Error( - `Docs version "${ - versionMetadata.versionName - }" has no docs! At least one doc should exist at "${path.relative( - siteDir, - versionMetadata.contentPath, - )}".`, - ); - } - function processVersionDoc(docFile: DocFile) { - return processDocMetadata({ - docFile, - versionMetadata, - context, - options, - env, - tagsFile, - }); - } - return Promise.all(docFiles.map(processVersionDoc)); - } - - async function doLoadVersion( - versionMetadata: VersionMetadata, - ): Promise { - const tagsFile = await getTagsFile({ - contentPaths: versionMetadata, - tags: options.tags, - }); - - const docsBase: DocMetadataBase[] = await loadVersionDocsBase( - versionMetadata, - tagsFile, - ); - - // TODO we only ever need draftIds in further code, not full draft items - // To simplify and prevent mistakes, avoid exposing draft - // replace draft=>draftIds in content loaded - const [drafts, docs] = _.partition(docsBase, (doc) => doc.draft); - - const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, { - sidebarItemsGenerator: options.sidebarItemsGenerator, - numberPrefixParser: options.numberPrefixParser, - docs, - drafts, - version: versionMetadata, - sidebarOptions: { - sidebarCollapsed: options.sidebarCollapsed, - sidebarCollapsible: options.sidebarCollapsible, - }, - categoryLabelSlugger: createSlugger(), - }); - - const sidebarsUtils = createSidebarsUtils(sidebars); - - const docsById = createDocsByIdIndex(docs); - const allDocIds = Object.keys(docsById); - - sidebarsUtils.checkLegacyVersionedSidebarNames({ - sidebarFilePath: versionMetadata.sidebarFilePath as string, - versionMetadata, - }); - sidebarsUtils.checkSidebarsDocIds({ - allDocIds, - sidebarFilePath: versionMetadata.sidebarFilePath as string, - versionMetadata, - }); - - return { - ...versionMetadata, - docs: addDocNavigation({ - docs, - sidebarsUtils, - }), - drafts, - sidebars, - }; - } - - async function loadVersion(versionMetadata: VersionMetadata) { - try { - return await doLoadVersion(versionMetadata); - } catch (err) { - logger.error`Loading of version failed for version name=${versionMetadata.versionName}`; - throw err; - } - } - return { - loadedVersions: await Promise.all(versionsMetadata.map(loadVersion)), + loadedVersions: await Promise.all( + versionsMetadata.map((versionMetadata) => + loadVersion({ + context, + options, + env, + versionMetadata, + }), + ), + ), }; }, diff --git a/packages/docusaurus-plugin-content-docs/src/server-export.ts b/packages/docusaurus-plugin-content-docs/src/server-export.ts index 0212758b78..bd2f4e4f76 100644 --- a/packages/docusaurus-plugin-content-docs/src/server-export.ts +++ b/packages/docusaurus-plugin-content-docs/src/server-export.ts @@ -22,5 +22,5 @@ export { getDefaultVersionBanner, getVersionBadge, getVersionBanner, -} from './versions'; +} from './versions/version'; export {readVersionNames} from './versions/files'; diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs/hello.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs/hello.md new file mode 100644 index 0000000000..aef67b7c25 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs/hello.md @@ -0,0 +1,4 @@ + +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__snapshots__/loadVersion.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__snapshots__/loadVersion.test.ts.snap new file mode 100644 index 0000000000..3dde6cbe1a --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__snapshots__/loadVersion.test.ts.snap @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`minimal site can load current version 1`] = ` +{ + "badge": false, + "banner": null, + "className": "docs-version-current", + "contentPath": "/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs", + "contentPathLocalized": "/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/i18n/en/docusaurus-plugin-content-docs/current", + "docs": [ + { + "description": "World", + "draft": false, + "editUrl": undefined, + "frontMatter": {}, + "id": "hello", + "lastUpdatedAt": undefined, + "lastUpdatedBy": undefined, + "next": undefined, + "permalink": "/docs/hello", + "previous": undefined, + "sidebar": "defaultSidebar", + "sidebarPosition": undefined, + "slug": "/hello", + "source": "@site/docs/hello.md", + "sourceDirName": ".", + "tags": [], + "title": "Hello", + "unlisted": false, + "version": "current", + }, + ], + "drafts": [], + "editUrl": undefined, + "editUrlLocalized": undefined, + "isLast": true, + "label": "Next", + "noIndex": false, + "path": "/docs", + "routePriority": -1, + "sidebarFilePath": undefined, + "sidebars": { + "defaultSidebar": [ + { + "id": "hello", + "type": "doc", + }, + ], + }, + "tagsPath": "/docs/tags", + "versionName": "current", +} +`; diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts new file mode 100644 index 0000000000..3e9b6d585f --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts @@ -0,0 +1,73 @@ +/** + * 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 path from 'path'; +import {fromPartial} from '@total-typescript/shoehorn'; +import {DEFAULT_PARSE_FRONT_MATTER} from '@docusaurus/utils/src'; +import {readVersionsMetadata} from '../version'; +import {DEFAULT_OPTIONS} from '../../options'; +import {loadVersion} from '../loadVersion'; +import type {I18n, LoadContext} from '@docusaurus/types'; +import type {PluginOptions} from '@docusaurus/plugin-content-docs'; + +const DefaultI18N: I18n = { + path: 'i18n', + currentLocale: 'en', + locales: ['en'], + defaultLocale: 'en', + localeConfigs: {}, +}; + +describe('minimal site', () => { + async function loadSite() { + const siteDir = path.resolve( + path.join(__dirname, './__fixtures__', 'minimal-site'), + ); + const options: PluginOptions = fromPartial({ + ...DEFAULT_OPTIONS, + }); + const context = fromPartial({ + siteDir, + baseUrl: '/', + i18n: DefaultI18N, + localizationDir: path.join(siteDir, 'i18n/en'), + siteConfig: { + markdown: { + parseFrontMatter: DEFAULT_PARSE_FRONT_MATTER, + }, + }, + }); + return { + siteDir, + options, + context, + }; + } + + it('can load current version', async () => { + const {options, context} = await loadSite(); + + const versionsMetadata = await readVersionsMetadata({ + options, + context, + }); + + expect(versionsMetadata).toHaveLength(1); + expect(versionsMetadata[0]!.versionName).toBe('current'); + + const versionMetadata = versionsMetadata[0]!; + + const loadedVersion = loadVersion({ + context, + options, + versionMetadata, + env: 'production', + }); + + await expect(loadedVersion).resolves.toMatchSnapshot(); + }); +}); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/version.test.ts similarity index 99% rename from packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts rename to packages/docusaurus-plugin-content-docs/src/versions/__tests__/version.test.ts index 26173cb91e..e4e53b58be 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/version.test.ts @@ -8,7 +8,7 @@ import {jest} from '@jest/globals'; import path from 'path'; import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils'; -import {readVersionsMetadata} from '../index'; +import {readVersionsMetadata} from '../version'; import {DEFAULT_OPTIONS} from '../../options'; import type {I18n, LoadContext} from '@docusaurus/types'; import type { diff --git a/packages/docusaurus-plugin-content-docs/src/versions/files.ts b/packages/docusaurus-plugin-content-docs/src/versions/files.ts index 00b3f08270..33839b9027 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/files.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/files.ts @@ -19,7 +19,7 @@ import type { PluginOptions, VersionMetadata, } from '@docusaurus/plugin-content-docs'; -import type {VersionContext} from './index'; +import type {VersionContext} from './version'; /** Add a prefix like `community_version-1.0.0`. No-op for default instance. */ function addPluginIdPrefix(fileOrDir: string, pluginId: string): string { diff --git a/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts b/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts new file mode 100644 index 0000000000..837bb0250c --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts @@ -0,0 +1,130 @@ +/** + * 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 path from 'path'; +import _ from 'lodash'; +import {createSlugger} from '@docusaurus/utils'; +import {getTagsFile} from '@docusaurus/utils-validation'; +import logger from '@docusaurus/logger'; +import { + addDocNavigation, + createDocsByIdIndex, + type DocEnv, + processDocMetadata, + readVersionDocs, +} from '../docs'; +import {loadSidebars} from '../sidebars'; +import {createSidebarsUtils} from '../sidebars/utils'; +import type {TagsFile} from '@docusaurus/utils'; +import type { + DocMetadataBase, + LoadedVersion, + PluginOptions, + VersionMetadata, +} from '@docusaurus/plugin-content-docs'; +import type {DocFile} from '../types'; +import type {LoadContext} from '@docusaurus/types'; + +export async function loadVersion({ + context, + options, + versionMetadata, + env, +}: { + context: LoadContext; + options: PluginOptions; + versionMetadata: VersionMetadata; + env: DocEnv; +}): Promise { + const {siteDir} = context; + + async function loadVersionDocsBase( + tagsFile: TagsFile | null, + ): Promise { + const docFiles = await readVersionDocs(versionMetadata, options); + if (docFiles.length === 0) { + throw new Error( + `Docs version "${ + versionMetadata.versionName + }" has no docs! At least one doc should exist at "${path.relative( + siteDir, + versionMetadata.contentPath, + )}".`, + ); + } + function processVersionDoc(docFile: DocFile) { + return processDocMetadata({ + docFile, + versionMetadata, + context, + options, + env, + tagsFile, + }); + } + return Promise.all(docFiles.map(processVersionDoc)); + } + + async function doLoadVersion(): Promise { + const tagsFile = await getTagsFile({ + contentPaths: versionMetadata, + tags: options.tags, + }); + + const docsBase: DocMetadataBase[] = await loadVersionDocsBase(tagsFile); + + // TODO we only ever need draftIds in further code, not full draft items + // To simplify and prevent mistakes, avoid exposing draft + // replace draft=>draftIds in content loaded + const [drafts, docs] = _.partition(docsBase, (doc) => doc.draft); + + const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, { + sidebarItemsGenerator: options.sidebarItemsGenerator, + numberPrefixParser: options.numberPrefixParser, + docs, + drafts, + version: versionMetadata, + sidebarOptions: { + sidebarCollapsed: options.sidebarCollapsed, + sidebarCollapsible: options.sidebarCollapsible, + }, + categoryLabelSlugger: createSlugger(), + }); + + const sidebarsUtils = createSidebarsUtils(sidebars); + + const docsById = createDocsByIdIndex(docs); + const allDocIds = Object.keys(docsById); + + sidebarsUtils.checkLegacyVersionedSidebarNames({ + sidebarFilePath: versionMetadata.sidebarFilePath as string, + versionMetadata, + }); + sidebarsUtils.checkSidebarsDocIds({ + allDocIds, + sidebarFilePath: versionMetadata.sidebarFilePath as string, + versionMetadata, + }); + + return { + ...versionMetadata, + docs: addDocNavigation({ + docs, + sidebarsUtils, + }), + drafts, + sidebars, + }; + } + + try { + return await doLoadVersion(); + } catch (err) { + logger.error`Loading of version failed for version name=${versionMetadata.versionName}`; + throw err; + } +} diff --git a/packages/docusaurus-plugin-content-docs/src/versions/index.ts b/packages/docusaurus-plugin-content-docs/src/versions/version.ts similarity index 99% rename from packages/docusaurus-plugin-content-docs/src/versions/index.ts rename to packages/docusaurus-plugin-content-docs/src/versions/version.ts index bb77f8cbbd..5b4ef5c043 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/version.ts @@ -243,7 +243,7 @@ export async function readVersionsMetadata({ validateVersionsOptions(allVersionNames, options); const versionNames = filterVersions(allVersionNames, options); const lastVersionName = getLastVersionName({versionNames, options}); - const versionsMetadata = await Promise.all( + return Promise.all( versionNames.map((versionName) => createVersionMetadata({ versionName, @@ -254,7 +254,6 @@ export async function readVersionsMetadata({ }), ), ); - return versionsMetadata; } export function toFullVersion(version: LoadedVersion): FullVersion { From e17a26ab456049439c2484f5577f697bab7c38fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Vincent?= <28714795+leovct@users.noreply.github.com> Date: Wed, 4 Jun 2025 23:32:24 +0200 Subject: [PATCH 005/103] docs: deployment, fix build website commands (#11238) --- website/docs/deployment.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/deployment.mdx b/website/docs/deployment.mdx index 5a6cfb00ee..98f8f02cfa 100644 --- a/website/docs/deployment.mdx +++ b/website/docs/deployment.mdx @@ -407,7 +407,7 @@ jobs: - name: Install dependencies run: npm ci - name: Build website - run: npm build + run: npm run build - name: Upload Build Artifact uses: actions/upload-pages-artifact@v3 @@ -461,7 +461,7 @@ jobs: - name: Install dependencies run: npm ci - name: Test build website - run: npm build + run: npm run build ``` From ef23f546fdd5184a15f2cb15589a6aabc698086c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 5 Jun 2025 12:50:07 +0200 Subject: [PATCH 006/103] chore(ci): add yarn-v1-windows e2e job (#11231) --- .github/workflows/tests-e2e.yml | 42 +++++++++++++++++++++++++++++++++ admin/scripts/test-release.sh | 2 ++ 2 files changed, 44 insertions(+) diff --git a/.github/workflows/tests-e2e.yml b/.github/workflows/tests-e2e.yml index 1e2054dfb9..875910efaa 100644 --- a/.github/workflows/tests-e2e.yml +++ b/.github/workflows/tests-e2e.yml @@ -72,6 +72,48 @@ jobs: DOCUSAURUS_PERF_LOGGER: 'true' working-directory: ../test-website + yarn-v1-windows: + name: E2E — Yarn v1 Windows + timeout-minutes: 30 + runs-on: windows-8-core + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Use Node.js LTS + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: lts/* + cache: yarn + - name: Installation + run: yarn || yarn || yarn + - name: Generate test-website project against main branch + # Not using test-release.sh => no verdaccio docker image on Windows + # run: bash ./admin/scripts/test-release.sh -s + run: yarn create-docusaurus test-website-in-workspace classic --typescript + - name: Install test-website project with Yarn v1 + run: yarn || yarn || yarn + working-directory: test-website-in-workspace + - name: Start test-website project + run: yarn start --no-open + working-directory: test-website-in-workspace + env: + E2E_TEST: true + - name: Build test-website project + # We build 2 locales to ensure a localized site doesn't leak memory + # See https://github.com/facebook/docusaurus/pull/10599 + run: yarn build --locale en --locale fr + env: + # Our website should build even with limited memory + # See https://github.com/facebook/docusaurus/pull/10590 + NODE_OPTIONS: '--max-old-space-size=300' + DOCUSAURUS_PERF_LOGGER: 'true' + working-directory: test-website-in-workspace + - name: Upload Website artifact + uses: actions/upload-artifact@v4 + with: + name: website-e2e-windows + path: test-website-in-workspace/build + yarn-berry: name: E2E — Yarn Berry timeout-minutes: 30 diff --git a/admin/scripts/test-release.sh b/admin/scripts/test-release.sh index 0ae82234a5..53bbb868b1 100755 --- a/admin/scripts/test-release.sh +++ b/admin/scripts/test-release.sh @@ -53,6 +53,8 @@ git diff --name-only -- '*.json' | sed 's, ,\\&,g' | xargs git checkout -- # The website is generated outside the repo to minimize chances of yarn resolving the wrong version cd .. +echo Generating test-website in `pwd` + # Build skeleton website with new version npm_config_registry="$CUSTOM_REGISTRY_URL" npx --yes --loglevel silly create-docusaurus@"$NEW_VERSION" test-website classic --javascript $EXTRA_OPTS From d3ab0e63a02a8c9d41d93fb19c56e8cea8400298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 5 Jun 2025 17:03:41 +0200 Subject: [PATCH 007/103] fix(css-cascade-layers): fix windows css cascade layers bug (#11241) --- packages/docusaurus-plugin-css-cascade-layers/package.json | 1 + .../docusaurus-plugin-css-cascade-layers/src/options.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-plugin-css-cascade-layers/package.json b/packages/docusaurus-plugin-css-cascade-layers/package.json index ab2bb9f46d..ca579d4a19 100644 --- a/packages/docusaurus-plugin-css-cascade-layers/package.json +++ b/packages/docusaurus-plugin-css-cascade-layers/package.json @@ -20,6 +20,7 @@ "dependencies": { "@docusaurus/core": "3.8.0", "@docusaurus/types": "3.8.0", + "@docusaurus/utils": "3.8.0", "@docusaurus/utils-validation": "3.8.0", "tslib": "^2.6.0" }, diff --git a/packages/docusaurus-plugin-css-cascade-layers/src/options.ts b/packages/docusaurus-plugin-css-cascade-layers/src/options.ts index 180e9d427e..60af502ba1 100644 --- a/packages/docusaurus-plugin-css-cascade-layers/src/options.ts +++ b/packages/docusaurus-plugin-css-cascade-layers/src/options.ts @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ import {Joi} from '@docusaurus/utils-validation'; +import {posixPath} from '@docusaurus/utils'; import {isValidLayerName} from './layers'; import type {OptionValidationContext} from '@docusaurus/types'; @@ -20,7 +21,10 @@ export type Options = { // Not ideal to compute layers using "filePath.includes()" // But this is mostly temporary until we add first-class layers everywhere function layerFor(...params: string[]) { - return (filePath: string) => params.some((p) => filePath.includes(p)); + return (filePath: string) => { + const posixFilePath = posixPath(filePath); + return params.some((p) => posixFilePath.includes(p)); + }; } // Object order matters, it defines the layer order From 60df4936aa4189a28e301ebb6fc284706f7b0046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 5 Jun 2025 18:13:46 +0200 Subject: [PATCH 008/103] fix(theme): fix unability to navigate to category's page when browsing its children items (#11242) --- .../src/theme/DocSidebarItem/Category/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx index 49c384c0d1..cf29059928 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx @@ -188,7 +188,11 @@ export default function DocSidebarItemCategory({ ? (e) => { onItemClick?.(item); if (href) { - if (isActive) { + // When already on the category's page, we collapse it + // We don't use "isActive" because it would collapse the + // category even when we browse a children element + // See https://github.com/facebook/docusaurus/issues/11213 + if (isCurrentPage) { e.preventDefault(); updateCollapsed(); } else { From a36ac159475bb2b0d61e50bd972f67814d8cde3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 5 Jun 2025 18:56:09 +0200 Subject: [PATCH 009/103] fix(bundler): upgrade bundler CSS deps to fix potential bugs (#11243) Co-authored-by: slorber <749374+slorber@users.noreply.github.com> --- packages/docusaurus-bundler/package.json | 12 +- .../docusaurus-cssnano-preset/package.json | 2 +- .../docusaurus-theme-classic/package.json | 2 +- yarn.lock | 638 +++++++++--------- 4 files changed, 333 insertions(+), 321 deletions(-) diff --git a/packages/docusaurus-bundler/package.json b/packages/docusaurus-bundler/package.json index 3e0c5c992a..b04ad09c63 100644 --- a/packages/docusaurus-bundler/package.json +++ b/packages/docusaurus-bundler/package.json @@ -25,18 +25,18 @@ "@docusaurus/types": "3.8.0", "@docusaurus/utils": "3.8.0", "babel-loader": "^9.2.1", - "clean-css": "^5.3.2", + "clean-css": "^5.3.3", "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.8.1", + "css-loader": "^6.11.0", "css-minimizer-webpack-plugin": "^5.0.1", "cssnano": "^6.1.2", "file-loader": "^6.2.0", "html-minifier-terser": "^7.2.0", - "mini-css-extract-plugin": "^2.9.1", + "mini-css-extract-plugin": "^2.9.2", "null-loader": "^4.0.1", - "postcss": "^8.4.26", - "postcss-loader": "^7.3.3", - "postcss-preset-env": "^10.1.0", + "postcss": "^8.5.4", + "postcss-loader": "^7.3.4", + "postcss-preset-env": "^10.2.1", "terser-webpack-plugin": "^5.3.9", "tslib": "^2.6.0", "url-loader": "^4.1.1", diff --git a/packages/docusaurus-cssnano-preset/package.json b/packages/docusaurus-cssnano-preset/package.json index bc30723cfd..30659d52de 100644 --- a/packages/docusaurus-cssnano-preset/package.json +++ b/packages/docusaurus-cssnano-preset/package.json @@ -18,7 +18,7 @@ }, "dependencies": { "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.4.38", + "postcss": "^8.5.4", "postcss-sort-media-queries": "^5.2.0", "tslib": "^2.6.0" }, diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index 5b66f97e31..5868661866 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -39,7 +39,7 @@ "infima": "0.2.0-alpha.45", "lodash": "^4.17.21", "nprogress": "^0.2.0", - "postcss": "^8.4.26", + "postcss": "^8.5.4", "prism-react-renderer": "^2.3.0", "prismjs": "^1.29.0", "react-router-dom": "^5.3.4", diff --git a/yarn.lock b/yarn.lock index 3012501d78..70869f6e20 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1697,43 +1697,43 @@ resolved "https://registry.yarnpkg.com/@cspell/url/-/url-8.18.1.tgz#d1b79cecaa5c23f1db54fc980c9f805d7e6ce73e" integrity sha512-FRJbLYDC9ucpTOzbF6MohP2u5X3NU5L0RoVuoYCynqm/QOI38XP6WOEaI4H58CAn857bOIKZk0LZRPTGzi6Qlg== -"@csstools/cascade-layer-name-parser@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-2.0.4.tgz#64d128529397aa1e1c986f685713363b262b81b1" - integrity sha512-7DFHlPuIxviKYZrOiwVU/PiHLm3lLUR23OMuEEtfEOQTOp9hzQ2JjdY6X5H18RVuUPJqSCI+qNnD5iOLMVE0bA== +"@csstools/cascade-layer-name-parser@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-2.0.5.tgz#43f962bebead0052a9fed1a2deeb11f85efcbc72" + integrity sha512-p1ko5eHgV+MgXFVa4STPKpvPxr6ReS8oS2jzTukjR74i5zJNyWO1ZM1m8YKBXnzDKWfBN1ztLYlHxbVemDD88A== -"@csstools/color-helpers@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@csstools/color-helpers/-/color-helpers-5.0.1.tgz#829f1c76f5800b79c51c709e2f36821b728e0e10" - integrity sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA== +"@csstools/color-helpers@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@csstools/color-helpers/-/color-helpers-5.0.2.tgz#82592c9a7c2b83c293d9161894e2a6471feb97b8" + integrity sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA== -"@csstools/css-calc@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@csstools/css-calc/-/css-calc-2.1.0.tgz#3f28b8f8f736b8f78abbc75eebd55c756207e773" - integrity sha512-X69PmFOrjTZfN5ijxtI8hZ9kRADFSLrmmQ6hgDJ272Il049WGKpDY64KhrFm/7rbWve0z81QepawzjkKlqkNGw== +"@csstools/css-calc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@csstools/css-calc/-/css-calc-2.1.4.tgz#8473f63e2fcd6e459838dd412401d5948f224c65" + integrity sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ== -"@csstools/css-color-parser@^3.0.6": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-3.0.6.tgz#e646838f6aab4618aeea7ba0c4921a254e180276" - integrity sha512-S/IjXqTHdpI4EtzGoNCHfqraXF37x12ZZHA1Lk7zoT5pm2lMjFuqhX/89L7dqX4CcMacKK+6ZCs5TmEGb/+wKw== +"@csstools/css-color-parser@^3.0.10": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz#79fc68864dd43c3b6782d2b3828bc0fa9d085c10" + integrity sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg== dependencies: - "@csstools/color-helpers" "^5.0.1" - "@csstools/css-calc" "^2.1.0" + "@csstools/color-helpers" "^5.0.2" + "@csstools/css-calc" "^2.1.4" -"@csstools/css-parser-algorithms@^3.0.4": +"@csstools/css-parser-algorithms@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz#5755370a9a29abaec5515b43c8b3f2cf9c2e3076" + integrity sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ== + +"@csstools/css-tokenizer@^3.0.4": version "3.0.4" - resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz#74426e93bd1c4dcab3e441f5cc7ba4fb35d94356" - integrity sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A== + resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz#333fedabc3fd1a8e5d0100013731cf19e6a8c5d3" + integrity sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw== -"@csstools/css-tokenizer@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz#a5502c8539265fecbd873c1e395a890339f119c2" - integrity sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw== - -"@csstools/media-query-list-parser@^4.0.2": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz#e80e17eba1693fceafb8d6f2cfc68c0e7a9ab78a" - integrity sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A== +"@csstools/media-query-list-parser@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz#7aec77bcb89c2da80ef207e73f474ef9e1b3cdf1" + integrity sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ== "@csstools/postcss-cascade-layers@^5.0.1": version "5.0.1" @@ -1743,46 +1743,57 @@ "@csstools/selector-specificity" "^5.0.0" postcss-selector-parser "^7.0.0" -"@csstools/postcss-color-function@^4.0.6": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-color-function/-/postcss-color-function-4.0.6.tgz#dabd1e516ccd4c7bd5803e37075a503b5f7f0ac4" - integrity sha512-EcvXfC60cTIumzpsxWuvVjb7rsJEHPvqn3jeMEBUaE3JSc4FRuP7mEQ+1eicxWmIrs3FtzMH9gR3sgA5TH+ebQ== +"@csstools/postcss-color-function@^4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@csstools/postcss-color-function/-/postcss-color-function-4.0.10.tgz#11ad43a66ef2cc794ab826a07df8b5fa9fb47a3a" + integrity sha512-4dY0NBu7NVIpzxZRgh/Q/0GPSz/jLSw0i/u3LTUor0BkQcz/fNhN10mSWBDsL0p9nDb0Ky1PD6/dcGbhACuFTQ== dependencies: - "@csstools/css-color-parser" "^3.0.6" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/postcss-progressive-custom-properties" "^4.0.0" + "@csstools/css-color-parser" "^3.0.10" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" "@csstools/utilities" "^2.0.0" -"@csstools/postcss-color-mix-function@^3.0.6": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.6.tgz#d971832ec30b3b60363bceddfeb4b90c7cc0f4b8" - integrity sha512-jVKdJn4+JkASYGhyPO+Wa5WXSx1+oUgaXb3JsjJn/BlrtFh5zjocCY7pwWi0nuP24V1fY7glQsxEYcYNy0dMFg== +"@csstools/postcss-color-mix-function@^3.0.10": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.10.tgz#8c9d0ccfae5c45a9870dd84807ea2995c7a3a514" + integrity sha512-P0lIbQW9I4ShE7uBgZRib/lMTf9XMjJkFl/d6w4EMNHu2qvQ6zljJGEcBkw/NsBtq/6q3WrmgxSS8kHtPMkK4Q== dependencies: - "@csstools/css-color-parser" "^3.0.6" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/postcss-progressive-custom-properties" "^4.0.0" + "@csstools/css-color-parser" "^3.0.10" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" "@csstools/utilities" "^2.0.0" -"@csstools/postcss-content-alt-text@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.4.tgz#76f4687fb15ed45bc1139bb71e5775779762897a" - integrity sha512-YItlZUOuZJCBlRaCf8Aucc1lgN41qYGALMly0qQllrxYJhiyzlI6RxOTMUvtWk+KhS8GphMDsDhKQ7KTPfEMSw== +"@csstools/postcss-color-mix-variadic-function-arguments@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-color-mix-variadic-function-arguments/-/postcss-color-mix-variadic-function-arguments-1.0.0.tgz#0b29cb9b4630d7ed68549db265662d41554a17ed" + integrity sha512-Z5WhouTyD74dPFPrVE7KydgNS9VvnjB8qcdes9ARpCOItb4jTnm7cHp4FhxCRUoyhabD0WVv43wbkJ4p8hLAlQ== dependencies: - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/postcss-progressive-custom-properties" "^4.0.0" + "@csstools/css-color-parser" "^3.0.10" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" "@csstools/utilities" "^2.0.0" -"@csstools/postcss-exponential-functions@^2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-2.0.5.tgz#0c39f75df3357ee1e444b0aa0ede4e12aafea0e9" - integrity sha512-mi8R6dVfA2nDoKM3wcEi64I8vOYEgQVtVKCfmLHXupeLpACfGAided5ddMt5f+CnEodNu4DifuVwb0I6fQDGGQ== +"@csstools/postcss-content-alt-text@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@csstools/postcss-content-alt-text/-/postcss-content-alt-text-2.0.6.tgz#548862226eac54bab0ee5f1bf3a9981393ab204b" + integrity sha512-eRjLbOjblXq+byyaedQRSrAejKGNAFued+LcbzT+LCL78fabxHkxYjBbxkroONxHHYu2qxhFK2dBStTLPG3jpQ== dependencies: - "@csstools/css-calc" "^2.1.0" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" + "@csstools/utilities" "^2.0.0" + +"@csstools/postcss-exponential-functions@^2.0.9": + version "2.0.9" + resolved "https://registry.yarnpkg.com/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-2.0.9.tgz#fc03d1272888cb77e64cc1a7d8a33016e4f05c69" + integrity sha512-abg2W/PI3HXwS/CZshSa79kNWNZHdJPMBXeZNyPQFbbj8sKO3jXxOt/wF7juJVjyDTc6JrvaUZYFcSBZBhaxjw== + dependencies: + "@csstools/css-calc" "^2.1.4" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" "@csstools/postcss-font-format-keywords@^4.0.0": version "4.0.0" @@ -1792,50 +1803,50 @@ "@csstools/utilities" "^2.0.0" postcss-value-parser "^4.2.0" -"@csstools/postcss-gamut-mapping@^2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.6.tgz#04ec6a50fdbca2a30dec56e6bb780c79621e47a7" - integrity sha512-0ke7fmXfc8H+kysZz246yjirAH6JFhyX9GTlyRnM0exHO80XcA9zeJpy5pOp5zo/AZiC/q5Pf+Hw7Pd6/uAoYA== +"@csstools/postcss-gamut-mapping@^2.0.10": + version "2.0.10" + resolved "https://registry.yarnpkg.com/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.10.tgz#f518d941231d721dbecf5b41e3c441885ff2f28b" + integrity sha512-QDGqhJlvFnDlaPAfCYPsnwVA6ze+8hhrwevYWlnUeSjkkZfBpcCO42SaUD8jiLlq7niouyLgvup5lh+f1qessg== dependencies: - "@csstools/css-color-parser" "^3.0.6" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" + "@csstools/css-color-parser" "^3.0.10" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" -"@csstools/postcss-gradients-interpolation-method@^5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.6.tgz#67fa61ada95e4534687fa76cd2d15ac74386560e" - integrity sha512-Itrbx6SLUzsZ6Mz3VuOlxhbfuyLTogG5DwEF1V8dAi24iMuvQPIHd7Ti+pNDp7j6WixndJGZaoNR0f9VSzwuTg== +"@csstools/postcss-gradients-interpolation-method@^5.0.10": + version "5.0.10" + resolved "https://registry.yarnpkg.com/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.10.tgz#3146da352c31142a721fdba062ac3a6d11dbbec3" + integrity sha512-HHPauB2k7Oits02tKFUeVFEU2ox/H3OQVrP3fSOKDxvloOikSal+3dzlyTZmYsb9FlY9p5EUpBtz0//XBmy+aw== dependencies: - "@csstools/css-color-parser" "^3.0.6" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/postcss-progressive-custom-properties" "^4.0.0" + "@csstools/css-color-parser" "^3.0.10" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" "@csstools/utilities" "^2.0.0" -"@csstools/postcss-hwb-function@^4.0.6": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.6.tgz#c40f557a54ed45e75c601a9ba7a08d315f64dbd7" - integrity sha512-927Pqy3a1uBP7U8sTfaNdZVB0mNXzIrJO/GZ8us9219q9n06gOqCdfZ0E6d1P66Fm0fYHvxfDbfcUuwAn5UwhQ== +"@csstools/postcss-hwb-function@^4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.10.tgz#f93f3c457e6440ac37ef9b908feb5d901b417d50" + integrity sha512-nOKKfp14SWcdEQ++S9/4TgRKchooLZL0TUFdun3nI4KPwCjETmhjta1QT4ICQcGVWQTvrsgMM/aLB5We+kMHhQ== dependencies: - "@csstools/css-color-parser" "^3.0.6" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/postcss-progressive-custom-properties" "^4.0.0" + "@csstools/css-color-parser" "^3.0.10" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" "@csstools/utilities" "^2.0.0" -"@csstools/postcss-ic-unit@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.0.tgz#b60ec06500717c337447c39ae7fe7952eeb9d48f" - integrity sha512-9QT5TDGgx7wD3EEMN3BSUG6ckb6Eh5gSPT5kZoVtUuAonfPmLDJyPhqR4ntPpMYhUKAMVKAg3I/AgzqHMSeLhA== +"@csstools/postcss-ic-unit@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@csstools/postcss-ic-unit/-/postcss-ic-unit-4.0.2.tgz#7561e09db65fac8304ceeab9dd3e5c6e43414587" + integrity sha512-lrK2jjyZwh7DbxaNnIUjkeDmU8Y6KyzRBk91ZkI5h8nb1ykEfZrtIVArdIjX4DHMIBGpdHrgP0n4qXDr7OHaKA== dependencies: - "@csstools/postcss-progressive-custom-properties" "^4.0.0" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" "@csstools/utilities" "^2.0.0" postcss-value-parser "^4.2.0" -"@csstools/postcss-initial@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-initial/-/postcss-initial-2.0.0.tgz#a86f5fc59ab9f16f1422dade4c58bd941af5df22" - integrity sha512-dv2lNUKR+JV+OOhZm9paWzYBXOCi+rJPqJ2cJuhh9xd8USVrd0cBEPczla81HNOyThMQWeCcdln3gZkQV2kYxA== +"@csstools/postcss-initial@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@csstools/postcss-initial/-/postcss-initial-2.0.1.tgz#c385bd9d8ad31ad159edd7992069e97ceea4d09a" + integrity sha512-L1wLVMSAZ4wovznquK0xmC7QSctzO4D0Is590bxpGqhqjboLXYA16dWZpfwImkdOgACdQ9PqXsuRroW6qPlEsg== "@csstools/postcss-is-pseudo-class@^5.0.1": version "5.0.1" @@ -1845,14 +1856,14 @@ "@csstools/selector-specificity" "^5.0.0" postcss-selector-parser "^7.0.0" -"@csstools/postcss-light-dark-function@^2.0.7": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.7.tgz#807c170cd28eebb0c00e64dfc6ab0bf418f19209" - integrity sha512-ZZ0rwlanYKOHekyIPaU+sVm3BEHCe+Ha0/px+bmHe62n0Uc1lL34vbwrLYn6ote8PHlsqzKeTQdIejQCJ05tfw== +"@csstools/postcss-light-dark-function@^2.0.9": + version "2.0.9" + resolved "https://registry.yarnpkg.com/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.9.tgz#9fb080188907539734a9d5311d2a1cb82531ef38" + integrity sha512-1tCZH5bla0EAkFAI2r0H33CDnIBeLUaJh1p+hvvsylJ4svsv2wOmJjJn+OXwUZLXef37GYbRIVKX+X+g6m+3CQ== dependencies: - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/postcss-progressive-custom-properties" "^4.0.0" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" "@csstools/utilities" "^2.0.0" "@csstools/postcss-logical-float-and-clear@^3.0.0": @@ -1877,32 +1888,32 @@ dependencies: postcss-value-parser "^4.2.0" -"@csstools/postcss-logical-viewport-units@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-3.0.3.tgz#f6cc63520ca2a6eb76b9cd946070c38dda66d733" - integrity sha512-OC1IlG/yoGJdi0Y+7duz/kU/beCwO+Gua01sD6GtOtLi7ByQUpcIqs7UE/xuRPay4cHgOMatWdnDdsIDjnWpPw== +"@csstools/postcss-logical-viewport-units@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-3.0.4.tgz#016d98a8b7b5f969e58eb8413447eb801add16fc" + integrity sha512-q+eHV1haXA4w9xBwZLKjVKAWn3W2CMqmpNpZUk5kRprvSiBEGMgrNH3/sJZ8UA3JgyHaOt3jwT9uFa4wLX4EqQ== dependencies: - "@csstools/css-tokenizer" "^3.0.3" + "@csstools/css-tokenizer" "^3.0.4" "@csstools/utilities" "^2.0.0" -"@csstools/postcss-media-minmax@^2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@csstools/postcss-media-minmax/-/postcss-media-minmax-2.0.5.tgz#66970aa8d8057f84b88aff21f385194fbe03eb11" - integrity sha512-sdh5i5GToZOIAiwhdntRWv77QDtsxP2r2gXW/WbLSCoLr00KTq/yiF1qlQ5XX2+lmiFa8rATKMcbwl3oXDMNew== +"@csstools/postcss-media-minmax@^2.0.9": + version "2.0.9" + resolved "https://registry.yarnpkg.com/@csstools/postcss-media-minmax/-/postcss-media-minmax-2.0.9.tgz#184252d5b93155ae526689328af6bdf3fc113987" + integrity sha512-af9Qw3uS3JhYLnCbqtZ9crTvvkR+0Se+bBqSr7ykAnl9yKhk6895z9rf+2F4dClIDJWxgn0iZZ1PSdkhrbs2ig== dependencies: - "@csstools/css-calc" "^2.1.0" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/media-query-list-parser" "^4.0.2" + "@csstools/css-calc" "^2.1.4" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/media-query-list-parser" "^4.0.3" -"@csstools/postcss-media-queries-aspect-ratio-number-values@^3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-3.0.4.tgz#d71102172c74baf3f892fac88cf1ea46a961600d" - integrity sha512-AnGjVslHMm5xw9keusQYvjVWvuS7KWK+OJagaG0+m9QnIjZsrysD2kJP/tr/UJIyYtMCtu8OkUd+Rajb4DqtIQ== +"@csstools/postcss-media-queries-aspect-ratio-number-values@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-3.0.5.tgz#f485c31ec13d6b0fb5c528a3474334a40eff5f11" + integrity sha512-zhAe31xaaXOY2Px8IYfoVTB3wglbJUVigGphFLj6exb7cjZRH9A6adyE22XfFK3P2PzwRk0VDeTJmaxpluyrDg== dependencies: - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/media-query-list-parser" "^4.0.2" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/media-query-list-parser" "^4.0.3" "@csstools/postcss-nested-calc@^4.0.0": version "4.0.0" @@ -1919,42 +1930,42 @@ dependencies: postcss-value-parser "^4.2.0" -"@csstools/postcss-oklab-function@^4.0.6": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.6.tgz#17e8dfb6422dfd8d77256def5d5be8335ea7af34" - integrity sha512-Hptoa0uX+XsNacFBCIQKTUBrFKDiplHan42X73EklG6XmQLG7/aIvxoNhvZ7PvOWMt67Pw3bIlUY2nD6p5vL8A== +"@csstools/postcss-oklab-function@^4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.10.tgz#d4c23c51dd0be45e6dedde22432d7d0003710780" + integrity sha512-ZzZUTDd0fgNdhv8UUjGCtObPD8LYxMH+MJsW9xlZaWTV8Ppr4PtxlHYNMmF4vVWGl0T6f8tyWAKjoI6vePSgAg== dependencies: - "@csstools/css-color-parser" "^3.0.6" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/postcss-progressive-custom-properties" "^4.0.0" + "@csstools/css-color-parser" "^3.0.10" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" "@csstools/utilities" "^2.0.0" -"@csstools/postcss-progressive-custom-properties@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.0.0.tgz#ecdb85bcdb1852d73970a214a376684a91f82bdc" - integrity sha512-XQPtROaQjomnvLUSy/bALTR5VCtTVUFwYs1SblvYgLSeTo2a/bMNwUwo2piXw5rTv/FEYiy5yPSXBqg9OKUx7Q== +"@csstools/postcss-progressive-custom-properties@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-4.1.0.tgz#70c8d41b577f4023633b7e3791604e0b7f3775bc" + integrity sha512-YrkI9dx8U4R8Sz2EJaoeD9fI7s7kmeEBfmO+UURNeL6lQI7VxF6sBE+rSqdCBn4onwqmxFdBU3lTwyYb/lCmxA== dependencies: postcss-value-parser "^4.2.0" -"@csstools/postcss-random-function@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@csstools/postcss-random-function/-/postcss-random-function-1.0.1.tgz#73a0b62b5dbbc03c25a28f085235eb61b09a2fb0" - integrity sha512-Ab/tF8/RXktQlFwVhiC70UNfpFQRhtE5fQQoP2pO+KCPGLsLdWFiOuHgSRtBOqEshCVAzR4H6o38nhvRZq8deA== +"@csstools/postcss-random-function@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@csstools/postcss-random-function/-/postcss-random-function-2.0.1.tgz#3191f32fe72936e361dadf7dbfb55a0209e2691e" + integrity sha512-q+FQaNiRBhnoSNo+GzqGOIBKoHQ43lYz0ICrV+UudfWnEF6ksS6DsBIJSISKQT2Bvu3g4k6r7t0zYrk5pDlo8w== dependencies: - "@csstools/css-calc" "^2.1.0" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" + "@csstools/css-calc" "^2.1.4" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" -"@csstools/postcss-relative-color-syntax@^3.0.6": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.6.tgz#4b8bc219b34b16f5abdbbcf09ac13e65bff6ef16" - integrity sha512-yxP618Xb+ji1I624jILaYM62uEmZcmbdmFoZHoaThw896sq0vU39kqTTF+ZNic9XyPtPMvq0vyvbgmHaszq8xg== +"@csstools/postcss-relative-color-syntax@^3.0.10": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.10.tgz#daa840583969461e1e06b12e9c591e52a790ec86" + integrity sha512-8+0kQbQGg9yYG8hv0dtEpOMLwB9M+P7PhacgIzVzJpixxV4Eq9AUQtQw8adMmAJU1RBBmIlpmtmm3XTRd/T00g== dependencies: - "@csstools/css-color-parser" "^3.0.6" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/postcss-progressive-custom-properties" "^4.0.0" + "@csstools/css-color-parser" "^3.0.10" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" "@csstools/utilities" "^2.0.0" "@csstools/postcss-scope-pseudo-class@^4.0.1": @@ -1964,40 +1975,40 @@ dependencies: postcss-selector-parser "^7.0.0" -"@csstools/postcss-sign-functions@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-sign-functions/-/postcss-sign-functions-1.0.0.tgz#37ea7c85874cef5710a1a8878bf0e2b26d4270fd" - integrity sha512-cUpr5W8eookBi5TiLSvx1HL6DFoTTgcj2pmiVNd63y2JHhvtpnJs3sfsFMmLhB42yTRS02tFPsNz3Q5zeN8ZVA== +"@csstools/postcss-sign-functions@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@csstools/postcss-sign-functions/-/postcss-sign-functions-1.1.4.tgz#a9ac56954014ae4c513475b3f1b3e3424a1e0c12" + integrity sha512-P97h1XqRPcfcJndFdG95Gv/6ZzxUBBISem0IDqPZ7WMvc/wlO+yU0c5D/OCpZ5TJoTt63Ok3knGk64N+o6L2Pg== dependencies: - "@csstools/css-calc" "^2.1.0" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" + "@csstools/css-calc" "^2.1.4" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" -"@csstools/postcss-stepped-value-functions@^4.0.5": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-4.0.5.tgz#4d68633d502fbe2b6ef3898e368e3540488a0d8a" - integrity sha512-G6SJ6hZJkhxo6UZojVlLo14MohH4J5J7z8CRBrxxUYy9JuZiIqUo5TBYyDGcE0PLdzpg63a7mHSJz3VD+gMwqw== +"@csstools/postcss-stepped-value-functions@^4.0.9": + version "4.0.9" + resolved "https://registry.yarnpkg.com/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-4.0.9.tgz#36036f1a0e5e5ee2308e72f3c9cb433567c387b9" + integrity sha512-h9btycWrsex4dNLeQfyU3y3w40LMQooJWFMm/SK9lrKguHDcFl4VMkncKKoXi2z5rM9YGWbUQABI8BT2UydIcA== dependencies: - "@csstools/css-calc" "^2.1.0" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" + "@csstools/css-calc" "^2.1.4" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" -"@csstools/postcss-text-decoration-shorthand@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.1.tgz#251fab0939d50c6fd73bb2b830b2574188efa087" - integrity sha512-xPZIikbx6jyzWvhms27uugIc0I4ykH4keRvoa3rxX5K7lEhkbd54rjj/dv60qOCTisoS+3bmwJTeyV1VNBrXaw== +"@csstools/postcss-text-decoration-shorthand@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-4.0.2.tgz#a3bcf80492e6dda36477538ab8e8943908c9f80a" + integrity sha512-8XvCRrFNseBSAGxeaVTaNijAu+FzUvjwFXtcrynmazGb/9WUdsPCpBX+mHEHShVRq47Gy4peYAoxYs8ltUnmzA== dependencies: - "@csstools/color-helpers" "^5.0.1" + "@csstools/color-helpers" "^5.0.2" postcss-value-parser "^4.2.0" -"@csstools/postcss-trigonometric-functions@^4.0.5": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-4.0.5.tgz#267b95a8bd45536e0360596b6da660a9eb6aac83" - integrity sha512-/YQThYkt5MLvAmVu7zxjhceCYlKrYddK6LEmK5I4ojlS6BmO9u2yO4+xjXzu2+NPYmHSTtP4NFSamBCMmJ1NJA== +"@csstools/postcss-trigonometric-functions@^4.0.9": + version "4.0.9" + resolved "https://registry.yarnpkg.com/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-4.0.9.tgz#3f94ed2e319b57f2c59720b64e4d0a8a6fb8c3b2" + integrity sha512-Hnh5zJUdpNrJqK9v1/E3BbrQhaDTj5YiX7P61TOvUhoDHnUmsNNxcDAgkQ32RrcWx9GVUvfUNPcUkn8R3vIX6A== dependencies: - "@csstools/css-calc" "^2.1.0" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" + "@csstools/css-calc" "^2.1.4" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" "@csstools/postcss-unset-value@^4.0.0": version "4.0.0" @@ -5367,16 +5378,16 @@ at-least-node@^1.0.0: resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -autoprefixer@^10.4.19: - version "10.4.20" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.20.tgz#5caec14d43976ef42e32dcb4bd62878e96be5b3b" - integrity sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g== +autoprefixer@^10.4.19, autoprefixer@^10.4.21: + version "10.4.21" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.21.tgz#77189468e7a8ad1d9a37fbc08efc9f480cf0a95d" + integrity sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ== dependencies: - browserslist "^4.23.3" - caniuse-lite "^1.0.30001646" + browserslist "^4.24.4" + caniuse-lite "^1.0.30001702" fraction.js "^4.3.7" normalize-range "^0.1.2" - picocolors "^1.0.1" + picocolors "^1.1.1" postcss-value-parser "^4.2.0" available-typed-arrays@^1.0.7: @@ -5674,15 +5685,15 @@ braces@^3.0.3, braces@~3.0.2: dependencies: fill-range "^7.1.1" -browserslist@^4.0.0, browserslist@^4.21.10, browserslist@^4.23.0, browserslist@^4.23.1, browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.2: - version "4.24.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.2.tgz#f5845bc91069dbd55ee89faf9822e1d885d16580" - integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg== +browserslist@^4.0.0, browserslist@^4.21.10, browserslist@^4.23.0, browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.2, browserslist@^4.24.4, browserslist@^4.25.0: + version "4.25.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.25.0.tgz#986aa9c6d87916885da2b50d8eb577ac8d133b2c" + integrity sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA== dependencies: - caniuse-lite "^1.0.30001669" - electron-to-chromium "^1.5.41" - node-releases "^2.0.18" - update-browserslist-db "^1.1.1" + caniuse-lite "^1.0.30001718" + electron-to-chromium "^1.5.160" + node-releases "^2.0.19" + update-browserslist-db "^1.1.3" bser@2.1.1: version "2.1.1" @@ -5911,10 +5922,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001669, caniuse-lite@^1.0.30001717: - version "1.0.30001718" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz#dae13a9c80d517c30c6197515a96131c194d8f82" - integrity sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.30001717, caniuse-lite@^1.0.30001718: + version "1.0.30001721" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz#36b90cd96901f8c98dd6698bf5c8af7d4c6872d7" + integrity sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ== ccount@^2.0.0: version "2.0.1" @@ -6096,7 +6107,7 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== -clean-css@^5.2.2, clean-css@^5.3.2, clean-css@~5.3.2: +clean-css@^5.2.2, clean-css@^5.3.3, clean-css@~5.3.2: version "5.3.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd" integrity sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg== @@ -6924,16 +6935,16 @@ css-functions-list@^3.1.0: resolved "https://registry.yarnpkg.com/css-functions-list/-/css-functions-list-3.2.0.tgz#8290b7d064bf483f48d6559c10e98dc4d1ad19ee" integrity sha512-d/jBMPyYybkkLVypgtGv12R+pIFw4/f/IHtCTxWpZc8ofTYOPigIgmA6vu5rMHartZC+WuXhBUHfnyNUIQSYrg== -css-has-pseudo@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-7.0.1.tgz#adbb51821e51f7a7c1d2df4d12827870cc311137" - integrity sha512-EOcoyJt+OsuKfCADgLT7gADZI5jMzIe/AeI6MeAYKiFBDmNmM7kk46DtSfMj5AohUJisqVzopBpnQTlvbyaBWg== +css-has-pseudo@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-7.0.2.tgz#fb42e8de7371f2896961e1f6308f13c2c7019b72" + integrity sha512-nzol/h+E0bId46Kn2dQH5VElaknX2Sr0hFuB/1EomdC7j+OISt2ZzK7EHX9DZDY53WbIVAR7FYKSO2XnSf07MQ== dependencies: "@csstools/selector-specificity" "^5.0.0" postcss-selector-parser "^7.0.0" postcss-value-parser "^4.2.0" -css-loader@^6.8.1: +css-loader@^6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.11.0.tgz#33bae3bf6363d0a7c2cf9031c96c744ff54d85ba" integrity sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g== @@ -7007,10 +7018,10 @@ css-what@^6.0.1, css-what@^6.1.0: resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== -cssdb@^8.2.1: - version "8.2.1" - resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-8.2.1.tgz#62a5d9a41e2c86f1d7c35981098fc5ce47c5766c" - integrity sha512-KwEPys7lNsC8OjASI8RrmwOYYDcm0JOW9zQhcV83ejYcQkirTEyeAGui8aO2F5PiS6SLpxuTzl6qlMElIdsgIg== +cssdb@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-8.3.0.tgz#940becad497b8509ad822a28fb0cfe54c969ccfe" + integrity sha512-c7bmItIg38DgGjSwDPZOYF/2o0QU/sSgkWOMyl8votOfgFuyiFKWPesmCGEsrGLxEA9uL540cp8LdaGEjUGsZQ== cssesc@^3.0.0: version "3.0.0" @@ -7876,10 +7887,10 @@ ejs@^3.1.6, ejs@^3.1.7: dependencies: jake "^10.8.5" -electron-to-chromium@^1.5.41: - version "1.5.45" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.45.tgz#fa592ce6a88b44d23acbc7453a2feab98996e6c9" - integrity sha512-vOzZS6uZwhhbkZbcRyiy99Wg+pYFV5hk+5YaECvx0+Z31NR3Tt5zS6dze2OepT6PCTzVzT0dIJItti+uAW5zmw== +electron-to-chromium@^1.5.160: + version "1.5.165" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz#477b0957e42f071905a86f7c905a9848f95d2bdb" + integrity sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw== emittery@^0.13.1: version "0.13.1" @@ -12935,10 +12946,10 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -mini-css-extract-plugin@^2.9.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.1.tgz#4d184f12ce90582e983ccef0f6f9db637b4be758" - integrity sha512-+Vyi+GCCOHnrJ2VPS+6aPoXN2k2jgUzDRhTFLjjTBn23qyXJXkjUWQgTL+mXpF5/A8ixLdCc6kWsoeOjKGejKQ== +mini-css-extract-plugin@^2.9.2: + version "2.9.2" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz#966031b468917a5446f4c24a80854b2947503c5b" + integrity sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w== dependencies: schema-utils "^4.0.0" tapable "^2.2.1" @@ -13192,10 +13203,10 @@ mz@^2.4.0, mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nanoid@^3.3.7: - version "3.3.8" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" - integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== +nanoid@^3.3.11: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== napi-build-utils@^1.0.1: version "1.0.2" @@ -13313,10 +13324,10 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^2.0.18: - version "2.0.18" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" - integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== +node-releases@^2.0.19: + version "2.0.19" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" + integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== nopt@^6.0.0: version "6.0.0" @@ -14274,7 +14285,7 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== -picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.0: +picocolors@^1.0.0, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== @@ -14410,15 +14421,15 @@ postcss-clamp@^4.1.0: dependencies: postcss-value-parser "^4.2.0" -postcss-color-functional-notation@^7.0.6: - version "7.0.6" - resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.6.tgz#d74c1e2294b72287eb9af079c04b7ddeff7ec5b3" - integrity sha512-wLXvm8RmLs14Z2nVpB4CWlnvaWPRcOZFltJSlcbYwSJ1EDZKsKDhPKIMecCnuU054KSmlmubkqczmm6qBPCBhA== +postcss-color-functional-notation@^7.0.10: + version "7.0.10" + resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.10.tgz#f1e9c3e4371889dcdfeabfa8515464fd8338cedc" + integrity sha512-k9qX+aXHBiLTRrWoCJuUFI6F1iF6QJQUXNVWJVSbqZgj57jDhBlOvD8gNUGl35tgqDivbGLhZeW3Ongz4feuKA== dependencies: - "@csstools/css-color-parser" "^3.0.6" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/postcss-progressive-custom-properties" "^4.0.0" + "@csstools/css-color-parser" "^3.0.10" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" "@csstools/utilities" "^2.0.0" postcss-color-hex-alpha@^10.0.0: @@ -14455,35 +14466,35 @@ postcss-convert-values@^6.1.0: browserslist "^4.23.0" postcss-value-parser "^4.2.0" -postcss-custom-media@^11.0.5: - version "11.0.5" - resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-11.0.5.tgz#2fcd88a9b1d4da41c67dac6f2def903063a3377d" - integrity sha512-SQHhayVNgDvSAdX9NQ/ygcDQGEY+aSF4b/96z7QUX6mqL5yl/JgG/DywcF6fW9XbnCRE+aVYk+9/nqGuzOPWeQ== +postcss-custom-media@^11.0.6: + version "11.0.6" + resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-11.0.6.tgz#6b450e5bfa209efb736830066682e6567bd04967" + integrity sha512-C4lD4b7mUIw+RZhtY7qUbf4eADmb7Ey8BFA2px9jUbwg7pjTZDl4KY4bvlUV+/vXQvzQRfiGEVJyAbtOsCMInw== dependencies: - "@csstools/cascade-layer-name-parser" "^2.0.4" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/media-query-list-parser" "^4.0.2" + "@csstools/cascade-layer-name-parser" "^2.0.5" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/media-query-list-parser" "^4.0.3" -postcss-custom-properties@^14.0.4: - version "14.0.4" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-14.0.4.tgz#de9c663285a98833a946d7003a34369d3ce373a9" - integrity sha512-QnW8FCCK6q+4ierwjnmXF9Y9KF8q0JkbgVfvQEMa93x1GT8FvOiUevWCN2YLaOWyByeDX8S6VFbZEeWoAoXs2A== +postcss-custom-properties@^14.0.6: + version "14.0.6" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-14.0.6.tgz#1af73a650bf115ba052cf915287c9982825fc90e" + integrity sha512-fTYSp3xuk4BUeVhxCSJdIPhDLpJfNakZKoiTDx7yRGCdlZrSJR7mWKVOBS4sBF+5poPQFMj2YdXx1VHItBGihQ== dependencies: - "@csstools/cascade-layer-name-parser" "^2.0.4" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" + "@csstools/cascade-layer-name-parser" "^2.0.5" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" "@csstools/utilities" "^2.0.0" postcss-value-parser "^4.2.0" -postcss-custom-selectors@^8.0.4: - version "8.0.4" - resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-8.0.4.tgz#95ef8268fdbbbd84f34cf84a4517c9d99d419c5a" - integrity sha512-ASOXqNvDCE0dAJ/5qixxPeL1aOVGHGW2JwSy7HyjWNbnWTQCl+fDc968HY1jCmZI0+BaYT5CxsOiUhavpG/7eg== +postcss-custom-selectors@^8.0.5: + version "8.0.5" + resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-8.0.5.tgz#9448ed37a12271d7ab6cb364b6f76a46a4a323e8" + integrity sha512-9PGmckHQswiB2usSO6XMSswO2yFWVoCAuih1yl9FVcwkscLjRKjwsjM3t+NIWpSU2Jx3eOiK2+t4vVTQaoCHHg== dependencies: - "@csstools/cascade-layer-name-parser" "^2.0.4" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" + "@csstools/cascade-layer-name-parser" "^2.0.5" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" postcss-selector-parser "^7.0.0" postcss-dir-pseudo-class@^9.0.1: @@ -14520,12 +14531,12 @@ postcss-discard-unused@^6.0.5: dependencies: postcss-selector-parser "^6.0.16" -postcss-double-position-gradients@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.0.tgz#eddd424ec754bb543d057d4d2180b1848095d4d2" - integrity sha512-JkIGah3RVbdSEIrcobqj4Gzq0h53GG4uqDPsho88SgY84WnpkTpI0k50MFK/sX7XqVisZ6OqUfFnoUO6m1WWdg== +postcss-double-position-gradients@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-6.0.2.tgz#185f8eab2db9cf4e34be69b5706c905895bb52ae" + integrity sha512-7qTqnL7nfLRyJK/AHSVrrXOuvDDzettC+wGoienURV8v2svNbu6zJC52ruZtHaO6mfcagFmuTGFdzRsJKB3k5Q== dependencies: - "@csstools/postcss-progressive-custom-properties" "^4.0.0" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" "@csstools/utilities" "^2.0.0" postcss-value-parser "^4.2.0" @@ -14561,18 +14572,18 @@ postcss-image-set-function@^7.0.0: "@csstools/utilities" "^2.0.0" postcss-value-parser "^4.2.0" -postcss-lab-function@^7.0.6: - version "7.0.6" - resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-7.0.6.tgz#3121800fc7939ed1d9a1e87abeb33c407151252c" - integrity sha512-HPwvsoK7C949vBZ+eMyvH2cQeMr3UREoHvbtra76/UhDuiViZH6pir+z71UaJQohd7VDSVUdR6TkWYKExEc9aQ== +postcss-lab-function@^7.0.10: + version "7.0.10" + resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-7.0.10.tgz#0537bd7245b935fc133298c8896bcbd160540cae" + integrity sha512-tqs6TCEv9tC1Riq6fOzHuHcZyhg4k3gIAMB8GGY/zA1ssGdm6puHMVE7t75aOSoFg7UD2wyrFFhbldiCMyyFTQ== dependencies: - "@csstools/css-color-parser" "^3.0.6" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - "@csstools/postcss-progressive-custom-properties" "^4.0.0" + "@csstools/css-color-parser" "^3.0.10" + "@csstools/css-parser-algorithms" "^3.0.5" + "@csstools/css-tokenizer" "^3.0.4" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" "@csstools/utilities" "^2.0.0" -postcss-loader@^7.3.3: +postcss-loader@^7.3.4: version "7.3.4" resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.3.4.tgz#aed9b79ce4ed7e9e89e56199d25ad1ec8f606209" integrity sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A== @@ -14581,10 +14592,10 @@ postcss-loader@^7.3.3: jiti "^1.20.0" semver "^7.5.4" -postcss-logical@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-8.0.0.tgz#0db0b90c2dc53b485a8074a4b7a906297544f58d" - integrity sha512-HpIdsdieClTjXLOyYdUPAX/XQASNIwdKt5hoZW08ZOAiI+tbV0ta1oclkpVkW5ANU+xJvk3KkA0FejkjGLXUkg== +postcss-logical@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-8.1.0.tgz#4092b16b49e3ecda70c4d8945257da403d167228" + integrity sha512-pL1hXFQ2fEXNKiNiAgtfA005T9FBxky5zkX6s4GZM2D8RkVgRqz3f4g1JUoq925zXv495qk8UNldDwh8uGEDoA== dependencies: postcss-value-parser "^4.2.0" @@ -14782,66 +14793,67 @@ postcss-place@^10.0.0: dependencies: postcss-value-parser "^4.2.0" -postcss-preset-env@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-10.1.0.tgz#b9c85d25b26c7581a8b11792b1883469c4b69cbf" - integrity sha512-OfzbinZWpFcmuLB3mabsGa0NArzx5DVVtZ9G1k326iLvU7Jj9q/G3ihBu/Msi0mt96CjrM23HpbuEewDvT71KQ== +postcss-preset-env@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-10.2.1.tgz#e4f60ea0366ce2632524a36cf5e50bec60ba2611" + integrity sha512-mDInnlm4mYhmR0S79hNLzseW9nx4Ihd8s15K99iu6u6QhoSQgqWX9Oj6nTd/8Dz3b0T7v2JSrfnXsDfv9TFvDg== dependencies: "@csstools/postcss-cascade-layers" "^5.0.1" - "@csstools/postcss-color-function" "^4.0.6" - "@csstools/postcss-color-mix-function" "^3.0.6" - "@csstools/postcss-content-alt-text" "^2.0.4" - "@csstools/postcss-exponential-functions" "^2.0.5" + "@csstools/postcss-color-function" "^4.0.10" + "@csstools/postcss-color-mix-function" "^3.0.10" + "@csstools/postcss-color-mix-variadic-function-arguments" "^1.0.0" + "@csstools/postcss-content-alt-text" "^2.0.6" + "@csstools/postcss-exponential-functions" "^2.0.9" "@csstools/postcss-font-format-keywords" "^4.0.0" - "@csstools/postcss-gamut-mapping" "^2.0.6" - "@csstools/postcss-gradients-interpolation-method" "^5.0.6" - "@csstools/postcss-hwb-function" "^4.0.6" - "@csstools/postcss-ic-unit" "^4.0.0" - "@csstools/postcss-initial" "^2.0.0" + "@csstools/postcss-gamut-mapping" "^2.0.10" + "@csstools/postcss-gradients-interpolation-method" "^5.0.10" + "@csstools/postcss-hwb-function" "^4.0.10" + "@csstools/postcss-ic-unit" "^4.0.2" + "@csstools/postcss-initial" "^2.0.1" "@csstools/postcss-is-pseudo-class" "^5.0.1" - "@csstools/postcss-light-dark-function" "^2.0.7" + "@csstools/postcss-light-dark-function" "^2.0.9" "@csstools/postcss-logical-float-and-clear" "^3.0.0" "@csstools/postcss-logical-overflow" "^2.0.0" "@csstools/postcss-logical-overscroll-behavior" "^2.0.0" "@csstools/postcss-logical-resize" "^3.0.0" - "@csstools/postcss-logical-viewport-units" "^3.0.3" - "@csstools/postcss-media-minmax" "^2.0.5" - "@csstools/postcss-media-queries-aspect-ratio-number-values" "^3.0.4" + "@csstools/postcss-logical-viewport-units" "^3.0.4" + "@csstools/postcss-media-minmax" "^2.0.9" + "@csstools/postcss-media-queries-aspect-ratio-number-values" "^3.0.5" "@csstools/postcss-nested-calc" "^4.0.0" "@csstools/postcss-normalize-display-values" "^4.0.0" - "@csstools/postcss-oklab-function" "^4.0.6" - "@csstools/postcss-progressive-custom-properties" "^4.0.0" - "@csstools/postcss-random-function" "^1.0.0" - "@csstools/postcss-relative-color-syntax" "^3.0.6" + "@csstools/postcss-oklab-function" "^4.0.10" + "@csstools/postcss-progressive-custom-properties" "^4.1.0" + "@csstools/postcss-random-function" "^2.0.1" + "@csstools/postcss-relative-color-syntax" "^3.0.10" "@csstools/postcss-scope-pseudo-class" "^4.0.1" - "@csstools/postcss-sign-functions" "^1.0.0" - "@csstools/postcss-stepped-value-functions" "^4.0.5" - "@csstools/postcss-text-decoration-shorthand" "^4.0.1" - "@csstools/postcss-trigonometric-functions" "^4.0.5" + "@csstools/postcss-sign-functions" "^1.1.4" + "@csstools/postcss-stepped-value-functions" "^4.0.9" + "@csstools/postcss-text-decoration-shorthand" "^4.0.2" + "@csstools/postcss-trigonometric-functions" "^4.0.9" "@csstools/postcss-unset-value" "^4.0.0" - autoprefixer "^10.4.19" - browserslist "^4.23.1" + autoprefixer "^10.4.21" + browserslist "^4.25.0" css-blank-pseudo "^7.0.1" - css-has-pseudo "^7.0.1" + css-has-pseudo "^7.0.2" css-prefers-color-scheme "^10.0.0" - cssdb "^8.2.1" + cssdb "^8.3.0" postcss-attribute-case-insensitive "^7.0.1" postcss-clamp "^4.1.0" - postcss-color-functional-notation "^7.0.6" + postcss-color-functional-notation "^7.0.10" postcss-color-hex-alpha "^10.0.0" postcss-color-rebeccapurple "^10.0.0" - postcss-custom-media "^11.0.5" - postcss-custom-properties "^14.0.4" - postcss-custom-selectors "^8.0.4" + postcss-custom-media "^11.0.6" + postcss-custom-properties "^14.0.6" + postcss-custom-selectors "^8.0.5" postcss-dir-pseudo-class "^9.0.1" - postcss-double-position-gradients "^6.0.0" + postcss-double-position-gradients "^6.0.2" postcss-focus-visible "^10.0.1" postcss-focus-within "^9.0.1" postcss-font-variant "^5.0.0" postcss-gap-properties "^6.0.0" postcss-image-set-function "^7.0.0" - postcss-lab-function "^7.0.6" - postcss-logical "^8.0.0" + postcss-lab-function "^7.0.10" + postcss-logical "^8.1.0" postcss-nesting "^13.0.1" postcss-opacity-percentage "^3.0.0" postcss-overflow-shorthand "^6.0.0" @@ -14950,13 +14962,13 @@ postcss-zindex@^6.0.2: resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-6.0.2.tgz#e498304b83a8b165755f53db40e2ea65a99b56e1" integrity sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg== -postcss@^8.2.x, postcss@^8.4.19, postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.26, postcss@^8.4.33, postcss@^8.4.38: - version "8.4.47" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" - integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ== +postcss@^8.2.x, postcss@^8.4.19, postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.33, postcss@^8.5.4: + version "8.5.4" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.4.tgz#d61014ac00e11d5f58458ed7247d899bd65f99c0" + integrity sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w== dependencies: - nanoid "^3.3.7" - picocolors "^1.1.0" + nanoid "^3.3.11" + picocolors "^1.1.1" source-map-js "^1.2.1" postinstall-postinstall@^2.1.0: @@ -18051,13 +18063,13 @@ upath@^1.2.0: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== -update-browserslist-db@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" - integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A== +update-browserslist-db@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" + integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== dependencies: escalade "^3.2.0" - picocolors "^1.1.0" + picocolors "^1.1.1" update-notifier@^6.0.2: version "6.0.2" From 315e3f617e38f7d99fe0ba3b253d1eb450b6aaba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 6 Jun 2025 11:44:59 +0200 Subject: [PATCH 010/103] chore(faster): upgrade Rspack (#11248) --- packages/docusaurus-faster/package.json | 2 +- yarn.lock | 179 ++++++++++++------------ 2 files changed, 90 insertions(+), 91 deletions(-) diff --git a/packages/docusaurus-faster/package.json b/packages/docusaurus-faster/package.json index c6dad75f78..797932439d 100644 --- a/packages/docusaurus-faster/package.json +++ b/packages/docusaurus-faster/package.json @@ -19,7 +19,7 @@ "license": "MIT", "dependencies": { "@docusaurus/types": "3.8.0", - "@rspack/core": "^1.3.10", + "@rspack/core": "^1.3.15", "@swc/core": "^1.7.39", "@swc/html": "^1.7.39", "browserslist": "^4.24.2", diff --git a/yarn.lock b/yarn.lock index 70869f6e20..76c94272a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2576,48 +2576,48 @@ dependencies: langium "3.3.1" -"@module-federation/error-codes@0.13.1": - version "0.13.1" - resolved "https://registry.yarnpkg.com/@module-federation/error-codes/-/error-codes-0.13.1.tgz#8a1697f8e5e62baf135f8a96832f55e0afc31ead" - integrity sha512-azgGDBnFRfqlivHOl96ZjlFUFlukESz2Rnnz/pINiSqoBBNjUE0fcAZP4X6jgrVITuEg90YkruZa7pW9I3m7Uw== +"@module-federation/error-codes@0.14.3": + version "0.14.3" + resolved "https://registry.yarnpkg.com/@module-federation/error-codes/-/error-codes-0.14.3.tgz#e6b5c380240f5650bcf67a1906b22271b891d2c5" + integrity sha512-sBJ3XKU9g5Up31jFeXPFsD8AgORV7TLO/cCSMuRewSfgYbG/3vSKLJmfHrO6+PvjZSb9VyV2UaF02ojktW65vw== -"@module-federation/runtime-core@0.13.1": - version "0.13.1" - resolved "https://registry.yarnpkg.com/@module-federation/runtime-core/-/runtime-core-0.13.1.tgz#e9c8002eed251feeae1a04688dff1fb6c9aa32d1" - integrity sha512-TfyKfkSAentKeuvSsAItk8s5tqQSMfIRTPN2e1aoaq/kFhE+7blps719csyWSX5Lg5Es7WXKMsXHy40UgtBtuw== +"@module-federation/runtime-core@0.14.3": + version "0.14.3" + resolved "https://registry.yarnpkg.com/@module-federation/runtime-core/-/runtime-core-0.14.3.tgz#434025c1304278e30bbc024aaeab086d80f9e196" + integrity sha512-xMFQXflLVW/AJTWb4soAFP+LB4XuhE7ryiLIX8oTyUoBBgV6U2OPghnFljPjeXbud72O08NYlQ1qsHw1kN/V8Q== dependencies: - "@module-federation/error-codes" "0.13.1" - "@module-federation/sdk" "0.13.1" + "@module-federation/error-codes" "0.14.3" + "@module-federation/sdk" "0.14.3" -"@module-federation/runtime-tools@0.13.1": - version "0.13.1" - resolved "https://registry.yarnpkg.com/@module-federation/runtime-tools/-/runtime-tools-0.13.1.tgz#69fc13660b189f516e56ff9f3d55a1ddfe93d2fb" - integrity sha512-GEF1pxqLc80osIMZmE8j9UKZSaTm2hX2lql8tgIH/O9yK4wnF06k6LL5Ah+wJt+oJv6Dj55ri/MoxMP4SXoPNA== +"@module-federation/runtime-tools@0.14.3": + version "0.14.3" + resolved "https://registry.yarnpkg.com/@module-federation/runtime-tools/-/runtime-tools-0.14.3.tgz#fa1414b449cbe5fb6dcbde4ed02c85e0cdcc758b" + integrity sha512-QBETX7iMYXdSa3JtqFlYU+YkpymxETZqyIIRiqg0gW+XGpH3jgU68yjrme2NBJp7URQi/CFZG8KWtfClk0Pjgw== dependencies: - "@module-federation/runtime" "0.13.1" - "@module-federation/webpack-bundler-runtime" "0.13.1" + "@module-federation/runtime" "0.14.3" + "@module-federation/webpack-bundler-runtime" "0.14.3" -"@module-federation/runtime@0.13.1": - version "0.13.1" - resolved "https://registry.yarnpkg.com/@module-federation/runtime/-/runtime-0.13.1.tgz#bd103f3e62dc335f5d7ab6e0b8f086febe5bb487" - integrity sha512-ZHnYvBquDm49LiHfv6fgagMo/cVJneijNJzfPh6S0CJrPS2Tay1bnTXzy8VA5sdIrESagYPaskKMGIj7YfnPug== +"@module-federation/runtime@0.14.3": + version "0.14.3" + resolved "https://registry.yarnpkg.com/@module-federation/runtime/-/runtime-0.14.3.tgz#fc9142c093001c67a0fcacaf53d4eb5749e9bbd6" + integrity sha512-7ZHpa3teUDVhraYdxQGkfGHzPbjna4LtwbpudgzAxSLLFxLDNanaxCuSeIgSM9c+8sVUNC9kvzUgJEZB0krPJw== dependencies: - "@module-federation/error-codes" "0.13.1" - "@module-federation/runtime-core" "0.13.1" - "@module-federation/sdk" "0.13.1" + "@module-federation/error-codes" "0.14.3" + "@module-federation/runtime-core" "0.14.3" + "@module-federation/sdk" "0.14.3" -"@module-federation/sdk@0.13.1": - version "0.13.1" - resolved "https://registry.yarnpkg.com/@module-federation/sdk/-/sdk-0.13.1.tgz#5b8d63719c452e6f691ce1b839f3b09079dfe4c9" - integrity sha512-bmf2FGQ0ymZuxYnw9bIUfhV3y6zDhaqgydEjbl4msObKMLGXZqhse2pTIIxBFpIxR1oONKX/y2FAolDCTlWKiw== +"@module-federation/sdk@0.14.3": + version "0.14.3" + resolved "https://registry.yarnpkg.com/@module-federation/sdk/-/sdk-0.14.3.tgz#a03e37f1cb018283542cfc66a87e7a37e39cfe1a" + integrity sha512-THJZMfbXpqjQOLblCQ8jjcBFFXsGRJwUWE9l/Q4SmuCSKMgAwie7yLT0qSGrHmyBYrsUjAuy+xNB4nfKP0pnGw== -"@module-federation/webpack-bundler-runtime@0.13.1": - version "0.13.1" - resolved "https://registry.yarnpkg.com/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.13.1.tgz#4a14f8626cfbbd9f4d0ec03b5c90b0aa14ba8cbd" - integrity sha512-QSuSIGa09S8mthbB1L6xERqrz+AzPlHR6D7RwAzssAc+IHf40U6NiTLPzUqp9mmKDhC5Tm0EISU0ZHNeJpnpBQ== +"@module-federation/webpack-bundler-runtime@0.14.3": + version "0.14.3" + resolved "https://registry.yarnpkg.com/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.14.3.tgz#2d6bf63e93f626a2f5e469bc57fb5bcc098fee37" + integrity sha512-hIyJFu34P7bY2NeMIUHAS/mYUHEY71VTAsN0A0AqEJFSVPszheopu9VdXq0VDLrP9KQfuXT8SDxeYeJXyj0mgA== dependencies: - "@module-federation/runtime" "0.13.1" - "@module-federation/sdk" "0.13.1" + "@module-federation/runtime" "0.14.3" + "@module-federation/sdk" "0.14.3" "@netlify/functions@^1.6.0": version "1.6.0" @@ -3273,75 +3273,74 @@ fs-extra "^11.1.1" lodash "^4.17.21" -"@rspack/binding-darwin-arm64@1.3.10": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.3.10.tgz#676ac33fc66a7da4669e68175bf267f40b99a282" - integrity sha512-0k/j8OeMSVm5u5Nzckp9Ie7S7hprnvNegebnGr+L6VCyD7sMqm4m+4rLHs99ZklYdH0dZtY2+LrzrtjUZCqfew== +"@rspack/binding-darwin-arm64@1.3.15": + version "1.3.15" + resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.3.15.tgz#8deb8845dbb6285e40dd329b9ad13fcbaf6be8f4" + integrity sha512-f+DnVRENRdVe+ufpZeqTtWAUDSTnP48jVo7x9KWsXf8XyJHUi+eHKEPrFoy1HvL1/k5yJ3HVnFBh1Hb9cNIwSg== -"@rspack/binding-darwin-x64@1.3.10": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.3.10.tgz#79102a085443617bf70ced9dc5f7cfe2fb3dd6a6" - integrity sha512-jOyqYW/18cgxw60wK5oqJvM194pbD4H99xaif89McNtLkH3npFvBkXBHVWWuOHGoXNX0LhRpHcI89p9b9THQZQ== +"@rspack/binding-darwin-x64@1.3.15": + version "1.3.15" + resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.3.15.tgz#a7dc05a5d278c2c1fd920987afb0b839311bff89" + integrity sha512-TfUvEIBqYUT2OK01BYXb2MNcZeZIhAnJy/5aj0qV0uy4KlvwW63HYcKWa1sFd4Ac7bnGShDkanvP3YEuHOFOyg== -"@rspack/binding-linux-arm64-gnu@1.3.10": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.3.10.tgz#192c7f27013119f6fc082fca03525897726eda21" - integrity sha512-zhF5ZNaT/7pxrm8xD3dWG1b4x+FO3LbVeZZG448CjpSo5T57kPD+SaGUU1GcPpn6mexf795x0SVS49aH7/e3Dg== +"@rspack/binding-linux-arm64-gnu@1.3.15": + version "1.3.15" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.3.15.tgz#31a29d4aac66fd92232bccbb2be0273362e1d6f2" + integrity sha512-D/YjYk9snKvYm1Elotq8/GsEipB4ZJWVv/V8cZ+ohhFNOPzygENi6JfyI06TryBTQiN0/JDZqt/S9RaWBWnMqw== -"@rspack/binding-linux-arm64-musl@1.3.10": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.3.10.tgz#2be001351a7f2e93d7a189b8607137343648a682" - integrity sha512-o3x7IrOSCHK6lcRvdZgsSuOG1CHRQR00xiyLW7kkWmNm7t417LC9xdFWKIK62C5fKXGC5YcTbUkDMnQujespkg== +"@rspack/binding-linux-arm64-musl@1.3.15": + version "1.3.15" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.3.15.tgz#f8bdc956f6ef644b1c469d20ecc3849415f3e71b" + integrity sha512-lJbBsPMOiR0hYPCSM42yp7QiZjfo0ALtX7ws2wURpsQp3BMfRVAmXU3Ixpo2XCRtG1zj8crHaCmAWOJTS0smsA== -"@rspack/binding-linux-x64-gnu@1.3.10": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.3.10.tgz#ad44d1dee50688ed81e87235d774bfe22528ce20" - integrity sha512-FMSi28VZhXMr15picOHFynULhqZ/FODPxRIS6uNrvPRYcbNuiO1v+VHV6X88mhOMmJ/aVF6OwjUO/o2l1FVa9Q== +"@rspack/binding-linux-x64-gnu@1.3.15": + version "1.3.15" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.3.15.tgz#5dd39fd59eb5d3f8e353110f3ed40e00242c73f8" + integrity sha512-qGB8ucHklrzNg6lsAS36VrBsCbOw0acgpQNqTE5cuHWrp1Pu3GFTRiFEogenxEmzoRbohMZt0Ev5grivrcgKBQ== -"@rspack/binding-linux-x64-musl@1.3.10": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.3.10.tgz#24ff3df3017c44e570a604e64312b0a3c603a133" - integrity sha512-e0xbY9SlbRGIFz41v1yc0HfREvmgMnLV1bLmTSPK8wI2suIEJ7iYYqsocHOAOk86qLZcxVrTnL6EjUcNaRTWlg== +"@rspack/binding-linux-x64-musl@1.3.15": + version "1.3.15" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.3.15.tgz#32c2bb197568cca841a26ecea019590bc0e2ce56" + integrity sha512-qRn6e40fLQP+N2rQD8GAj/h4DakeTIho32VxTIaHRVuzw68ZD7VmKkwn55ssN370ejmey35ZdoNFNE12RBrMZA== -"@rspack/binding-win32-arm64-msvc@1.3.10": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.3.10.tgz#d853250fee6b066a815c3d29abd115db331a4b6b" - integrity sha512-YHJPvEujWeWjU6EUF6sDpaec9rsOtKVvy16YCtGaxRpDQXqfuxibnp6Ge0ZTTrY+joRiWehRA9OUI+3McqI+QA== +"@rspack/binding-win32-arm64-msvc@1.3.15": + version "1.3.15" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.3.15.tgz#75c1b04d2ea08b49f480825ad57d8ca82acaf6d9" + integrity sha512-7uJ7dWhO1nWXJiCss6Rslz8hoAxAhFpwpbWja3eHgRb7O4NPHg6MWw63AQSI2aFVakreenfu9yXQqYfpVWJ2dA== -"@rspack/binding-win32-ia32-msvc@1.3.10": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.3.10.tgz#40d401aa1c7550f2b5688b68aee54de3abca67b1" - integrity sha512-2iwSBzVBC89ZSk56MYwgirh3bda2WKmL9I3qPajiTEivChXpX7jp83jAtGE6CPqPYcccYz6nrURTHNUZhqXxVw== +"@rspack/binding-win32-ia32-msvc@1.3.15": + version "1.3.15" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.3.15.tgz#56093d8818d68cd270ba63bddffd38dbd50957f7" + integrity sha512-UsaWTYCjDiSCB0A0qETgZk4QvhwfG8gCrO4SJvA+QSEWOmgSai1YV70prFtLLIiyT9mDt1eU3tPWl1UWPRU/EQ== -"@rspack/binding-win32-x64-msvc@1.3.10": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.3.10.tgz#4eefa2d1d851c25ba0e0b1eee0ee525be224c1cd" - integrity sha512-ehWJ9Y5Zezj/+uJpiWbt29RZaRIM00f91PWuabM6/sKmHJhdCEE21u5iI3B8DeW/EjJsH8zkI69YYAxJWwGn9A== +"@rspack/binding-win32-x64-msvc@1.3.15": + version "1.3.15" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.3.15.tgz#eb404ff76ea9da045173e6efccc6b7f276fd6960" + integrity sha512-ZnDIc9Es8EF94MirPDN+hOMt7tkb8nMEbRJFKLMmNd0ElNPgsql+1cY5SqyGRH1hsKB87KfSUQlhFiKZvzbfIg== -"@rspack/binding@1.3.10": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@rspack/binding/-/binding-1.3.10.tgz#b14d9a21a7bae8c7025e6c2d9707e81c311147d5" - integrity sha512-9TjO+Ig5U4VqdYWpBsv01n4d2KsgFfdXGIE7zdHXDDbry0avL0J4109ESqSeP9uC+Bi7ZCF53iaxJRvZDflNVQ== +"@rspack/binding@1.3.15": + version "1.3.15" + resolved "https://registry.yarnpkg.com/@rspack/binding/-/binding-1.3.15.tgz#535fa1f14d173fb72a2d8bb7df10906827e77185" + integrity sha512-utNPuJglLO5lW9XbwIqjB7+2ilMo6JkuVLTVdnNVKU94FW7asn9F/qV+d+MgjUVqU1QPCGm0NuGO9xhbgeJ7pg== optionalDependencies: - "@rspack/binding-darwin-arm64" "1.3.10" - "@rspack/binding-darwin-x64" "1.3.10" - "@rspack/binding-linux-arm64-gnu" "1.3.10" - "@rspack/binding-linux-arm64-musl" "1.3.10" - "@rspack/binding-linux-x64-gnu" "1.3.10" - "@rspack/binding-linux-x64-musl" "1.3.10" - "@rspack/binding-win32-arm64-msvc" "1.3.10" - "@rspack/binding-win32-ia32-msvc" "1.3.10" - "@rspack/binding-win32-x64-msvc" "1.3.10" + "@rspack/binding-darwin-arm64" "1.3.15" + "@rspack/binding-darwin-x64" "1.3.15" + "@rspack/binding-linux-arm64-gnu" "1.3.15" + "@rspack/binding-linux-arm64-musl" "1.3.15" + "@rspack/binding-linux-x64-gnu" "1.3.15" + "@rspack/binding-linux-x64-musl" "1.3.15" + "@rspack/binding-win32-arm64-msvc" "1.3.15" + "@rspack/binding-win32-ia32-msvc" "1.3.15" + "@rspack/binding-win32-x64-msvc" "1.3.15" -"@rspack/core@^1.3.10": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@rspack/core/-/core-1.3.10.tgz#6b00365c3ccfd1008d598d1ce5a82bab466dc777" - integrity sha512-YomvSRGuMUQgCE2rNMdff2q1Z0YpZw/z6m5+PVTMSs9l/q69YKUzpbpSD8YyB5i1DddrRxC2RE34DkrBuwlREQ== +"@rspack/core@^1.3.15": + version "1.3.15" + resolved "https://registry.yarnpkg.com/@rspack/core/-/core-1.3.15.tgz#22bce959aa386c3f38021af6ee6a94339896ffd2" + integrity sha512-QuElIC8jXSKWAp0LSx18pmbhA7NiA5HGoVYesmai90UVxz98tud0KpMxTVCg+0lrLrnKZfCWN9kwjCxM5pGnrA== dependencies: - "@module-federation/runtime-tools" "0.13.1" - "@rspack/binding" "1.3.10" + "@module-federation/runtime-tools" "0.14.3" + "@rspack/binding" "1.3.15" "@rspack/lite-tapable" "1.0.1" - caniuse-lite "^1.0.30001717" "@rspack/lite-tapable@1.0.1": version "1.0.1" @@ -5922,7 +5921,7 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.30001717, caniuse-lite@^1.0.30001718: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.30001718: version "1.0.30001721" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz#36b90cd96901f8c98dd6698bf5c8af7d4c6872d7" integrity sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ== From f811e2dbf432f4ff6d2201b397df91c83ea3f058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 6 Jun 2025 17:45:58 +0200 Subject: [PATCH 011/103] chore: release 3.8.1 (#11249) --- CHANGELOG.md | 39 ++++++++++++++++++ admin/new.docusaurus.io/package.json | 2 +- admin/test-bad-package/package.json | 2 +- argos/package.json | 2 +- lerna.json | 2 +- packages/create-docusaurus/package.json | 6 +-- .../templates/classic-typescript/package.json | 12 +++--- .../templates/classic/package.json | 10 ++--- packages/docusaurus-babel/package.json | 6 +-- packages/docusaurus-bundler/package.json | 12 +++--- .../docusaurus-cssnano-preset/package.json | 2 +- packages/docusaurus-faster/package.json | 4 +- packages/docusaurus-logger/package.json | 2 +- packages/docusaurus-mdx-loader/package.json | 10 ++--- .../package.json | 4 +- .../package.json | 14 +++---- .../package.json | 18 ++++---- .../package.json | 20 ++++----- .../package.json | 12 +++--- .../package.json | 10 ++--- packages/docusaurus-plugin-debug/package.json | 8 ++-- .../package.json | 8 ++-- .../package.json | 8 ++-- .../package.json | 8 ++-- .../package.json | 14 +++---- packages/docusaurus-plugin-pwa/package.json | 20 ++++----- .../docusaurus-plugin-rsdoctor/package.json | 8 ++-- .../docusaurus-plugin-sitemap/package.json | 14 +++---- packages/docusaurus-plugin-svgr/package.json | 10 ++--- .../package.json | 12 +++--- .../docusaurus-preset-classic/package.json | 32 +++++++------- .../package.json | 2 +- .../docusaurus-theme-classic/package.json | 28 ++++++------- packages/docusaurus-theme-common/package.json | 14 +++---- .../package.json | 12 +++--- .../docusaurus-theme-mermaid/package.json | 12 +++--- .../package.json | 18 ++++---- .../package.json | 10 ++--- packages/docusaurus-tsconfig/package.json | 2 +- packages/docusaurus-types/package.json | 2 +- packages/docusaurus-utils-common/package.json | 4 +- .../docusaurus-utils-validation/package.json | 8 ++-- packages/docusaurus-utils/package.json | 8 ++-- packages/docusaurus/package.json | 20 ++++----- packages/eslint-plugin/package.json | 2 +- packages/lqip-loader/package.json | 4 +- packages/stylelint-copyright/package.json | 2 +- website/package.json | 34 +++++++-------- .../advanced/architecture.mdx | 0 .../advanced/client.mdx | 0 .../advanced/index.mdx | 0 .../advanced/plugins.mdx | 0 .../advanced/routing.mdx | 0 .../advanced/ssg.mdx | 0 .../api/docusaurus.config.js.mdx | 0 .../api/misc/_category_.yml | 0 .../api/misc/create-docusaurus.mdx | 0 .../api/misc/eslint-plugin/README.mdx | 0 .../api/misc/eslint-plugin/no-html-links.mdx | 0 .../eslint-plugin/no-untranslated-text.mdx | 0 .../prefer-docusaurus-heading.mdx | 0 .../string-literal-i18n-messages.mdx | 0 .../api/misc/logger/demo.png | Bin .../api/misc/logger/logger.mdx | 0 .../api/plugin-methods/README.mdx | 0 .../api/plugin-methods/_category_.yml | 0 .../plugin-methods/extend-infrastructure.mdx | 0 .../api/plugin-methods/i18n-lifecycles.mdx | 0 .../api/plugin-methods/lifecycle-apis.mdx | 0 .../api/plugin-methods/static-methods.mdx | 0 .../api/plugins/_category_.yml | 0 .../_partial-tags-file-api-ref-section.mdx | 0 .../api/plugins/overview.mdx | 0 .../api/plugins/plugin-client-redirects.mdx | 0 .../api/plugins/plugin-content-blog.mdx | 0 .../api/plugins/plugin-content-docs.mdx | 0 .../api/plugins/plugin-content-pages.mdx | 0 .../api/plugins/plugin-css-cascade-layers.mdx | 0 .../api/plugins/plugin-debug.mdx | 0 .../api/plugins/plugin-google-analytics.mdx | 0 .../api/plugins/plugin-google-gtag.mdx | 0 .../api/plugins/plugin-google-tag-manager.mdx | 0 .../api/plugins/plugin-ideal-image.mdx | 0 .../api/plugins/plugin-pwa.mdx | 0 .../api/plugins/plugin-rsdoctor.mdx | 0 .../api/plugins/plugin-sitemap.mdx | 0 .../api/plugins/plugin-svgr.mdx | 0 .../api/plugins/plugin-vercel-analytics.mdx | 0 .../api/themes/_category_.yml | 0 .../api/themes/overview.mdx | 0 .../api/themes/theme-classic.mdx | 0 .../api/themes/theme-configuration.mdx | 0 .../api/themes/theme-live-codeblock.mdx | 0 .../api/themes/theme-mermaid.mdx | 0 .../api/themes/theme-search-algolia.mdx | 0 .../docusaurus-asset-example-banner.png | Bin .../assets/docusaurus-asset-example.docx | Bin .../assets/docusaurus-asset-example.xyz | Bin .../{version-3.8.0 => version-3.8.1}/blog.mdx | 0 .../browser-support.mdx | 0 .../{version-3.8.0 => version-3.8.1}/cli.mdx | 0 .../configuration.mdx | 0 .../deployment.mdx | 0 .../docusaurus-core.mdx | 0 .../guides/creating-pages.mdx | 0 .../guides/docs/docs-create-doc.mdx | 0 .../guides/docs/docs-introduction.mdx | 0 .../guides/docs/docs-multi-instance.mdx | 0 .../guides/docs/sidebar/autogenerated.mdx | 0 .../guides/docs/sidebar/index.mdx | 0 .../guides/docs/sidebar/items.mdx | 0 .../guides/docs/sidebar/multiple-sidebars.mdx | 0 .../guides/docs/versioning.mdx | 0 .../_markdown-partial-example.mdx | 0 .../markdown-features-admonitions.mdx | 0 .../markdown-features-assets.mdx | 0 .../markdown-features-code-blocks.mdx | 0 .../markdown-features-diagrams.mdx | 0 .../markdown-features-head-metadata.mdx | 0 .../markdown-features-intro.mdx | 0 .../markdown-features-links.mdx | 0 .../markdown-features-math-equations.mdx | 0 .../markdown-features-plugins.mdx | 0 .../markdown-features-react.mdx | 0 .../markdown-features-react.module.css | 0 .../markdown-features-tabs-styles.module.css | 0 .../markdown-features-tabs.mdx | 0 .../markdown-features-toc.mdx | 0 .../guides/whats-next.mdx | 0 .../i18n/i18n-crowdin.mdx | 0 .../i18n/i18n-git.mdx | 0 .../i18n/i18n-introduction.mdx | 0 .../i18n/i18n-tutorial.mdx | 0 .../installation.mdx | 0 .../introduction.mdx | 0 .../migration/index.mdx | 0 .../migration/v2/migration-automated.mdx | 0 .../migration/v2/migration-manual.mdx | 0 .../migration/v2/migration-overview.mdx | 0 .../v2/migration-translated-sites.mdx | 0 .../v2/migration-versioned-sites.mdx | 0 .../migration/v3.mdx | 0 .../playground.mdx | 0 .../search.mdx | 0 .../{version-3.8.0 => version-3.8.1}/seo.mdx | 0 .../static-assets.mdx | 0 .../styling-layout.mdx | 0 .../swizzling.mdx | 0 .../typescript-support.mdx | 0 .../using-plugins.mdx | 0 ...ebars.json => version-3.8.1-sidebars.json} | 0 website/versions.json | 2 +- 152 files changed, 277 insertions(+), 238 deletions(-) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/advanced/architecture.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/advanced/client.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/advanced/index.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/advanced/plugins.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/advanced/routing.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/advanced/ssg.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/docusaurus.config.js.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/misc/_category_.yml (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/misc/create-docusaurus.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/misc/eslint-plugin/README.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/misc/eslint-plugin/no-html-links.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/misc/eslint-plugin/no-untranslated-text.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/misc/eslint-plugin/prefer-docusaurus-heading.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/misc/eslint-plugin/string-literal-i18n-messages.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/misc/logger/demo.png (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/misc/logger/logger.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugin-methods/README.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugin-methods/_category_.yml (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugin-methods/extend-infrastructure.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugin-methods/i18n-lifecycles.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugin-methods/lifecycle-apis.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugin-methods/static-methods.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/_category_.yml (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/_partial-tags-file-api-ref-section.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/overview.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-client-redirects.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-content-blog.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-content-docs.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-content-pages.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-css-cascade-layers.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-debug.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-google-analytics.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-google-gtag.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-google-tag-manager.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-ideal-image.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-pwa.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-rsdoctor.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-sitemap.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-svgr.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/plugins/plugin-vercel-analytics.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/themes/_category_.yml (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/themes/overview.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/themes/theme-classic.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/themes/theme-configuration.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/themes/theme-live-codeblock.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/themes/theme-mermaid.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/api/themes/theme-search-algolia.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/assets/docusaurus-asset-example-banner.png (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/assets/docusaurus-asset-example.docx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/assets/docusaurus-asset-example.xyz (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/blog.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/browser-support.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/cli.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/configuration.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/deployment.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/docusaurus-core.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/creating-pages.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/docs/docs-create-doc.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/docs/docs-introduction.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/docs/docs-multi-instance.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/docs/sidebar/autogenerated.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/docs/sidebar/index.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/docs/sidebar/items.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/docs/sidebar/multiple-sidebars.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/docs/versioning.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/_markdown-partial-example.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-admonitions.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-assets.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-code-blocks.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-diagrams.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-head-metadata.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-intro.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-links.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-math-equations.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-plugins.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-react.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-react.module.css (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-tabs-styles.module.css (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-tabs.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/markdown-features/markdown-features-toc.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/guides/whats-next.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/i18n/i18n-crowdin.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/i18n/i18n-git.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/i18n/i18n-introduction.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/i18n/i18n-tutorial.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/installation.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/introduction.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/migration/index.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/migration/v2/migration-automated.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/migration/v2/migration-manual.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/migration/v2/migration-overview.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/migration/v2/migration-translated-sites.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/migration/v2/migration-versioned-sites.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/migration/v3.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/playground.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/search.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/seo.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/static-assets.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/styling-layout.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/swizzling.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/typescript-support.mdx (100%) rename website/versioned_docs/{version-3.8.0 => version-3.8.1}/using-plugins.mdx (100%) rename website/versioned_sidebars/{version-3.8.0-sidebars.json => version-3.8.1-sidebars.json} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 035ea191b0..02aac58ae9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,44 @@ # Docusaurus Changelog +## 3.8.1 (2025-06-06) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#11242](https://github.com/facebook/docusaurus/pull/11242) fix(theme): fix unability to navigate to category's page when browsing its children items ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-css-cascade-layers` + - [#11241](https://github.com/facebook/docusaurus/pull/11241) fix(css-cascade-layers): fix windows css cascade layers bug ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#11222](https://github.com/facebook/docusaurus/pull/11222) fix(bundler): fix `docusaurus start` using `concatenateModules: true` ([@slorber](https://github.com/slorber)) + - [#11217](https://github.com/facebook/docusaurus/pull/11217) fix: include Arc to supported Chromium Browsers ([@wellwelwel](https://github.com/wellwelwel)) + - [#11205](https://github.com/facebook/docusaurus/pull/11205) fix(core): fix `docusaurus start` error for macOS users with no Chromium-based browser ([@slorber](https://github.com/slorber)) +- `docusaurus-types` + - [#11221](https://github.com/facebook/docusaurus/pull/11221) fix(types): fix future flags public types ([@slorber](https://github.com/slorber)) + +#### :running_woman: Performance + +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#11211](https://github.com/facebook/docusaurus/pull/11211) perf: avoid duplicated `git log` calls in `loadContent()` and `postBuild()` for untracked Git files ([@slorber](https://github.com/slorber)) + +#### :wrench: Maintenance + +- `docusaurus-faster` + - [#11248](https://github.com/facebook/docusaurus/pull/11248) chore(faster): upgrade Rspack ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs` + - [#11230](https://github.com/facebook/docusaurus/pull/11230) refactor(docs): extract `loadVersion()` without changing the behavior ([@slorber](https://github.com/slorber)) +- Other + - [#11212](https://github.com/facebook/docusaurus/pull/11212) chore: upgrade to Node 22 by default ([@slorber](https://github.com/slorber)) + +#### Committers: 7 + +- Ben McCann ([@benmccann](https://github.com/benmccann)) +- Dave Meyer ([@dave-meyer](https://github.com/dave-meyer)) +- Léo Vincent ([@leovct](https://github.com/leovct)) +- Noritaka Kobayashi ([@noritaka1166](https://github.com/noritaka1166)) +- Phil Parsons ([@p-m-p](https://github.com/p-m-p)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Weslley Araújo ([@wellwelwel](https://github.com/wellwelwel)) + ## 3.8.0 (2025-05-26) #### :rocket: New Feature diff --git a/admin/new.docusaurus.io/package.json b/admin/new.docusaurus.io/package.json index 5ed90aed2b..4146fb0d03 100644 --- a/admin/new.docusaurus.io/package.json +++ b/admin/new.docusaurus.io/package.json @@ -1,6 +1,6 @@ { "name": "new.docusaurus.io", - "version": "3.8.0", + "version": "3.8.1", "private": true, "scripts": { "start": "npx --package netlify-cli netlify dev" diff --git a/admin/test-bad-package/package.json b/admin/test-bad-package/package.json index c85734f83c..6b5043a5e9 100644 --- a/admin/test-bad-package/package.json +++ b/admin/test-bad-package/package.json @@ -1,6 +1,6 @@ { "name": "test-bad-package", - "version": "3.8.0", + "version": "3.8.1", "private": true, "dependencies": { "@mdx-js/react": "1.0.1", diff --git a/argos/package.json b/argos/package.json index 2e86304c5b..da71275545 100644 --- a/argos/package.json +++ b/argos/package.json @@ -1,6 +1,6 @@ { "name": "argos", - "version": "3.8.0", + "version": "3.8.1", "description": "Argos visual diff tests", "license": "MIT", "private": true, diff --git a/lerna.json b/lerna.json index 65ae45e5dd..08d375dded 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "3.8.0", + "version": "3.8.1", "npmClient": "yarn", "useWorkspaces": true, "useNx": false, diff --git a/packages/create-docusaurus/package.json b/packages/create-docusaurus/package.json index 8e93de1010..7c2ce37e28 100755 --- a/packages/create-docusaurus/package.json +++ b/packages/create-docusaurus/package.json @@ -1,6 +1,6 @@ { "name": "create-docusaurus", - "version": "3.8.0", + "version": "3.8.1", "description": "Create Docusaurus apps easily.", "type": "module", "repository": { @@ -22,8 +22,8 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.0", - "@docusaurus/utils": "3.8.0", + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", "commander": "^5.1.0", "execa": "5.1.1", "fs-extra": "^11.1.1", diff --git a/packages/create-docusaurus/templates/classic-typescript/package.json b/packages/create-docusaurus/templates/classic-typescript/package.json index 57d674ab49..543f44f99b 100644 --- a/packages/create-docusaurus/templates/classic-typescript/package.json +++ b/packages/create-docusaurus/templates/classic-typescript/package.json @@ -1,6 +1,6 @@ { "name": "docusaurus-2-classic-typescript-template", - "version": "3.8.0", + "version": "3.8.1", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -15,8 +15,8 @@ "typecheck": "tsc" }, "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/preset-classic": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/preset-classic": "3.8.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "prism-react-renderer": "^2.3.0", @@ -24,9 +24,9 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/tsconfig": "3.8.0", - "@docusaurus/types": "3.8.0", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/tsconfig": "3.8.1", + "@docusaurus/types": "3.8.1", "typescript": "~5.6.2" }, "browserslist": { diff --git a/packages/create-docusaurus/templates/classic/package.json b/packages/create-docusaurus/templates/classic/package.json index 4df4f79808..91083729fd 100644 --- a/packages/create-docusaurus/templates/classic/package.json +++ b/packages/create-docusaurus/templates/classic/package.json @@ -1,6 +1,6 @@ { "name": "docusaurus-2-classic-template", - "version": "3.8.0", + "version": "3.8.1", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -14,8 +14,8 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/preset-classic": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/preset-classic": "3.8.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "prism-react-renderer": "^2.3.0", @@ -23,8 +23,8 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/types": "3.8.0" + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/types": "3.8.1" }, "browserslist": { "production": [ diff --git a/packages/docusaurus-babel/package.json b/packages/docusaurus-babel/package.json index 982104a462..1c111b7c8b 100644 --- a/packages/docusaurus-babel/package.json +++ b/packages/docusaurus-babel/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/babel", - "version": "3.8.0", + "version": "3.8.1", "description": "Docusaurus package for Babel-related utils.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -38,8 +38,8 @@ "@babel/runtime": "^7.25.9", "@babel/runtime-corejs3": "^7.25.9", "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.8.0", - "@docusaurus/utils": "3.8.0", + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", "babel-plugin-dynamic-import-node": "^2.3.3", "fs-extra": "^11.1.1", "tslib": "^2.6.0" diff --git a/packages/docusaurus-bundler/package.json b/packages/docusaurus-bundler/package.json index b04ad09c63..6b6e252cdf 100644 --- a/packages/docusaurus-bundler/package.json +++ b/packages/docusaurus-bundler/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/bundler", - "version": "3.8.0", + "version": "3.8.1", "description": "Docusaurus util package to abstract the current bundler.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -19,11 +19,11 @@ "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.8.0", - "@docusaurus/cssnano-preset": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", + "@docusaurus/babel": "3.8.1", + "@docusaurus/cssnano-preset": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", "babel-loader": "^9.2.1", "clean-css": "^5.3.3", "copy-webpack-plugin": "^11.0.0", diff --git a/packages/docusaurus-cssnano-preset/package.json b/packages/docusaurus-cssnano-preset/package.json index 30659d52de..d4d8fbacd1 100644 --- a/packages/docusaurus-cssnano-preset/package.json +++ b/packages/docusaurus-cssnano-preset/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/cssnano-preset", - "version": "3.8.0", + "version": "3.8.1", "description": "Advanced cssnano preset for maximum optimization.", "main": "lib/index.js", "license": "MIT", diff --git a/packages/docusaurus-faster/package.json b/packages/docusaurus-faster/package.json index 797932439d..86127a48e2 100644 --- a/packages/docusaurus-faster/package.json +++ b/packages/docusaurus-faster/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/faster", - "version": "3.8.0", + "version": "3.8.1", "description": "Docusaurus experimental package exposing new modern dependencies to make the build faster.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -18,7 +18,7 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/types": "3.8.0", + "@docusaurus/types": "3.8.1", "@rspack/core": "^1.3.15", "@swc/core": "^1.7.39", "@swc/html": "^1.7.39", diff --git a/packages/docusaurus-logger/package.json b/packages/docusaurus-logger/package.json index 0f1add4994..14a58f1009 100644 --- a/packages/docusaurus-logger/package.json +++ b/packages/docusaurus-logger/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/logger", - "version": "3.8.0", + "version": "3.8.1", "description": "An encapsulated logger for semantically formatting console messages.", "main": "./lib/index.js", "repository": { diff --git a/packages/docusaurus-mdx-loader/package.json b/packages/docusaurus-mdx-loader/package.json index 555eb266fe..46ba90b8bc 100644 --- a/packages/docusaurus-mdx-loader/package.json +++ b/packages/docusaurus-mdx-loader/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/mdx-loader", - "version": "3.8.0", + "version": "3.8.1", "description": "Docusaurus Loader for MDX", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -44,7 +44,7 @@ "webpack": "^5.88.1" }, "devDependencies": { - "@docusaurus/types": "3.8.0", + "@docusaurus/types": "3.8.1", "@types/escape-html": "^1.0.2", "@types/mdast": "^4.0.2", "@types/stringify-object": "^3.3.1", diff --git a/packages/docusaurus-module-type-aliases/package.json b/packages/docusaurus-module-type-aliases/package.json index 2ce77cae4f..7ea74490b1 100644 --- a/packages/docusaurus-module-type-aliases/package.json +++ b/packages/docusaurus-module-type-aliases/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/module-type-aliases", - "version": "3.8.0", + "version": "3.8.1", "description": "Docusaurus module type aliases.", "types": "./src/index.d.ts", "publishConfig": { @@ -12,7 +12,7 @@ "directory": "packages/docusaurus-module-type-aliases" }, "dependencies": { - "@docusaurus/types": "3.8.0", + "@docusaurus/types": "3.8.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", diff --git a/packages/docusaurus-plugin-client-redirects/package.json b/packages/docusaurus-plugin-client-redirects/package.json index 8f5eb017c2..7dcee5be1f 100644 --- a/packages/docusaurus-plugin-client-redirects/package.json +++ b/packages/docusaurus-plugin-client-redirects/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-client-redirects", - "version": "3.8.0", + "version": "3.8.1", "description": "Client redirects plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,18 +18,18 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "eta": "^2.2.0", "fs-extra": "^11.1.1", "lodash": "^4.17.21", "tslib": "^2.6.0" }, "devDependencies": { - "@docusaurus/types": "3.8.0" + "@docusaurus/types": "3.8.1" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json index a68091ea6c..615ce75013 100644 --- a/packages/docusaurus-plugin-content-blog/package.json +++ b/packages/docusaurus-plugin-content-blog/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-content-blog", - "version": "3.8.0", + "version": "3.8.1", "description": "Blog plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-content-blog.d.ts", @@ -31,14 +31,14 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "cheerio": "1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", diff --git a/packages/docusaurus-plugin-content-docs/package.json b/packages/docusaurus-plugin-content-docs/package.json index 0050e6db26..7ac48ffa89 100644 --- a/packages/docusaurus-plugin-content-docs/package.json +++ b/packages/docusaurus-plugin-content-docs/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-content-docs", - "version": "3.8.0", + "version": "3.8.1", "description": "Docs plugin for Docusaurus.", "main": "lib/index.js", "sideEffects": false, @@ -35,15 +35,15 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", diff --git a/packages/docusaurus-plugin-content-pages/package.json b/packages/docusaurus-plugin-content-pages/package.json index 6914af1528..16d3d9ed16 100644 --- a/packages/docusaurus-plugin-content-pages/package.json +++ b/packages/docusaurus-plugin-content-pages/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-content-pages", - "version": "3.8.0", + "version": "3.8.1", "description": "Pages plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-content-pages.d.ts", @@ -18,11 +18,11 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" diff --git a/packages/docusaurus-plugin-css-cascade-layers/package.json b/packages/docusaurus-plugin-css-cascade-layers/package.json index ca579d4a19..56c9bc6b34 100644 --- a/packages/docusaurus-plugin-css-cascade-layers/package.json +++ b/packages/docusaurus-plugin-css-cascade-layers/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-css-cascade-layers", - "version": "3.8.0", + "version": "3.8.1", "description": "CSS Cascade Layer plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,10 +18,10 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "tslib": "^2.6.0" }, "engines": { diff --git a/packages/docusaurus-plugin-debug/package.json b/packages/docusaurus-plugin-debug/package.json index d719496d70..6c7987ea9d 100644 --- a/packages/docusaurus-plugin-debug/package.json +++ b/packages/docusaurus-plugin-debug/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-debug", - "version": "3.8.0", + "version": "3.8.1", "description": "Debug plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-debug.d.ts", @@ -20,9 +20,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", "fs-extra": "^11.1.1", "react-json-view-lite": "^2.3.0", "tslib": "^2.6.0" diff --git a/packages/docusaurus-plugin-google-analytics/package.json b/packages/docusaurus-plugin-google-analytics/package.json index bfab23ec93..1bba44dfff 100644 --- a/packages/docusaurus-plugin-google-analytics/package.json +++ b/packages/docusaurus-plugin-google-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-google-analytics", - "version": "3.8.0", + "version": "3.8.1", "description": "Global analytics (analytics.js) plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "tslib": "^2.6.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-google-gtag/package.json b/packages/docusaurus-plugin-google-gtag/package.json index 7ad4066b5e..477dafd9b7 100644 --- a/packages/docusaurus-plugin-google-gtag/package.json +++ b/packages/docusaurus-plugin-google-gtag/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-google-gtag", - "version": "3.8.0", + "version": "3.8.1", "description": "Global Site Tag (gtag.js) plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, diff --git a/packages/docusaurus-plugin-google-tag-manager/package.json b/packages/docusaurus-plugin-google-tag-manager/package.json index 71f25dd878..47444e2590 100644 --- a/packages/docusaurus-plugin-google-tag-manager/package.json +++ b/packages/docusaurus-plugin-google-tag-manager/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-google-tag-manager", - "version": "3.8.0", + "version": "3.8.1", "description": "Google Tag Manager (gtm.js) plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "tslib": "^2.6.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-ideal-image/package.json b/packages/docusaurus-plugin-ideal-image/package.json index d124bb687d..80244aa619 100644 --- a/packages/docusaurus-plugin-ideal-image/package.json +++ b/packages/docusaurus-plugin-ideal-image/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-ideal-image", - "version": "3.8.0", + "version": "3.8.1", "description": "Docusaurus Plugin to generate an almost ideal image (responsive, lazy-loading, and low quality placeholder).", "main": "lib/index.js", "types": "src/plugin-ideal-image.d.ts", @@ -20,18 +20,18 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/lqip-loader": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/lqip-loader": "3.8.1", "@docusaurus/responsive-loader": "^1.7.0", - "@docusaurus/theme-translations": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/theme-translations": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "sharp": "^0.32.3", "tslib": "^2.6.0", "webpack": "^5.88.1" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.8.0", + "@docusaurus/module-type-aliases": "3.8.1", "fs-extra": "^11.1.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-pwa/package.json b/packages/docusaurus-plugin-pwa/package.json index 18428e3419..824070ac91 100644 --- a/packages/docusaurus-plugin-pwa/package.json +++ b/packages/docusaurus-plugin-pwa/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-pwa", - "version": "3.8.0", + "version": "3.8.1", "description": "Docusaurus Plugin to add PWA support.", "main": "lib/index.js", "types": "src/plugin-pwa.d.ts", @@ -22,14 +22,14 @@ "dependencies": { "@babel/core": "^7.25.9", "@babel/preset-env": "^7.25.9", - "@docusaurus/bundler": "3.8.0", - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/theme-translations": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/bundler": "3.8.1", + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/theme-translations": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "babel-loader": "^9.2.1", "clsx": "^2.0.0", "core-js": "^3.31.1", @@ -41,7 +41,7 @@ "workbox-window": "^7.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.8.0", + "@docusaurus/module-type-aliases": "3.8.1", "fs-extra": "^11.1.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-rsdoctor/package.json b/packages/docusaurus-plugin-rsdoctor/package.json index 258a22310f..49bb6ed894 100644 --- a/packages/docusaurus-plugin-rsdoctor/package.json +++ b/packages/docusaurus-plugin-rsdoctor/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-rsdoctor", - "version": "3.8.0", + "version": "3.8.1", "description": "Rsdoctor plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@rsdoctor/rspack-plugin": "^0.4.6", "@rsdoctor/webpack-plugin": "^0.4.6", "tslib": "^2.6.0" diff --git a/packages/docusaurus-plugin-sitemap/package.json b/packages/docusaurus-plugin-sitemap/package.json index f1a9d47a83..62cd1ceb1c 100644 --- a/packages/docusaurus-plugin-sitemap/package.json +++ b/packages/docusaurus-plugin-sitemap/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-sitemap", - "version": "3.8.0", + "version": "3.8.1", "description": "Simple sitemap generation plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,12 +18,12 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" diff --git a/packages/docusaurus-plugin-svgr/package.json b/packages/docusaurus-plugin-svgr/package.json index f03ef8a203..a395bbfc46 100644 --- a/packages/docusaurus-plugin-svgr/package.json +++ b/packages/docusaurus-plugin-svgr/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-svgr", - "version": "3.8.0", + "version": "3.8.1", "description": "SVGR plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,10 +18,10 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@svgr/core": "8.1.0", "@svgr/webpack": "^8.1.0", "tslib": "^2.6.0", diff --git a/packages/docusaurus-plugin-vercel-analytics/package.json b/packages/docusaurus-plugin-vercel-analytics/package.json index e4f79d490e..3cd3a72593 100644 --- a/packages/docusaurus-plugin-vercel-analytics/package.json +++ b/packages/docusaurus-plugin-vercel-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-vercel-analytics", - "version": "3.8.0", + "version": "3.8.1", "description": "Global vercel analytics plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,11 +18,11 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@vercel/analytics": "^1.1.1", "tslib": "^2.6.0" }, diff --git a/packages/docusaurus-preset-classic/package.json b/packages/docusaurus-preset-classic/package.json index ec05c998b7..0ce142ee55 100644 --- a/packages/docusaurus-preset-classic/package.json +++ b/packages/docusaurus-preset-classic/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/preset-classic", - "version": "3.8.0", + "version": "3.8.1", "description": "Classic preset for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,21 +18,21 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/plugin-content-blog": "3.8.0", - "@docusaurus/plugin-content-docs": "3.8.0", - "@docusaurus/plugin-content-pages": "3.8.0", - "@docusaurus/plugin-css-cascade-layers": "3.8.0", - "@docusaurus/plugin-debug": "3.8.0", - "@docusaurus/plugin-google-analytics": "3.8.0", - "@docusaurus/plugin-google-gtag": "3.8.0", - "@docusaurus/plugin-google-tag-manager": "3.8.0", - "@docusaurus/plugin-sitemap": "3.8.0", - "@docusaurus/plugin-svgr": "3.8.0", - "@docusaurus/theme-classic": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/theme-search-algolia": "3.8.0", - "@docusaurus/types": "3.8.0" + "@docusaurus/core": "3.8.1", + "@docusaurus/plugin-content-blog": "3.8.1", + "@docusaurus/plugin-content-docs": "3.8.1", + "@docusaurus/plugin-content-pages": "3.8.1", + "@docusaurus/plugin-css-cascade-layers": "3.8.1", + "@docusaurus/plugin-debug": "3.8.1", + "@docusaurus/plugin-google-analytics": "3.8.1", + "@docusaurus/plugin-google-gtag": "3.8.1", + "@docusaurus/plugin-google-tag-manager": "3.8.1", + "@docusaurus/plugin-sitemap": "3.8.1", + "@docusaurus/plugin-svgr": "3.8.1", + "@docusaurus/theme-classic": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/theme-search-algolia": "3.8.1", + "@docusaurus/types": "3.8.1" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", diff --git a/packages/docusaurus-remark-plugin-npm2yarn/package.json b/packages/docusaurus-remark-plugin-npm2yarn/package.json index 841626c50b..c8c62b2c2f 100644 --- a/packages/docusaurus-remark-plugin-npm2yarn/package.json +++ b/packages/docusaurus-remark-plugin-npm2yarn/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/remark-plugin-npm2yarn", - "version": "3.8.0", + "version": "3.8.1", "description": "Remark plugin for converting npm commands to Yarn commands as tabs.", "main": "lib/index.js", "publishConfig": { diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index 5868661866..1b76c00b8a 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-classic", - "version": "3.8.0", + "version": "3.8.1", "description": "Classic theme for Docusaurus", "main": "lib/index.js", "types": "src/theme-classic.d.ts", @@ -20,19 +20,19 @@ "copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch" }, "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/plugin-content-blog": "3.8.0", - "@docusaurus/plugin-content-docs": "3.8.0", - "@docusaurus/plugin-content-pages": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/theme-translations": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/plugin-content-blog": "3.8.1", + "@docusaurus/plugin-content-docs": "3.8.1", + "@docusaurus/plugin-content-pages": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/theme-translations": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "copy-text-to-clipboard": "^3.2.0", diff --git a/packages/docusaurus-theme-common/package.json b/packages/docusaurus-theme-common/package.json index d0cf8ed062..af0017380d 100644 --- a/packages/docusaurus-theme-common/package.json +++ b/packages/docusaurus-theme-common/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-common", - "version": "3.8.0", + "version": "3.8.1", "description": "Common code for Docusaurus themes.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -30,10 +30,10 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -44,8 +44,8 @@ "utility-types": "^3.10.0" }, "devDependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/types": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/types": "3.8.1", "fs-extra": "^11.1.1", "lodash": "^4.17.21" }, diff --git a/packages/docusaurus-theme-live-codeblock/package.json b/packages/docusaurus-theme-live-codeblock/package.json index 590d856307..696adb8180 100644 --- a/packages/docusaurus-theme-live-codeblock/package.json +++ b/packages/docusaurus-theme-live-codeblock/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-live-codeblock", - "version": "3.8.0", + "version": "3.8.1", "description": "Docusaurus live code block component.", "main": "lib/index.js", "types": "src/theme-live-codeblock.d.ts", @@ -23,10 +23,10 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/theme-translations": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/theme-translations": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "@philpl/buble": "^0.19.7", "clsx": "^2.0.0", "fs-extra": "^11.1.1", @@ -34,7 +34,7 @@ "tslib": "^2.6.0" }, "devDependencies": { - "@docusaurus/types": "3.8.0", + "@docusaurus/types": "3.8.1", "@types/buble": "^0.20.1" }, "peerDependencies": { diff --git a/packages/docusaurus-theme-mermaid/package.json b/packages/docusaurus-theme-mermaid/package.json index 93f50e7a1b..c97bc97f59 100644 --- a/packages/docusaurus-theme-mermaid/package.json +++ b/packages/docusaurus-theme-mermaid/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-mermaid", - "version": "3.8.0", + "version": "3.8.1", "description": "Mermaid components for Docusaurus.", "main": "lib/index.js", "types": "src/theme-mermaid.d.ts", @@ -33,11 +33,11 @@ "copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch" }, "dependencies": { - "@docusaurus/core": "3.8.0", - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "mermaid": ">=11.6.0", "tslib": "^2.6.0" }, diff --git a/packages/docusaurus-theme-search-algolia/package.json b/packages/docusaurus-theme-search-algolia/package.json index cd72ab17df..cd20a55108 100644 --- a/packages/docusaurus-theme-search-algolia/package.json +++ b/packages/docusaurus-theme-search-algolia/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-search-algolia", - "version": "3.8.0", + "version": "3.8.1", "description": "Algolia search component for Docusaurus.", "main": "lib/index.js", "sideEffects": [ @@ -34,13 +34,13 @@ }, "dependencies": { "@docsearch/react": "^3.9.0", - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/plugin-content-docs": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/theme-translations": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/plugin-content-docs": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/theme-translations": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "algoliasearch": "^5.17.1", "algoliasearch-helper": "^3.22.6", "clsx": "^2.0.0", @@ -51,7 +51,7 @@ "utility-types": "^3.10.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.8.0" + "@docusaurus/module-type-aliases": "3.8.1" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", diff --git a/packages/docusaurus-theme-translations/package.json b/packages/docusaurus-theme-translations/package.json index 5e75a3040f..dd6d77946d 100644 --- a/packages/docusaurus-theme-translations/package.json +++ b/packages/docusaurus-theme-translations/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-translations", - "version": "3.8.0", + "version": "3.8.1", "description": "Docusaurus theme translations.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -23,10 +23,10 @@ "tslib": "^2.6.0" }, "devDependencies": { - "@docusaurus/babel": "3.8.0", - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/utils": "3.8.0", + "@docusaurus/babel": "3.8.1", + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", "lodash": "^4.17.21" }, "engines": { diff --git a/packages/docusaurus-tsconfig/package.json b/packages/docusaurus-tsconfig/package.json index c7d6af9121..789859431d 100644 --- a/packages/docusaurus-tsconfig/package.json +++ b/packages/docusaurus-tsconfig/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/tsconfig", - "version": "3.8.0", + "version": "3.8.1", "description": "Docusaurus base TypeScript configuration.", "main": "tsconfig.json", "publishConfig": { diff --git a/packages/docusaurus-types/package.json b/packages/docusaurus-types/package.json index 35ea2f7cc8..db8872ca42 100644 --- a/packages/docusaurus-types/package.json +++ b/packages/docusaurus-types/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/types", - "version": "3.8.0", + "version": "3.8.1", "description": "Common types for Docusaurus packages.", "types": "./src/index.d.ts", "publishConfig": { diff --git a/packages/docusaurus-utils-common/package.json b/packages/docusaurus-utils-common/package.json index 4758a396da..a4d9b37692 100644 --- a/packages/docusaurus-utils-common/package.json +++ b/packages/docusaurus-utils-common/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/utils-common", - "version": "3.8.0", + "version": "3.8.1", "description": "Common (Node/Browser) utility functions for Docusaurus packages.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -19,7 +19,7 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/types": "3.8.0", + "@docusaurus/types": "3.8.1", "tslib": "^2.6.0" }, "engines": { diff --git a/packages/docusaurus-utils-validation/package.json b/packages/docusaurus-utils-validation/package.json index 3e5c908ba8..faa78bddb5 100644 --- a/packages/docusaurus-utils-validation/package.json +++ b/packages/docusaurus-utils-validation/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/utils-validation", - "version": "3.8.0", + "version": "3.8.1", "description": "Node validation utility functions for Docusaurus packages.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", + "@docusaurus/logger": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", "fs-extra": "^11.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", diff --git a/packages/docusaurus-utils/package.json b/packages/docusaurus-utils/package.json index 4ce3dc67d7..efcdce2b34 100644 --- a/packages/docusaurus-utils/package.json +++ b/packages/docusaurus-utils/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/utils", - "version": "3.8.0", + "version": "3.8.1", "description": "Node utility functions for Docusaurus packages.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.0", - "@docusaurus/types": "3.8.0", - "@docusaurus/utils-common": "3.8.0", + "@docusaurus/logger": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-common": "3.8.1", "escape-string-regexp": "^4.0.0", "execa": "5.1.1", "file-loader": "^6.2.0", diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index 04e6c32e2a..1f48d810b4 100644 --- a/packages/docusaurus/package.json +++ b/packages/docusaurus/package.json @@ -1,7 +1,7 @@ { "name": "@docusaurus/core", "description": "Easy to Maintain Open Source Documentation Websites", - "version": "3.8.0", + "version": "3.8.1", "license": "MIT", "publishConfig": { "access": "public" @@ -33,13 +33,13 @@ "url": "https://github.com/facebook/docusaurus/issues" }, "dependencies": { - "@docusaurus/babel": "3.8.0", - "@docusaurus/bundler": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/mdx-loader": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", - "@docusaurus/utils-validation": "3.8.0", + "@docusaurus/babel": "3.8.1", + "@docusaurus/bundler": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/mdx-loader": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", "boxen": "^6.2.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -77,8 +77,8 @@ "webpack-merge": "^6.0.1" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.8.0", - "@docusaurus/types": "3.8.0", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/types": "3.8.1", "@total-typescript/shoehorn": "^0.1.2", "@types/detect-port": "^1.3.3", "@types/react-dom": "^18.2.7", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index b39038375b..3a0548254a 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/eslint-plugin", - "version": "3.8.0", + "version": "3.8.1", "description": "ESLint plugin to enforce best Docusaurus practices.", "main": "lib/index.js", "keywords": [ diff --git a/packages/lqip-loader/package.json b/packages/lqip-loader/package.json index 2bdb3d6462..8f9fc307bd 100644 --- a/packages/lqip-loader/package.json +++ b/packages/lqip-loader/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/lqip-loader", - "version": "3.8.0", + "version": "3.8.1", "description": "Low Quality Image Placeholders (LQIP) loader for webpack.", "main": "lib/index.js", "publishConfig": { @@ -17,7 +17,7 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.0", + "@docusaurus/logger": "3.8.1", "file-loader": "^6.2.0", "lodash": "^4.17.21", "sharp": "^0.32.3", diff --git a/packages/stylelint-copyright/package.json b/packages/stylelint-copyright/package.json index 799076f72c..dfe3ef7603 100644 --- a/packages/stylelint-copyright/package.json +++ b/packages/stylelint-copyright/package.json @@ -1,6 +1,6 @@ { "name": "stylelint-copyright", - "version": "3.8.0", + "version": "3.8.1", "description": "Stylelint plugin to check CSS files for a copyright header.", "main": "lib/index.js", "license": "MIT", diff --git a/website/package.json b/website/package.json index 6d61086ce5..15fe623c78 100644 --- a/website/package.json +++ b/website/package.json @@ -1,6 +1,6 @@ { "name": "website", - "version": "3.8.0", + "version": "3.8.1", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -39,20 +39,20 @@ "dependencies": { "@crowdin/cli": "^3.13.0", "@crowdin/crowdin-api-client": "^1.29.5", - "@docusaurus/core": "3.8.0", - "@docusaurus/logger": "3.8.0", - "@docusaurus/plugin-client-redirects": "3.8.0", - "@docusaurus/plugin-ideal-image": "3.8.0", - "@docusaurus/plugin-pwa": "3.8.0", - "@docusaurus/plugin-rsdoctor": "3.8.0", - "@docusaurus/preset-classic": "3.8.0", - "@docusaurus/remark-plugin-npm2yarn": "3.8.0", - "@docusaurus/theme-classic": "3.8.0", - "@docusaurus/theme-common": "3.8.0", - "@docusaurus/theme-live-codeblock": "3.8.0", - "@docusaurus/theme-mermaid": "3.8.0", - "@docusaurus/utils": "3.8.0", - "@docusaurus/utils-common": "3.8.0", + "@docusaurus/core": "3.8.1", + "@docusaurus/logger": "3.8.1", + "@docusaurus/plugin-client-redirects": "3.8.1", + "@docusaurus/plugin-ideal-image": "3.8.1", + "@docusaurus/plugin-pwa": "3.8.1", + "@docusaurus/plugin-rsdoctor": "3.8.1", + "@docusaurus/preset-classic": "3.8.1", + "@docusaurus/remark-plugin-npm2yarn": "3.8.1", + "@docusaurus/theme-classic": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/theme-live-codeblock": "3.8.1", + "@docusaurus/theme-mermaid": "3.8.1", + "@docusaurus/utils": "3.8.1", + "@docusaurus/utils-common": "3.8.1", "clsx": "^2.0.0", "color": "^4.2.3", "fs-extra": "^11.1.1", @@ -83,8 +83,8 @@ ] }, "devDependencies": { - "@docusaurus/eslint-plugin": "3.8.0", - "@docusaurus/tsconfig": "3.8.0", + "@docusaurus/eslint-plugin": "3.8.1", + "@docusaurus/tsconfig": "3.8.1", "@types/color": "^3.0.4", "@types/jest": "^29.5.3", "cross-env": "^7.0.3", diff --git a/website/versioned_docs/version-3.8.0/advanced/architecture.mdx b/website/versioned_docs/version-3.8.1/advanced/architecture.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/advanced/architecture.mdx rename to website/versioned_docs/version-3.8.1/advanced/architecture.mdx diff --git a/website/versioned_docs/version-3.8.0/advanced/client.mdx b/website/versioned_docs/version-3.8.1/advanced/client.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/advanced/client.mdx rename to website/versioned_docs/version-3.8.1/advanced/client.mdx diff --git a/website/versioned_docs/version-3.8.0/advanced/index.mdx b/website/versioned_docs/version-3.8.1/advanced/index.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/advanced/index.mdx rename to website/versioned_docs/version-3.8.1/advanced/index.mdx diff --git a/website/versioned_docs/version-3.8.0/advanced/plugins.mdx b/website/versioned_docs/version-3.8.1/advanced/plugins.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/advanced/plugins.mdx rename to website/versioned_docs/version-3.8.1/advanced/plugins.mdx diff --git a/website/versioned_docs/version-3.8.0/advanced/routing.mdx b/website/versioned_docs/version-3.8.1/advanced/routing.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/advanced/routing.mdx rename to website/versioned_docs/version-3.8.1/advanced/routing.mdx diff --git a/website/versioned_docs/version-3.8.0/advanced/ssg.mdx b/website/versioned_docs/version-3.8.1/advanced/ssg.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/advanced/ssg.mdx rename to website/versioned_docs/version-3.8.1/advanced/ssg.mdx diff --git a/website/versioned_docs/version-3.8.0/api/docusaurus.config.js.mdx b/website/versioned_docs/version-3.8.1/api/docusaurus.config.js.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/docusaurus.config.js.mdx rename to website/versioned_docs/version-3.8.1/api/docusaurus.config.js.mdx diff --git a/website/versioned_docs/version-3.8.0/api/misc/_category_.yml b/website/versioned_docs/version-3.8.1/api/misc/_category_.yml similarity index 100% rename from website/versioned_docs/version-3.8.0/api/misc/_category_.yml rename to website/versioned_docs/version-3.8.1/api/misc/_category_.yml diff --git a/website/versioned_docs/version-3.8.0/api/misc/create-docusaurus.mdx b/website/versioned_docs/version-3.8.1/api/misc/create-docusaurus.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/misc/create-docusaurus.mdx rename to website/versioned_docs/version-3.8.1/api/misc/create-docusaurus.mdx diff --git a/website/versioned_docs/version-3.8.0/api/misc/eslint-plugin/README.mdx b/website/versioned_docs/version-3.8.1/api/misc/eslint-plugin/README.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/misc/eslint-plugin/README.mdx rename to website/versioned_docs/version-3.8.1/api/misc/eslint-plugin/README.mdx diff --git a/website/versioned_docs/version-3.8.0/api/misc/eslint-plugin/no-html-links.mdx b/website/versioned_docs/version-3.8.1/api/misc/eslint-plugin/no-html-links.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/misc/eslint-plugin/no-html-links.mdx rename to website/versioned_docs/version-3.8.1/api/misc/eslint-plugin/no-html-links.mdx diff --git a/website/versioned_docs/version-3.8.0/api/misc/eslint-plugin/no-untranslated-text.mdx b/website/versioned_docs/version-3.8.1/api/misc/eslint-plugin/no-untranslated-text.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/misc/eslint-plugin/no-untranslated-text.mdx rename to website/versioned_docs/version-3.8.1/api/misc/eslint-plugin/no-untranslated-text.mdx diff --git a/website/versioned_docs/version-3.8.0/api/misc/eslint-plugin/prefer-docusaurus-heading.mdx b/website/versioned_docs/version-3.8.1/api/misc/eslint-plugin/prefer-docusaurus-heading.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/misc/eslint-plugin/prefer-docusaurus-heading.mdx rename to website/versioned_docs/version-3.8.1/api/misc/eslint-plugin/prefer-docusaurus-heading.mdx diff --git a/website/versioned_docs/version-3.8.0/api/misc/eslint-plugin/string-literal-i18n-messages.mdx b/website/versioned_docs/version-3.8.1/api/misc/eslint-plugin/string-literal-i18n-messages.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/misc/eslint-plugin/string-literal-i18n-messages.mdx rename to website/versioned_docs/version-3.8.1/api/misc/eslint-plugin/string-literal-i18n-messages.mdx diff --git a/website/versioned_docs/version-3.8.0/api/misc/logger/demo.png b/website/versioned_docs/version-3.8.1/api/misc/logger/demo.png similarity index 100% rename from website/versioned_docs/version-3.8.0/api/misc/logger/demo.png rename to website/versioned_docs/version-3.8.1/api/misc/logger/demo.png diff --git a/website/versioned_docs/version-3.8.0/api/misc/logger/logger.mdx b/website/versioned_docs/version-3.8.1/api/misc/logger/logger.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/misc/logger/logger.mdx rename to website/versioned_docs/version-3.8.1/api/misc/logger/logger.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugin-methods/README.mdx b/website/versioned_docs/version-3.8.1/api/plugin-methods/README.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugin-methods/README.mdx rename to website/versioned_docs/version-3.8.1/api/plugin-methods/README.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugin-methods/_category_.yml b/website/versioned_docs/version-3.8.1/api/plugin-methods/_category_.yml similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugin-methods/_category_.yml rename to website/versioned_docs/version-3.8.1/api/plugin-methods/_category_.yml diff --git a/website/versioned_docs/version-3.8.0/api/plugin-methods/extend-infrastructure.mdx b/website/versioned_docs/version-3.8.1/api/plugin-methods/extend-infrastructure.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugin-methods/extend-infrastructure.mdx rename to website/versioned_docs/version-3.8.1/api/plugin-methods/extend-infrastructure.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugin-methods/i18n-lifecycles.mdx b/website/versioned_docs/version-3.8.1/api/plugin-methods/i18n-lifecycles.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugin-methods/i18n-lifecycles.mdx rename to website/versioned_docs/version-3.8.1/api/plugin-methods/i18n-lifecycles.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugin-methods/lifecycle-apis.mdx b/website/versioned_docs/version-3.8.1/api/plugin-methods/lifecycle-apis.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugin-methods/lifecycle-apis.mdx rename to website/versioned_docs/version-3.8.1/api/plugin-methods/lifecycle-apis.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugin-methods/static-methods.mdx b/website/versioned_docs/version-3.8.1/api/plugin-methods/static-methods.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugin-methods/static-methods.mdx rename to website/versioned_docs/version-3.8.1/api/plugin-methods/static-methods.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/_category_.yml b/website/versioned_docs/version-3.8.1/api/plugins/_category_.yml similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/_category_.yml rename to website/versioned_docs/version-3.8.1/api/plugins/_category_.yml diff --git a/website/versioned_docs/version-3.8.0/api/plugins/_partial-tags-file-api-ref-section.mdx b/website/versioned_docs/version-3.8.1/api/plugins/_partial-tags-file-api-ref-section.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/_partial-tags-file-api-ref-section.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/_partial-tags-file-api-ref-section.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/overview.mdx b/website/versioned_docs/version-3.8.1/api/plugins/overview.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/overview.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/overview.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-client-redirects.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-client-redirects.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-client-redirects.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-client-redirects.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-content-blog.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-content-blog.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-content-blog.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-content-blog.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-content-docs.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-content-docs.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-content-docs.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-content-docs.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-content-pages.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-content-pages.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-content-pages.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-content-pages.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-css-cascade-layers.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-css-cascade-layers.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-css-cascade-layers.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-css-cascade-layers.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-debug.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-debug.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-debug.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-debug.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-google-analytics.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-google-analytics.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-google-analytics.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-google-analytics.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-google-gtag.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-google-gtag.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-google-gtag.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-google-gtag.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-google-tag-manager.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-google-tag-manager.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-google-tag-manager.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-google-tag-manager.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-ideal-image.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-ideal-image.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-ideal-image.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-ideal-image.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-pwa.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-pwa.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-pwa.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-pwa.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-rsdoctor.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-rsdoctor.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-rsdoctor.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-rsdoctor.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-sitemap.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-sitemap.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-sitemap.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-sitemap.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-svgr.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-svgr.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-svgr.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-svgr.mdx diff --git a/website/versioned_docs/version-3.8.0/api/plugins/plugin-vercel-analytics.mdx b/website/versioned_docs/version-3.8.1/api/plugins/plugin-vercel-analytics.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/plugins/plugin-vercel-analytics.mdx rename to website/versioned_docs/version-3.8.1/api/plugins/plugin-vercel-analytics.mdx diff --git a/website/versioned_docs/version-3.8.0/api/themes/_category_.yml b/website/versioned_docs/version-3.8.1/api/themes/_category_.yml similarity index 100% rename from website/versioned_docs/version-3.8.0/api/themes/_category_.yml rename to website/versioned_docs/version-3.8.1/api/themes/_category_.yml diff --git a/website/versioned_docs/version-3.8.0/api/themes/overview.mdx b/website/versioned_docs/version-3.8.1/api/themes/overview.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/themes/overview.mdx rename to website/versioned_docs/version-3.8.1/api/themes/overview.mdx diff --git a/website/versioned_docs/version-3.8.0/api/themes/theme-classic.mdx b/website/versioned_docs/version-3.8.1/api/themes/theme-classic.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/themes/theme-classic.mdx rename to website/versioned_docs/version-3.8.1/api/themes/theme-classic.mdx diff --git a/website/versioned_docs/version-3.8.0/api/themes/theme-configuration.mdx b/website/versioned_docs/version-3.8.1/api/themes/theme-configuration.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/themes/theme-configuration.mdx rename to website/versioned_docs/version-3.8.1/api/themes/theme-configuration.mdx diff --git a/website/versioned_docs/version-3.8.0/api/themes/theme-live-codeblock.mdx b/website/versioned_docs/version-3.8.1/api/themes/theme-live-codeblock.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/themes/theme-live-codeblock.mdx rename to website/versioned_docs/version-3.8.1/api/themes/theme-live-codeblock.mdx diff --git a/website/versioned_docs/version-3.8.0/api/themes/theme-mermaid.mdx b/website/versioned_docs/version-3.8.1/api/themes/theme-mermaid.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/themes/theme-mermaid.mdx rename to website/versioned_docs/version-3.8.1/api/themes/theme-mermaid.mdx diff --git a/website/versioned_docs/version-3.8.0/api/themes/theme-search-algolia.mdx b/website/versioned_docs/version-3.8.1/api/themes/theme-search-algolia.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/api/themes/theme-search-algolia.mdx rename to website/versioned_docs/version-3.8.1/api/themes/theme-search-algolia.mdx diff --git a/website/versioned_docs/version-3.8.0/assets/docusaurus-asset-example-banner.png b/website/versioned_docs/version-3.8.1/assets/docusaurus-asset-example-banner.png similarity index 100% rename from website/versioned_docs/version-3.8.0/assets/docusaurus-asset-example-banner.png rename to website/versioned_docs/version-3.8.1/assets/docusaurus-asset-example-banner.png diff --git a/website/versioned_docs/version-3.8.0/assets/docusaurus-asset-example.docx b/website/versioned_docs/version-3.8.1/assets/docusaurus-asset-example.docx similarity index 100% rename from website/versioned_docs/version-3.8.0/assets/docusaurus-asset-example.docx rename to website/versioned_docs/version-3.8.1/assets/docusaurus-asset-example.docx diff --git a/website/versioned_docs/version-3.8.0/assets/docusaurus-asset-example.xyz b/website/versioned_docs/version-3.8.1/assets/docusaurus-asset-example.xyz similarity index 100% rename from website/versioned_docs/version-3.8.0/assets/docusaurus-asset-example.xyz rename to website/versioned_docs/version-3.8.1/assets/docusaurus-asset-example.xyz diff --git a/website/versioned_docs/version-3.8.0/blog.mdx b/website/versioned_docs/version-3.8.1/blog.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/blog.mdx rename to website/versioned_docs/version-3.8.1/blog.mdx diff --git a/website/versioned_docs/version-3.8.0/browser-support.mdx b/website/versioned_docs/version-3.8.1/browser-support.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/browser-support.mdx rename to website/versioned_docs/version-3.8.1/browser-support.mdx diff --git a/website/versioned_docs/version-3.8.0/cli.mdx b/website/versioned_docs/version-3.8.1/cli.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/cli.mdx rename to website/versioned_docs/version-3.8.1/cli.mdx diff --git a/website/versioned_docs/version-3.8.0/configuration.mdx b/website/versioned_docs/version-3.8.1/configuration.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/configuration.mdx rename to website/versioned_docs/version-3.8.1/configuration.mdx diff --git a/website/versioned_docs/version-3.8.0/deployment.mdx b/website/versioned_docs/version-3.8.1/deployment.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/deployment.mdx rename to website/versioned_docs/version-3.8.1/deployment.mdx diff --git a/website/versioned_docs/version-3.8.0/docusaurus-core.mdx b/website/versioned_docs/version-3.8.1/docusaurus-core.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/docusaurus-core.mdx rename to website/versioned_docs/version-3.8.1/docusaurus-core.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/creating-pages.mdx b/website/versioned_docs/version-3.8.1/guides/creating-pages.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/creating-pages.mdx rename to website/versioned_docs/version-3.8.1/guides/creating-pages.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/docs/docs-create-doc.mdx b/website/versioned_docs/version-3.8.1/guides/docs/docs-create-doc.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/docs/docs-create-doc.mdx rename to website/versioned_docs/version-3.8.1/guides/docs/docs-create-doc.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/docs/docs-introduction.mdx b/website/versioned_docs/version-3.8.1/guides/docs/docs-introduction.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/docs/docs-introduction.mdx rename to website/versioned_docs/version-3.8.1/guides/docs/docs-introduction.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/docs/docs-multi-instance.mdx b/website/versioned_docs/version-3.8.1/guides/docs/docs-multi-instance.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/docs/docs-multi-instance.mdx rename to website/versioned_docs/version-3.8.1/guides/docs/docs-multi-instance.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/docs/sidebar/autogenerated.mdx b/website/versioned_docs/version-3.8.1/guides/docs/sidebar/autogenerated.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/docs/sidebar/autogenerated.mdx rename to website/versioned_docs/version-3.8.1/guides/docs/sidebar/autogenerated.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/docs/sidebar/index.mdx b/website/versioned_docs/version-3.8.1/guides/docs/sidebar/index.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/docs/sidebar/index.mdx rename to website/versioned_docs/version-3.8.1/guides/docs/sidebar/index.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/docs/sidebar/items.mdx b/website/versioned_docs/version-3.8.1/guides/docs/sidebar/items.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/docs/sidebar/items.mdx rename to website/versioned_docs/version-3.8.1/guides/docs/sidebar/items.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/docs/sidebar/multiple-sidebars.mdx b/website/versioned_docs/version-3.8.1/guides/docs/sidebar/multiple-sidebars.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/docs/sidebar/multiple-sidebars.mdx rename to website/versioned_docs/version-3.8.1/guides/docs/sidebar/multiple-sidebars.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/docs/versioning.mdx b/website/versioned_docs/version-3.8.1/guides/docs/versioning.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/docs/versioning.mdx rename to website/versioned_docs/version-3.8.1/guides/docs/versioning.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/_markdown-partial-example.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/_markdown-partial-example.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/_markdown-partial-example.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/_markdown-partial-example.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-admonitions.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-admonitions.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-admonitions.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-admonitions.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-assets.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-assets.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-assets.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-assets.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-code-blocks.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-code-blocks.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-code-blocks.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-code-blocks.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-diagrams.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-diagrams.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-diagrams.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-diagrams.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-head-metadata.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-head-metadata.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-head-metadata.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-head-metadata.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-intro.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-intro.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-intro.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-intro.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-links.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-links.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-links.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-links.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-math-equations.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-math-equations.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-math-equations.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-math-equations.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-plugins.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-plugins.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-plugins.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-plugins.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-react.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-react.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-react.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-react.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-react.module.css b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-react.module.css similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-react.module.css rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-react.module.css diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-tabs-styles.module.css b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-tabs-styles.module.css similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-tabs-styles.module.css rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-tabs-styles.module.css diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-tabs.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-tabs.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-tabs.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-tabs.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-toc.mdx b/website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-toc.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/markdown-features/markdown-features-toc.mdx rename to website/versioned_docs/version-3.8.1/guides/markdown-features/markdown-features-toc.mdx diff --git a/website/versioned_docs/version-3.8.0/guides/whats-next.mdx b/website/versioned_docs/version-3.8.1/guides/whats-next.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/guides/whats-next.mdx rename to website/versioned_docs/version-3.8.1/guides/whats-next.mdx diff --git a/website/versioned_docs/version-3.8.0/i18n/i18n-crowdin.mdx b/website/versioned_docs/version-3.8.1/i18n/i18n-crowdin.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/i18n/i18n-crowdin.mdx rename to website/versioned_docs/version-3.8.1/i18n/i18n-crowdin.mdx diff --git a/website/versioned_docs/version-3.8.0/i18n/i18n-git.mdx b/website/versioned_docs/version-3.8.1/i18n/i18n-git.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/i18n/i18n-git.mdx rename to website/versioned_docs/version-3.8.1/i18n/i18n-git.mdx diff --git a/website/versioned_docs/version-3.8.0/i18n/i18n-introduction.mdx b/website/versioned_docs/version-3.8.1/i18n/i18n-introduction.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/i18n/i18n-introduction.mdx rename to website/versioned_docs/version-3.8.1/i18n/i18n-introduction.mdx diff --git a/website/versioned_docs/version-3.8.0/i18n/i18n-tutorial.mdx b/website/versioned_docs/version-3.8.1/i18n/i18n-tutorial.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/i18n/i18n-tutorial.mdx rename to website/versioned_docs/version-3.8.1/i18n/i18n-tutorial.mdx diff --git a/website/versioned_docs/version-3.8.0/installation.mdx b/website/versioned_docs/version-3.8.1/installation.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/installation.mdx rename to website/versioned_docs/version-3.8.1/installation.mdx diff --git a/website/versioned_docs/version-3.8.0/introduction.mdx b/website/versioned_docs/version-3.8.1/introduction.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/introduction.mdx rename to website/versioned_docs/version-3.8.1/introduction.mdx diff --git a/website/versioned_docs/version-3.8.0/migration/index.mdx b/website/versioned_docs/version-3.8.1/migration/index.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/migration/index.mdx rename to website/versioned_docs/version-3.8.1/migration/index.mdx diff --git a/website/versioned_docs/version-3.8.0/migration/v2/migration-automated.mdx b/website/versioned_docs/version-3.8.1/migration/v2/migration-automated.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/migration/v2/migration-automated.mdx rename to website/versioned_docs/version-3.8.1/migration/v2/migration-automated.mdx diff --git a/website/versioned_docs/version-3.8.0/migration/v2/migration-manual.mdx b/website/versioned_docs/version-3.8.1/migration/v2/migration-manual.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/migration/v2/migration-manual.mdx rename to website/versioned_docs/version-3.8.1/migration/v2/migration-manual.mdx diff --git a/website/versioned_docs/version-3.8.0/migration/v2/migration-overview.mdx b/website/versioned_docs/version-3.8.1/migration/v2/migration-overview.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/migration/v2/migration-overview.mdx rename to website/versioned_docs/version-3.8.1/migration/v2/migration-overview.mdx diff --git a/website/versioned_docs/version-3.8.0/migration/v2/migration-translated-sites.mdx b/website/versioned_docs/version-3.8.1/migration/v2/migration-translated-sites.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/migration/v2/migration-translated-sites.mdx rename to website/versioned_docs/version-3.8.1/migration/v2/migration-translated-sites.mdx diff --git a/website/versioned_docs/version-3.8.0/migration/v2/migration-versioned-sites.mdx b/website/versioned_docs/version-3.8.1/migration/v2/migration-versioned-sites.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/migration/v2/migration-versioned-sites.mdx rename to website/versioned_docs/version-3.8.1/migration/v2/migration-versioned-sites.mdx diff --git a/website/versioned_docs/version-3.8.0/migration/v3.mdx b/website/versioned_docs/version-3.8.1/migration/v3.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/migration/v3.mdx rename to website/versioned_docs/version-3.8.1/migration/v3.mdx diff --git a/website/versioned_docs/version-3.8.0/playground.mdx b/website/versioned_docs/version-3.8.1/playground.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/playground.mdx rename to website/versioned_docs/version-3.8.1/playground.mdx diff --git a/website/versioned_docs/version-3.8.0/search.mdx b/website/versioned_docs/version-3.8.1/search.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/search.mdx rename to website/versioned_docs/version-3.8.1/search.mdx diff --git a/website/versioned_docs/version-3.8.0/seo.mdx b/website/versioned_docs/version-3.8.1/seo.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/seo.mdx rename to website/versioned_docs/version-3.8.1/seo.mdx diff --git a/website/versioned_docs/version-3.8.0/static-assets.mdx b/website/versioned_docs/version-3.8.1/static-assets.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/static-assets.mdx rename to website/versioned_docs/version-3.8.1/static-assets.mdx diff --git a/website/versioned_docs/version-3.8.0/styling-layout.mdx b/website/versioned_docs/version-3.8.1/styling-layout.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/styling-layout.mdx rename to website/versioned_docs/version-3.8.1/styling-layout.mdx diff --git a/website/versioned_docs/version-3.8.0/swizzling.mdx b/website/versioned_docs/version-3.8.1/swizzling.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/swizzling.mdx rename to website/versioned_docs/version-3.8.1/swizzling.mdx diff --git a/website/versioned_docs/version-3.8.0/typescript-support.mdx b/website/versioned_docs/version-3.8.1/typescript-support.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/typescript-support.mdx rename to website/versioned_docs/version-3.8.1/typescript-support.mdx diff --git a/website/versioned_docs/version-3.8.0/using-plugins.mdx b/website/versioned_docs/version-3.8.1/using-plugins.mdx similarity index 100% rename from website/versioned_docs/version-3.8.0/using-plugins.mdx rename to website/versioned_docs/version-3.8.1/using-plugins.mdx diff --git a/website/versioned_sidebars/version-3.8.0-sidebars.json b/website/versioned_sidebars/version-3.8.1-sidebars.json similarity index 100% rename from website/versioned_sidebars/version-3.8.0-sidebars.json rename to website/versioned_sidebars/version-3.8.1-sidebars.json diff --git a/website/versions.json b/website/versions.json index 1695a2881a..01054bc8c7 100644 --- a/website/versions.json +++ b/website/versions.json @@ -1,5 +1,5 @@ [ - "3.8.0", + "3.8.1", "3.7.0", "3.6.3", "3.5.2", From b54103be5dbe000c40b0ed957aa1d976c78d7d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 6 Jun 2025 20:12:44 +0200 Subject: [PATCH 012/103] fix(docs): prevent docs ids conflicts within a version (#11251) --- .../docs/hello.md | 0 .../frontMatter/deeply/doc.md | 4 + .../frontMatter/deeply/nested/whatever.md | 7 + .../frontMatter/doc.md | 7 + .../frontMatter/doc1.md | 7 + .../frontMatter/doc2.md | 7 + .../number-prefix/1-doc.md | 3 + .../number-prefix/2-doc.md | 7 + .../number-prefix/deeply/1-doc.md | 3 + .../number-prefix/deeply/nested/2-doc.md | 3 + .../number-prefix/deeply/nested/3-doc.md | 3 + .../distinct-frontMatter-id/1-doc.md | 7 + .../distinct-frontMatter-id/2-doc.md | 7 + .../distinct-frontMatter-id/3-doc.md | 7 + .../site-broken-versions/versions.json | 3 + .../__fixtures__/site-minimal/docs/hello.md | 4 + .../__snapshots__/loadVersion.test.ts.snap | 6 +- .../versions/__tests__/loadVersion.test.ts | 128 +++++++---- .../src/versions/loadVersion.ts | 213 +++++++++++------- .../tests/Conflicts/file-name/1-file-name.mdx | 8 + .../tests/Conflicts/file-name/2-file-name.mdx | 8 + .../tests/Conflicts/file-name/_category_.json | 8 + 22 files changed, 323 insertions(+), 127 deletions(-) rename packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/{minimal-site => site-broken-versions}/docs/hello.md (100%) create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/deeply/doc.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/deeply/nested/whatever.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/doc.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/doc1.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/doc2.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/1-doc.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/2-doc.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/deeply/1-doc.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/deeply/nested/2-doc.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/deeply/nested/3-doc.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/distinct-frontMatter-id/1-doc.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/distinct-frontMatter-id/2-doc.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/distinct-frontMatter-id/3-doc.md create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versions.json create mode 100644 packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-minimal/docs/hello.md create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/file-name/1-file-name.mdx create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/file-name/2-file-name.mdx create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/file-name/_category_.json diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs/hello.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/docs/hello.md similarity index 100% rename from packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs/hello.md rename to packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/docs/hello.md diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/deeply/doc.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/deeply/doc.md new file mode 100644 index 0000000000..aef67b7c25 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/deeply/doc.md @@ -0,0 +1,4 @@ + +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/deeply/nested/whatever.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/deeply/nested/whatever.md new file mode 100644 index 0000000000..a6c896690d --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/deeply/nested/whatever.md @@ -0,0 +1,7 @@ +--- +id: doc +--- + +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/doc.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/doc.md new file mode 100644 index 0000000000..1c4d37fc55 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/doc.md @@ -0,0 +1,7 @@ +--- +# no id but should conflict due to the name anyway +--- + +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/doc1.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/doc1.md new file mode 100644 index 0000000000..a6c896690d --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/doc1.md @@ -0,0 +1,7 @@ +--- +id: doc +--- + +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/doc2.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/doc2.md new file mode 100644 index 0000000000..a6c896690d --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/frontMatter/doc2.md @@ -0,0 +1,7 @@ +--- +id: doc +--- + +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/1-doc.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/1-doc.md new file mode 100644 index 0000000000..1375fc8645 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/1-doc.md @@ -0,0 +1,3 @@ +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/2-doc.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/2-doc.md new file mode 100644 index 0000000000..a6c896690d --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/2-doc.md @@ -0,0 +1,7 @@ +--- +id: doc +--- + +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/deeply/1-doc.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/deeply/1-doc.md new file mode 100644 index 0000000000..1375fc8645 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/deeply/1-doc.md @@ -0,0 +1,3 @@ +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/deeply/nested/2-doc.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/deeply/nested/2-doc.md new file mode 100644 index 0000000000..1375fc8645 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/deeply/nested/2-doc.md @@ -0,0 +1,3 @@ +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/deeply/nested/3-doc.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/deeply/nested/3-doc.md new file mode 100644 index 0000000000..1375fc8645 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/deeply/nested/3-doc.md @@ -0,0 +1,3 @@ +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/distinct-frontMatter-id/1-doc.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/distinct-frontMatter-id/1-doc.md new file mode 100644 index 0000000000..82e7dd9449 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/distinct-frontMatter-id/1-doc.md @@ -0,0 +1,7 @@ +--- +id: doc-1 +--- + +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/distinct-frontMatter-id/2-doc.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/distinct-frontMatter-id/2-doc.md new file mode 100644 index 0000000000..1893441ee5 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/distinct-frontMatter-id/2-doc.md @@ -0,0 +1,7 @@ +--- +id: doc-2 +--- + +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/distinct-frontMatter-id/3-doc.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/distinct-frontMatter-id/3-doc.md new file mode 100644 index 0000000000..e2ec5ef2bb --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versioned_docs/version-with-id-conflicts/number-prefix/distinct-frontMatter-id/3-doc.md @@ -0,0 +1,7 @@ +--- +id: doc-3 +--- + +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versions.json b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versions.json new file mode 100644 index 0000000000..bd6349302e --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-broken-versions/versions.json @@ -0,0 +1,3 @@ +[ + "with-id-conflicts" +] diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-minimal/docs/hello.md b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-minimal/docs/hello.md new file mode 100644 index 0000000000..aef67b7c25 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-minimal/docs/hello.md @@ -0,0 +1,4 @@ + +# Hello + +World \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__snapshots__/loadVersion.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__snapshots__/loadVersion.test.ts.snap index 3dde6cbe1a..d8a41ee5cf 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__snapshots__/loadVersion.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__snapshots__/loadVersion.test.ts.snap @@ -1,12 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`minimal site can load current version 1`] = ` +exports[`loadVersion minimal site can load current version 1`] = ` { "badge": false, "banner": null, "className": "docs-version-current", - "contentPath": "/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/docs", - "contentPathLocalized": "/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/minimal-site/i18n/en/docusaurus-plugin-content-docs/current", + "contentPath": "/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-minimal/docs", + "contentPathLocalized": "/packages/docusaurus-plugin-content-docs/src/versions/__tests__/__fixtures__/site-minimal/i18n/en/docusaurus-plugin-content-docs/current", "docs": [ { "description": "World", diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts index 3e9b6d585f..a4329f7a5c 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts @@ -22,52 +22,96 @@ const DefaultI18N: I18n = { localeConfigs: {}, }; -describe('minimal site', () => { - async function loadSite() { - const siteDir = path.resolve( - path.join(__dirname, './__fixtures__', 'minimal-site'), - ); - const options: PluginOptions = fromPartial({ - ...DEFAULT_OPTIONS, - }); - const context = fromPartial({ - siteDir, - baseUrl: '/', - i18n: DefaultI18N, - localizationDir: path.join(siteDir, 'i18n/en'), - siteConfig: { - markdown: { - parseFrontMatter: DEFAULT_PARSE_FRONT_MATTER, - }, +async function siteFixture(fixture: string) { + const siteDir = path.resolve(path.join(__dirname, './__fixtures__', fixture)); + const options: PluginOptions = fromPartial({ + id: 'default', + ...DEFAULT_OPTIONS, + }); + const context = fromPartial({ + siteDir, + baseUrl: '/', + i18n: DefaultI18N, + localizationDir: path.join(siteDir, 'i18n/en'), + siteConfig: { + markdown: { + parseFrontMatter: DEFAULT_PARSE_FRONT_MATTER, }, + }, + }); + + const versions = await readVersionsMetadata({ + options, + context, + }); + + return { + siteDir, + options, + context, + versions, + }; +} + +describe('loadVersion', () => { + describe('minimal site', () => { + it('can load current version', async () => { + const {options, context, versions} = await siteFixture('site-minimal'); + + const version = versions[0]; + expect(version).toBeDefined(); + expect(version.versionName).toBe('current'); + + const loadedVersion = loadVersion({ + context, + options, + versionMetadata: version, + env: 'production', + }); + + await expect(loadedVersion).resolves.toMatchSnapshot(); }); - return { - siteDir, - options, - context, - }; - } + }); - it('can load current version', async () => { - const {options, context} = await loadSite(); + describe('site with broken versions', () => { + async function loadTestVersion(versionName: string) { + const {options, context, versions} = await siteFixture( + 'site-broken-versions', + ); + const version = versions.find((v) => v.versionName === versionName); + if (!version) { + throw new Error(`Version '${versionName}' should exist`); + } + return loadVersion({ + context, + options, + versionMetadata: version, + env: 'production', + }); + } - const versionsMetadata = await readVersionsMetadata({ - options, - context, + it('rejects version with doc id conflict', async () => { + await expect(() => loadTestVersion('with-id-conflicts')).rejects + .toThrowErrorMatchingInlineSnapshot(` + "The docs plugin found docs sharing the same id: + + - \`frontMatter/doc\` found in 3 docs: + - versioned_docs/version-with-id-conflicts/frontMatter/doc.md + - versioned_docs/version-with-id-conflicts/frontMatter/doc1.md + - versioned_docs/version-with-id-conflicts/frontMatter/doc2.md + + - \`number-prefix/doc\` found in 2 docs: + - versioned_docs/version-with-id-conflicts/number-prefix/1-doc.md + - versioned_docs/version-with-id-conflicts/number-prefix/2-doc.md + + - \`number-prefix/deeply/nested/doc\` found in 2 docs: + - versioned_docs/version-with-id-conflicts/number-prefix/deeply/nested/2-doc.md + - versioned_docs/version-with-id-conflicts/number-prefix/deeply/nested/3-doc.md + + Docs should have distinct ids. + In case of conflict, you can rename the docs file, or use the \`id\` front matter to assign an explicit distinct id to each doc. + " + `); }); - - expect(versionsMetadata).toHaveLength(1); - expect(versionsMetadata[0]!.versionName).toBe('current'); - - const versionMetadata = versionsMetadata[0]!; - - const loadedVersion = loadVersion({ - context, - options, - versionMetadata, - env: 'production', - }); - - await expect(loadedVersion).resolves.toMatchSnapshot(); }); }); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts b/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts index 837bb0250c..061f2d53ad 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts @@ -7,7 +7,7 @@ import path from 'path'; import _ from 'lodash'; -import {createSlugger} from '@docusaurus/utils'; +import {aliasedSitePathToRelativePath, createSlugger} from '@docusaurus/utils'; import {getTagsFile} from '@docusaurus/utils-validation'; import logger from '@docusaurus/logger'; import { @@ -29,102 +29,151 @@ import type { import type {DocFile} from '../types'; import type {LoadContext} from '@docusaurus/types'; -export async function loadVersion({ - context, - options, - versionMetadata, - env, -}: { +type LoadVersionParams = { context: LoadContext; options: PluginOptions; versionMetadata: VersionMetadata; env: DocEnv; -}): Promise { - const {siteDir} = context; +}; - async function loadVersionDocsBase( - tagsFile: TagsFile | null, - ): Promise { - const docFiles = await readVersionDocs(versionMetadata, options); - if (docFiles.length === 0) { - throw new Error( - `Docs version "${ - versionMetadata.versionName - }" has no docs! At least one doc should exist at "${path.relative( - siteDir, - versionMetadata.contentPath, - )}".`, - ); - } - function processVersionDoc(docFile: DocFile) { - return processDocMetadata({ - docFile, - versionMetadata, - context, - options, - env, - tagsFile, - }); - } - return Promise.all(docFiles.map(processVersionDoc)); +function ensureNoDuplicateDocId(docs: DocMetadataBase[]): void { + const duplicatesById = _.chain(docs) + .groupBy((d) => d.id) + .pickBy((group) => group.length > 1) + .value(); + + const duplicateIdEntries = Object.entries(duplicatesById); + + if (duplicateIdEntries.length) { + const idMessages = duplicateIdEntries + .map(([id, duplicateDocs]) => { + return logger.interpolate`- code=${id} found in number=${ + duplicateDocs.length + } docs: + - ${duplicateDocs + .map((d) => aliasedSitePathToRelativePath(d.source)) + .join('\n - ')}`; + }) + .join('\n\n'); + + const message = `The docs plugin found docs sharing the same id: +\n${idMessages}\n +Docs should have distinct ids. +In case of conflict, you can rename the docs file, or use the ${logger.code( + 'id', + )} front matter to assign an explicit distinct id to each doc. + `; + + throw new Error(message); } +} - async function doLoadVersion(): Promise { - const tagsFile = await getTagsFile({ - contentPaths: versionMetadata, - tags: options.tags, +async function loadVersionDocsBase({ + tagsFile, + context, + options, + versionMetadata, + env, +}: LoadVersionParams & { + tagsFile: TagsFile | null; +}): Promise { + const docFiles = await readVersionDocs(versionMetadata, options); + if (docFiles.length === 0) { + throw new Error( + `Docs version "${ + versionMetadata.versionName + }" has no docs! At least one doc should exist at "${path.relative( + context.siteDir, + versionMetadata.contentPath, + )}".`, + ); + } + function processVersionDoc(docFile: DocFile) { + return processDocMetadata({ + docFile, + versionMetadata, + context, + options, + env, + tagsFile, }); + } + const docs = await Promise.all(docFiles.map(processVersionDoc)); + ensureNoDuplicateDocId(docs); + return docs; +} - const docsBase: DocMetadataBase[] = await loadVersionDocsBase(tagsFile); +async function doLoadVersion({ + context, + options, + versionMetadata, + env, +}: LoadVersionParams): Promise { + const tagsFile = await getTagsFile({ + contentPaths: versionMetadata, + tags: options.tags, + }); - // TODO we only ever need draftIds in further code, not full draft items - // To simplify and prevent mistakes, avoid exposing draft - // replace draft=>draftIds in content loaded - const [drafts, docs] = _.partition(docsBase, (doc) => doc.draft); + const docsBase: DocMetadataBase[] = await loadVersionDocsBase({ + tagsFile, + context, + options, + versionMetadata, + env, + }); - const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, { - sidebarItemsGenerator: options.sidebarItemsGenerator, - numberPrefixParser: options.numberPrefixParser, + // TODO we only ever need draftIds in further code, not full draft items + // To simplify and prevent mistakes, avoid exposing draft + // replace draft=>draftIds in content loaded + const [drafts, docs] = _.partition(docsBase, (doc) => doc.draft); + + const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, { + sidebarItemsGenerator: options.sidebarItemsGenerator, + numberPrefixParser: options.numberPrefixParser, + docs, + drafts, + version: versionMetadata, + sidebarOptions: { + sidebarCollapsed: options.sidebarCollapsed, + sidebarCollapsible: options.sidebarCollapsible, + }, + categoryLabelSlugger: createSlugger(), + }); + + const sidebarsUtils = createSidebarsUtils(sidebars); + + const docsById = createDocsByIdIndex(docs); + const allDocIds = Object.keys(docsById); + + sidebarsUtils.checkLegacyVersionedSidebarNames({ + sidebarFilePath: versionMetadata.sidebarFilePath as string, + versionMetadata, + }); + sidebarsUtils.checkSidebarsDocIds({ + allDocIds, + sidebarFilePath: versionMetadata.sidebarFilePath as string, + versionMetadata, + }); + + return { + ...versionMetadata, + docs: addDocNavigation({ docs, - drafts, - version: versionMetadata, - sidebarOptions: { - sidebarCollapsed: options.sidebarCollapsed, - sidebarCollapsible: options.sidebarCollapsible, - }, - categoryLabelSlugger: createSlugger(), - }); - - const sidebarsUtils = createSidebarsUtils(sidebars); - - const docsById = createDocsByIdIndex(docs); - const allDocIds = Object.keys(docsById); - - sidebarsUtils.checkLegacyVersionedSidebarNames({ - sidebarFilePath: versionMetadata.sidebarFilePath as string, - versionMetadata, - }); - sidebarsUtils.checkSidebarsDocIds({ - allDocIds, - sidebarFilePath: versionMetadata.sidebarFilePath as string, - versionMetadata, - }); - - return { - ...versionMetadata, - docs: addDocNavigation({ - docs, - sidebarsUtils, - }), - drafts, - sidebars, - }; - } + sidebarsUtils, + }), + drafts, + sidebars, + }; +} +export async function loadVersion( + params: LoadVersionParams, +): Promise { try { - return await doLoadVersion(); + return await doLoadVersion(params); } catch (err) { - logger.error`Loading of version failed for version name=${versionMetadata.versionName}`; + // TODO use error cause (but need to refactor many tests) + logger.error`Loading of version failed for version name=${params.versionMetadata.versionName}`; throw err; } } diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/file-name/1-file-name.mdx b/website/_dogfooding/_docs tests/tests/Conflicts/file-name/1-file-name.mdx new file mode 100644 index 0000000000..b9c1d64ac8 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/file-name/1-file-name.mdx @@ -0,0 +1,8 @@ +--- +id: file-name-1 +slug: file-name-1 +--- + +# File name 1 + +File name 1 diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/file-name/2-file-name.mdx b/website/_dogfooding/_docs tests/tests/Conflicts/file-name/2-file-name.mdx new file mode 100644 index 0000000000..4f3a3fb7dc --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/file-name/2-file-name.mdx @@ -0,0 +1,8 @@ +--- +id: file-name-2 +slug: file-name-2 +--- + +# File name 2 + +File name 2 diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/file-name/_category_.json b/website/_dogfooding/_docs tests/tests/Conflicts/file-name/_category_.json new file mode 100644 index 0000000000..8ccbef7d18 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/file-name/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "File name conflict", + "link": { + "type": "generated-index", + "title": "File name conflict", + "description": "Testing what happens when 2 files have the same name but different position prefixes" + } +} From a392c33b8e424f3677f55b796e45e7f4caa78368 Mon Sep 17 00:00:00 2001 From: Riccardo Date: Fri, 13 Jun 2025 11:38:48 +0200 Subject: [PATCH 013/103] docs: fix announcement bar css selector (#11262) --- website/src/css/custom.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/css/custom.css b/website/src/css/custom.css index a731fb1a04..cd3463e760 100644 --- a/website/src/css/custom.css +++ b/website/src/css/custom.css @@ -143,7 +143,7 @@ html[data-theme='dark'] { ); } -div[class^='announcementBar_'] { +.theme-announcement-bar { font-size: 20px; /* From 6cb955987e510e3b98250d3841a94fee2b229ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 13 Jun 2025 18:49:28 +0200 Subject: [PATCH 014/103] fix(theme): make `useHistorySelector()` hydration-safe + use it read search/hash in theme (#11263) --- argos/tests/screenshot.spec.ts | 5 ----- .../NavbarItem/DocsVersionDropdownNavbarItem.tsx | 5 +++-- .../NavbarItem/LocaleDropdownNavbarItem/index.tsx | 5 +++-- .../src/utils/historyUtils.ts | 13 ++++++++++++- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/argos/tests/screenshot.spec.ts b/argos/tests/screenshot.spec.ts index d515fc0f33..9ceaf5ad8c 100644 --- a/argos/tests/screenshot.spec.ts +++ b/argos/tests/screenshot.spec.ts @@ -134,11 +134,6 @@ function throwOnConsole(page: Page) { // it's already happening in main branch 'Failed to load resource: the server responded with a status of 404 (Not Found)', - // TODO legit hydration bugs to fix on embeds of /docs/styling-layout - // useLocation() returns window.search/hash immediately :s - '/docs/configuration?docusaurus-theme=light', - '/docs/configuration?docusaurus-theme=dark', - // Warning because react-live not supporting React automatic JSX runtime // See https://github.com/FormidableLabs/react-live/issues/405 'Your app (or one of its dependencies) is using an outdated JSX transform. Update to the modern JSX transform for faster performance', diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx index 1e2d0bbf7a..fdd28ebc25 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx @@ -13,7 +13,7 @@ import { useDocsPreferredVersion, } from '@docusaurus/plugin-content-docs/client'; import {translate} from '@docusaurus/Translate'; -import {useLocation} from '@docusaurus/router'; +import {useHistorySelector} from '@docusaurus/theme-common'; import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem'; import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem'; import type { @@ -119,7 +119,8 @@ export default function DocsVersionDropdownNavbarItem({ versions: configs, ...props }: Props): ReactNode { - const {search, hash} = useLocation(); + const search = useHistorySelector((history) => history.location.search); + const hash = useHistorySelector((history) => history.location.hash); const activeDocContext = useActiveDocContext(docsPluginId); const {savePreferredVersionName} = useDocsPreferredVersion(docsPluginId); const versionItems = useVersionItems({docsPluginId, configs}); 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 66dec60797..21b14d417e 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx @@ -9,7 +9,7 @@ import React, {type ReactNode} from 'react'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import {useAlternatePageUtils} from '@docusaurus/theme-common/internal'; import {translate} from '@docusaurus/Translate'; -import {useLocation} from '@docusaurus/router'; +import {useHistorySelector} from '@docusaurus/theme-common'; import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem'; import IconLanguage from '@theme/Icon/Language'; import type {LinkLikeNavbarItemProps} from '@theme/NavbarItem'; @@ -28,7 +28,8 @@ export default function LocaleDropdownNavbarItem({ i18n: {currentLocale, locales, localeConfigs}, } = useDocusaurusContext(); const alternatePageUtils = useAlternatePageUtils(); - const {search, hash} = useLocation(); + const search = useHistorySelector((history) => history.location.search); + const hash = useHistorySelector((history) => history.location.hash); const localeItems = locales.map((locale): LinkLikeNavbarItemProps => { const baseTo = `pathname://${alternatePageUtils.createUrl({ diff --git a/packages/docusaurus-theme-common/src/utils/historyUtils.ts b/packages/docusaurus-theme-common/src/utils/historyUtils.ts index 4695896a1e..eea45351d8 100644 --- a/packages/docusaurus-theme-common/src/utils/historyUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/historyUtils.ts @@ -57,7 +57,18 @@ export function useHistorySelector( return useSyncExternalStore( history.listen, () => selector(history), - () => selector(history), + () => + selector({ + ...history, + location: { + ...history.location, + // On the server/hydration, these attributes should always be empty + // Forcing empty state makes this hook safe from hydration errors + search: '', + hash: '', + state: undefined, + }, + }), ); } From 3ed2ea2ecf7351d3bd00af36cf4028757744ddf8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 09:50:37 +0200 Subject: [PATCH 015/103] chore(deps): bump treosh/lighthouse-ci-action from 12.1.0 to 12.6.1 (#11273) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lighthouse-report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lighthouse-report.yml b/.github/workflows/lighthouse-report.yml index f588cb4c48..87770af66e 100644 --- a/.github/workflows/lighthouse-report.yml +++ b/.github/workflows/lighthouse-report.yml @@ -37,7 +37,7 @@ jobs: - name: Audit URLs using Lighthouse id: lighthouse_audit - uses: treosh/lighthouse-ci-action@2f8dda6cf4de7d73b29853c3f29e73a01e297bd8 # 12.1.0 + uses: treosh/lighthouse-ci-action@fcd65974f7c4c2bf0ee9d09b84d2489183c29726 # 12.6.1 with: urls: | http://localhost:3000 From ee332e951d723cba75544bc4e3fc6059975e36cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 09:51:18 +0200 Subject: [PATCH 016/103] chore(deps): bump stefanzweifel/git-auto-commit-action from 5 to 6 (#11272) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lint-autofix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-autofix.yml b/.github/workflows/lint-autofix.yml index e80761689b..dd42164b3b 100644 --- a/.github/workflows/lint-autofix.yml +++ b/.github/workflows/lint-autofix.yml @@ -42,6 +42,6 @@ jobs: - name: Print Diff run: git diff - - uses: stefanzweifel/git-auto-commit-action@v5 + - uses: stefanzweifel/git-auto-commit-action@v6 with: commit_message: 'refactor: apply lint autofix' From a94fdbe21c117956be7c27eb999f97399e97c5fa Mon Sep 17 00:00:00 2001 From: enumura Date: Tue, 17 Jun 2025 23:11:14 +0900 Subject: [PATCH 017/103] fix(dev-server): use correct dev server HTML lang attribute (#11271) Co-authored-by: sebastien --- packages/docusaurus/src/webpack/client.ts | 1 + packages/docusaurus/src/webpack/templates/dev.html.template.ejs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus/src/webpack/client.ts b/packages/docusaurus/src/webpack/client.ts index 56bbb669d4..66e32fae36 100644 --- a/packages/docusaurus/src/webpack/client.ts +++ b/packages/docusaurus/src/webpack/client.ts @@ -117,6 +117,7 @@ export async function createStartClientConfig({ headTags, preBodyTags, postBodyTags, + lang: props.i18n.localeConfigs[props.i18n.currentLocale]!.htmlLang, }), ], }, diff --git a/packages/docusaurus/src/webpack/templates/dev.html.template.ejs b/packages/docusaurus/src/webpack/templates/dev.html.template.ejs index ee6270b0e4..3827683355 100644 --- a/packages/docusaurus/src/webpack/templates/dev.html.template.ejs +++ b/packages/docusaurus/src/webpack/templates/dev.html.template.ejs @@ -1,5 +1,5 @@ - + From 068d4c63a98ad8c9d4f7e7500ce62891332bdd50 Mon Sep 17 00:00:00 2001 From: stubinubin Date: Thu, 19 Jun 2025 17:31:03 +0100 Subject: [PATCH 018/103] fix(theme-common): Export FooterColumnItem type (#11280) --- packages/docusaurus-theme-common/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/docusaurus-theme-common/src/index.ts b/packages/docusaurus-theme-common/src/index.ts index 378828d934..e2605ba622 100644 --- a/packages/docusaurus-theme-common/src/index.ts +++ b/packages/docusaurus-theme-common/src/index.ts @@ -53,6 +53,7 @@ export { type MultiColumnFooter, type SimpleFooter, type Footer, + type FooterColumnItem, type FooterLogo, type FooterLinkItem, type ColorModeConfig, From 1cbc0118b0ee9b6bf87c862b9a0b62fcc1d450ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 19 Jun 2025 19:04:28 +0200 Subject: [PATCH 019/103] fix(docs): Fix empty sidebar item category `className` lost when post-processed to a doc (#11281) --- .../site-with-doc-label/docs/hello-2.md | 2 ++ .../site-with-doc-label/sidebars.json | 4 +++- .../__tests__/__snapshots__/index.test.ts.snap | 4 ++++ .../src/__tests__/index.test.ts | 10 ++++++---- .../src/props.ts | 18 +++++------------- .../__snapshots__/postProcessor.test.ts.snap | 4 ++++ .../sidebars/__tests__/postProcessor.test.ts | 2 ++ .../src/sidebars/postProcessor.ts | 5 ++++- .../dir-with-unique-index/index.mdx | 14 ++++++++++++++ .../doc-with-sidebar-className.mdx | 2 +- 10 files changed, 45 insertions(+), 20 deletions(-) create mode 100644 website/_dogfooding/_docs tests/tests/sidebar-frontmatter/dir-with-unique-index/index.mdx diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-2.md b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-2.md index f137c9d8d0..4bfa2d957f 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-2.md +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-2.md @@ -2,6 +2,8 @@ id: hello-2 title: Hello 2 sidebar_label: Hello 2 From Doc +sidebar_class_name: front-matter-class-name +sidebar_custom_props: {custom: "from front matter"} --- Hello World 2! diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/site-with-doc-label/sidebars.json b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/site-with-doc-label/sidebars.json index 081ece926c..0be3109676 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/site-with-doc-label/sidebars.json +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/site-with-doc-label/sidebars.json @@ -8,7 +8,9 @@ { "id": "hello-2", "type": "doc", - "label": "Hello Two" + "label": "Hello Two", + "className": "class-name-from-sidebars.json", + "customProps": {"test": "from sidebars.json"} } ] } 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 048e97aaee..820c30fec3 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 @@ -8,6 +8,10 @@ exports[`sidebar site with undefined sidebar 1`] = ` "type": "doc", }, { + "className": "front-matter-class-name", + "customProps": { + "custom": "from front matter", + }, "id": "hello-2", "label": "Hello 2 From Doc", "type": "doc", 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 b0b7272a5c..fb1180159f 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts @@ -582,14 +582,16 @@ describe('site with doc label', () => { ); }); - it('sidebar_label in doc has higher precedence over label in sidebar.json', async () => { + it('frontMatter.sidebar_* data in doc has higher precedence over sidebar.json data', async () => { const {content} = await loadSite(); const loadedVersion = content.loadedVersions[0]!; const sidebarProps = toSidebarsProp(loadedVersion); - expect((sidebarProps.docs![1] as PropSidebarItemLink).label).toBe( - 'Hello 2 From Doc', - ); + const item = sidebarProps.docs![1] as PropSidebarItemLink; + + expect(item.label).toBe('Hello 2 From Doc'); + expect(item.className).toBe('front-matter-class-name'); + expect(item.customProps).toStrictEqual({custom: 'from front matter'}); }); }); diff --git a/packages/docusaurus-plugin-content-docs/src/props.ts b/packages/docusaurus-plugin-content-docs/src/props.ts index c34211fad1..3f2d00c87c 100644 --- a/packages/docusaurus-plugin-content-docs/src/props.ts +++ b/packages/docusaurus-plugin-content-docs/src/props.ts @@ -38,22 +38,14 @@ export function toSidebarDocItemLinkProp({ 'id' | 'title' | 'permalink' | 'unlisted' | 'frontMatter' >; }): PropSidebarItemLink { - const { - id, - title, - permalink, - frontMatter: { - sidebar_label: sidebarLabel, - sidebar_custom_props: customProps, - }, - unlisted, - } = doc; + const {id, title, permalink, frontMatter, unlisted} = doc; return { type: 'link', - label: sidebarLabel ?? item.label ?? title, href: permalink, - className: item.className, - customProps: item.customProps ?? customProps, + // Front Matter data takes precedence over sidebars.json + label: frontMatter.sidebar_label ?? item.label ?? title, + className: frontMatter.sidebar_class_name ?? item.className, + customProps: frontMatter.sidebar_custom_props ?? item.customProps, docId: id, unlisted, }; diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/__snapshots__/postProcessor.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/__snapshots__/postProcessor.test.ts.snap index 3284571628..3d1f2ffdab 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/__snapshots__/postProcessor.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/__snapshots__/postProcessor.test.ts.snap @@ -76,6 +76,10 @@ exports[`postProcess transforms category without subitems 1`] = ` { "sidebar": [ { + "className": "category-className", + "customProps": { + "custom": true, + }, "id": "doc ID", "label": "Category 2", "type": "doc", diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/postProcessor.test.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/postProcessor.test.ts index 144bb8282e..0a6f052b45 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/postProcessor.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/postProcessor.test.ts @@ -31,6 +31,8 @@ describe('postProcess', () => { type: 'doc', id: 'doc ID', }, + className: 'category-className', + customProps: {custom: true}, items: [], }, ], diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts index b5cdc34aa9..222d1eabbd 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts @@ -77,10 +77,13 @@ function postProcessSidebarItem( ) { return null; } + const {label, className, customProps} = category; return { type: 'doc', - label: category.label, id: category.link.id, + label, + ...(className && {className}), + ...(customProps && {customProps}), }; } // A non-collapsible category can't be collapsed! diff --git a/website/_dogfooding/_docs tests/tests/sidebar-frontmatter/dir-with-unique-index/index.mdx b/website/_dogfooding/_docs tests/tests/sidebar-frontmatter/dir-with-unique-index/index.mdx new file mode 100644 index 0000000000..5e9c4563c1 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/sidebar-frontmatter/dir-with-unique-index/index.mdx @@ -0,0 +1,14 @@ +--- +sidebar_label: 'Dir with unique index label' +sidebar_class_name: 'dogfood_sidebar_class_name_test' +sidebar_custom_props: + prop: custom + number: 1 + boolean: true +--- + +# Single index.md in dir + +This doc has `sidebar_class_*` front matter + +Dogfood test for bug https://github.com/facebook/docusaurus/issues/11258 diff --git a/website/_dogfooding/_docs tests/tests/sidebar-frontmatter/doc-with-sidebar-className.mdx b/website/_dogfooding/_docs tests/tests/sidebar-frontmatter/doc-with-sidebar-className.mdx index 5b29010366..4d4301ecb9 100644 --- a/website/_dogfooding/_docs tests/tests/sidebar-frontmatter/doc-with-sidebar-className.mdx +++ b/website/_dogfooding/_docs tests/tests/sidebar-frontmatter/doc-with-sidebar-className.mdx @@ -4,4 +4,4 @@ sidebar_class_name: 'dogfood_sidebar_class_name_test' # Doc With Sidebar Class Name -This doc has `sidebar_label` front matter +This doc has `sidebar_class_name` front matter From ef71ddf93789d092d582f83523c9a9eab8dbcdd8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Jun 2025 11:09:33 +0200 Subject: [PATCH 020/103] chore(deps): bump marocchino/sticky-pull-request-comment from 2.9.2 to 2.9.3 (#11285) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lighthouse-report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lighthouse-report.yml b/.github/workflows/lighthouse-report.yml index 87770af66e..118cd61afb 100644 --- a/.github/workflows/lighthouse-report.yml +++ b/.github/workflows/lighthouse-report.yml @@ -65,7 +65,7 @@ jobs: - name: Add Lighthouse stats as comment id: comment_to_pr - uses: marocchino/sticky-pull-request-comment@67d0dec7b07ed060a405f9b2a64b8ab319fdd7db # 2.9.2 + uses: marocchino/sticky-pull-request-comment@d2ad0de260ae8b0235ce059e63f2949ba9e05943 # 2.9.3 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} number: ${{ github.event.pull_request.number }} From 96c38d5fdd13183d5b81798ba44b9372ba6ec8c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Tue, 24 Jun 2025 15:51:33 +0200 Subject: [PATCH 021/103] feat(core): Add `siteConfig.markdown.hooks`, deprecate `siteConfig.onBrokenMarkdownLinks` (#11283) --- .../classic-typescript/docusaurus.config.ts | 1 - .../templates/classic/docusaurus.config.js | 1 - .../docusaurus-mdx-loader/src/processor.ts | 17 +- .../__tests__/index.test.ts | 243 +++++++++++- .../src/remark/resolveMarkdownLinks/index.ts | 53 ++- .../__tests__/__fixtures__/fail.md | 1 - .../__tests__/__fixtures__/fail2.md | 1 - .../__tests__/__fixtures__/invalid-img.md | 1 - .../__tests__/__fixtures__/noUrl.md | 1 - .../__tests__/__fixtures__/pathname.md | 1 - .../__snapshots__/index.test.ts.snap | 8 +- .../transformImage/__tests__/index.test.ts | 370 ++++++++++++++++-- .../src/remark/transformImage/index.ts | 136 +++++-- .../__tests__/__fixtures__/noUrl.md | 1 - .../__fixtures__/nonexistentSiteAlias.md | 1 - .../__tests__/__fixtures__/pathname.md | 1 - .../__snapshots__/index.test.ts.snap | 14 +- .../transformLinks/__tests__/index.test.ts | 277 +++++++++++-- .../src/remark/transformLinks/index.ts | 116 ++++-- .../src/remark/unusedDirectives/index.ts | 12 +- .../src/remark/utils/index.ts | 14 + .../src/index.ts | 10 +- .../src/index.ts | 9 +- packages/docusaurus-types/package.json | 1 + packages/docusaurus-types/src/config.d.ts | 106 +---- packages/docusaurus-types/src/index.d.ts | 16 +- packages/docusaurus-types/src/markdown.d.ts | 165 ++++++++ packages/docusaurus-types/src/reporting.d.ts | 8 + .../__snapshots__/config.test.ts.snap | 50 ++- .../__tests__/__snapshots__/site.test.ts.snap | 5 +- .../server/__tests__/configValidation.test.ts | 241 +++++++++--- .../docusaurus/src/server/configValidation.ts | 40 +- website/docs/api/docusaurus.config.js.mdx | 35 ++ website/docusaurus.config-blog-only.js | 1 - website/docusaurus.config.ts | 4 +- 35 files changed, 1580 insertions(+), 381 deletions(-) delete mode 100644 packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail.md delete mode 100644 packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail2.md delete mode 100644 packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/invalid-img.md delete mode 100644 packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/noUrl.md delete mode 100644 packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/pathname.md delete mode 100644 packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/noUrl.md delete mode 100644 packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/nonexistentSiteAlias.md delete mode 100644 packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/pathname.md create mode 100644 packages/docusaurus-types/src/markdown.d.ts create mode 100644 packages/docusaurus-types/src/reporting.d.ts diff --git a/packages/create-docusaurus/templates/classic-typescript/docusaurus.config.ts b/packages/create-docusaurus/templates/classic-typescript/docusaurus.config.ts index 95cb36ccd7..1ef4506097 100644 --- a/packages/create-docusaurus/templates/classic-typescript/docusaurus.config.ts +++ b/packages/create-docusaurus/templates/classic-typescript/docusaurus.config.ts @@ -26,7 +26,6 @@ const config: Config = { projectName: 'docusaurus', // Usually your repo name. onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'warn', // Even if you don't use internationalization, you can use this field to set // useful metadata like html lang. For example, if your site is Chinese, you diff --git a/packages/create-docusaurus/templates/classic/docusaurus.config.js b/packages/create-docusaurus/templates/classic/docusaurus.config.js index c1d553465e..124755d17f 100644 --- a/packages/create-docusaurus/templates/classic/docusaurus.config.js +++ b/packages/create-docusaurus/templates/classic/docusaurus.config.js @@ -31,7 +31,6 @@ const config = { projectName: 'docusaurus', // Usually your repo name. onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'warn', // Even if you don't use internationalization, you can use this field to set // useful metadata like html lang. For example, if your site is Chinese, you diff --git a/packages/docusaurus-mdx-loader/src/processor.ts b/packages/docusaurus-mdx-loader/src/processor.ts index 30a2143c9d..29b0f8170a 100644 --- a/packages/docusaurus-mdx-loader/src/processor.ts +++ b/packages/docusaurus-mdx-loader/src/processor.ts @@ -22,6 +22,9 @@ import type {WebpackCompilerName} from '@docusaurus/utils'; import type {MDXFrontMatter} from './frontMatter'; import type {Options} from './options'; import type {AdmonitionOptions} from './remark/admonitions'; +import type {PluginOptions as ResolveMarkdownLinksOptions} from './remark/resolveMarkdownLinks'; +import type {PluginOptions as TransformLinksOptions} from './remark/transformLinks'; +import type {PluginOptions as TransformImageOptions} from './remark/transformImage'; import type {ProcessorOptions} from '@mdx-js/mdx'; // TODO as of April 2023, no way to import/re-export this ESM type easily :/ @@ -121,13 +124,19 @@ async function createProcessorFactory() { { staticDirs: options.staticDirs, siteDir: options.siteDir, - }, + onBrokenMarkdownImages: + options.markdownConfig.hooks.onBrokenMarkdownImages, + } satisfies TransformImageOptions, ], // TODO merge this with transformLinks? options.resolveMarkdownLink ? [ resolveMarkdownLinks, - {resolveMarkdownLink: options.resolveMarkdownLink}, + { + resolveMarkdownLink: options.resolveMarkdownLink, + onBrokenMarkdownLinks: + options.markdownConfig.hooks.onBrokenMarkdownLinks, + } satisfies ResolveMarkdownLinksOptions, ] : undefined, [ @@ -135,7 +144,9 @@ async function createProcessorFactory() { { staticDirs: options.staticDirs, siteDir: options.siteDir, - }, + onBrokenMarkdownLinks: + options.markdownConfig.hooks.onBrokenMarkdownLinks, + } satisfies TransformLinksOptions, ], gfm, options.markdownConfig.mdx1Compat.comments ? comment : null, diff --git a/packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/index.test.ts b/packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/index.test.ts index 00a76da679..903ac9bf12 100644 --- a/packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/index.test.ts +++ b/packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/index.test.ts @@ -5,22 +5,47 @@ * LICENSE file in the root directory of this source tree. */ +import {jest} from '@jest/globals'; +import * as path from 'path'; import plugin from '..'; import type {PluginOptions} from '../index'; -async function process(content: string) { - const {remark} = await import('remark'); +const siteDir = __dirname; - const options: PluginOptions = { - resolveMarkdownLink: ({linkPathname}) => `/RESOLVED---${linkPathname}`, +const DefaultTestOptions: PluginOptions = { + resolveMarkdownLink: ({linkPathname}) => `/RESOLVED---${linkPathname}`, + onBrokenMarkdownLinks: 'throw', +}; + +async function process(content: string, optionsInput?: Partial) { + const options = { + ...DefaultTestOptions, + ...optionsInput, }; - const result = await remark().use(plugin, options).process(content); + const {remark} = await import('remark'); + + const result = await remark() + .use(plugin, options) + .process({ + value: content, + path: path.posix.join(siteDir, 'docs', 'myFile.mdx'), + }); return result.value; } describe('resolveMarkdownLinks remark plugin', () => { + it('accepts non-md link', async () => { + /* language=markdown */ + const content = `[link1](link1)`; + const result = await process(content); + expect(result).toMatchInlineSnapshot(` + "[link1](link1) + " + `); + }); + it('resolves Markdown and MDX links', async () => { /* language=markdown */ const content = `[link1](link1.mdx) @@ -157,4 +182,212 @@ this is a code block " `); }); + + describe('onBrokenMarkdownLinks', () => { + const warnMock = jest.spyOn(console, 'warn').mockImplementation(() => {}); + beforeEach(() => { + warnMock.mockClear(); + }); + + async function processResolutionErrors( + content: string, + onBrokenMarkdownLinks: PluginOptions['onBrokenMarkdownLinks'] = 'throw', + ) { + return process(content, { + resolveMarkdownLink: () => null, + onBrokenMarkdownLinks, + }); + } + + describe('throws', () => { + it('for unresolvable mdx link', async () => { + /* language=markdown */ + const content = `[link1](link1.mdx)`; + + await expect(() => processResolutionErrors(content)).rejects + .toThrowErrorMatchingInlineSnapshot(` + "Markdown link with URL \`link1.mdx\` in source file "packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/docs/myFile.mdx" (1:1) couldn't be resolved. + Make sure it references a local Markdown file that exists within the current plugin. + To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownLinks\` option, or apply the \`pathname://\` protocol to the broken link URLs." + `); + }); + + it('for unresolvable md link', async () => { + /* language=markdown */ + const content = `[link1](link1.md)`; + + await expect(() => processResolutionErrors(content)).rejects + .toThrowErrorMatchingInlineSnapshot(` + "Markdown link with URL \`link1.md\` in source file "packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/docs/myFile.mdx" (1:1) couldn't be resolved. + Make sure it references a local Markdown file that exists within the current plugin. + To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownLinks\` option, or apply the \`pathname://\` protocol to the broken link URLs." + `); + }); + }); + + describe('warns', () => { + it('for unresolvable md and mdx link', async () => { + /* language=markdown */ + const content = ` +[link1](link1.mdx) + +[link2](link2) + +[link3](dir/link3.md) + +[link 4](/link/4) + `; + + const result = await processResolutionErrors(content, 'warn'); + + expect(result).toMatchInlineSnapshot(` + "[link1](link1.mdx) + + [link2](link2) + + [link3](dir/link3.md) + + [link 4](/link/4) + " + `); + + expect(warnMock).toHaveBeenCalledTimes(2); + expect(warnMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "[WARNING] Markdown link with URL \`link1.mdx\` in source file "packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/docs/myFile.mdx" (2:1) couldn't be resolved. + Make sure it references a local Markdown file that exists within the current plugin.", + ], + [ + "[WARNING] Markdown link with URL \`dir/link3.md\` in source file "packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/docs/myFile.mdx" (6:1) couldn't be resolved. + Make sure it references a local Markdown file that exists within the current plugin.", + ], + ] + `); + }); + + it('for unresolvable md and mdx link - with recovery', async () => { + /* language=markdown */ + const content = ` +[link1](link1.mdx) + +[link2](link2) + +[link3](dir/link3.md?query#hash) + +[link 4](/link/4) + `; + + const result = await processResolutionErrors(content, (params) => { + console.warn(`onBrokenMarkdownLinks called with`, params); + // We can alter the AST Node + params.node.title = 'fixed link title'; + params.node.url = 'ignored, less important than returned value'; + // Or return a new URL + return `/recovered-link`; + }); + + expect(result).toMatchInlineSnapshot(` + "[link1](/recovered-link "fixed link title") + + [link2](link2) + + [link3](/recovered-link "fixed link title") + + [link 4](/link/4) + " + `); + + expect(warnMock).toHaveBeenCalledTimes(2); + expect(warnMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "onBrokenMarkdownLinks called with", + { + "node": { + "children": [ + { + "position": { + "end": { + "column": 7, + "line": 2, + "offset": 7, + }, + "start": { + "column": 2, + "line": 2, + "offset": 2, + }, + }, + "type": "text", + "value": "link1", + }, + ], + "position": { + "end": { + "column": 19, + "line": 2, + "offset": 19, + }, + "start": { + "column": 1, + "line": 2, + "offset": 1, + }, + }, + "title": "fixed link title", + "type": "link", + "url": "/recovered-link", + }, + "sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/docs/myFile.mdx", + "url": "link1.mdx", + }, + ], + [ + "onBrokenMarkdownLinks called with", + { + "node": { + "children": [ + { + "position": { + "end": { + "column": 7, + "line": 6, + "offset": 43, + }, + "start": { + "column": 2, + "line": 6, + "offset": 38, + }, + }, + "type": "text", + "value": "link3", + }, + ], + "position": { + "end": { + "column": 33, + "line": 6, + "offset": 69, + }, + "start": { + "column": 1, + "line": 6, + "offset": 37, + }, + }, + "title": "fixed link title", + "type": "link", + "url": "/recovered-link", + }, + "sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/__tests__/docs/myFile.mdx", + "url": "dir/link3.md?query#hash", + }, + ], + ] + `); + }); + }); + }); }); diff --git a/packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/index.ts b/packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/index.ts index 7903ac3b18..326c0d831d 100644 --- a/packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/index.ts +++ b/packages/docusaurus-mdx-loader/src/remark/resolveMarkdownLinks/index.ts @@ -8,11 +8,18 @@ import { parseLocalURLPath, serializeURLPath, + toMessageRelativeFilePath, type URLPath, } from '@docusaurus/utils'; +import logger from '@docusaurus/logger'; +import {formatNodePositionExtraMessage} from '../utils'; import type {Plugin, Transformer} from 'unified'; import type {Definition, Link, Root} from 'mdast'; +import type { + MarkdownConfig, + OnBrokenMarkdownLinksFunction, +} from '@docusaurus/types'; type ResolveMarkdownLinkParams = { /** @@ -32,6 +39,33 @@ export type ResolveMarkdownLink = ( export interface PluginOptions { resolveMarkdownLink: ResolveMarkdownLink; + onBrokenMarkdownLinks: MarkdownConfig['hooks']['onBrokenMarkdownLinks']; +} + +function asFunction( + onBrokenMarkdownLinks: PluginOptions['onBrokenMarkdownLinks'], +): OnBrokenMarkdownLinksFunction { + if (typeof onBrokenMarkdownLinks === 'string') { + const extraHelp = + onBrokenMarkdownLinks === 'throw' + ? logger.interpolate`\nTo ignore this error, use the code=${'siteConfig.markdown.hooks.onBrokenMarkdownLinks'} option, or apply the code=${'pathname://'} protocol to the broken link URLs.` + : ''; + return ({sourceFilePath, url: linkUrl, node}) => { + const relativePath = toMessageRelativeFilePath(sourceFilePath); + logger.report( + onBrokenMarkdownLinks, + )`Markdown link with URL code=${linkUrl} in source file path=${relativePath}${formatNodePositionExtraMessage( + node, + )} couldn't be resolved. +Make sure it references a local Markdown file that exists within the current plugin.${extraHelp}`; + }; + } else { + return (params) => + onBrokenMarkdownLinks({ + ...params, + sourceFilePath: toMessageRelativeFilePath(params.sourceFilePath), + }); + } } const HAS_MARKDOWN_EXTENSION = /\.mdx?$/i; @@ -57,10 +91,15 @@ function parseMarkdownLinkURLPath(link: string): URLPath | null { * This is exposed as "data.contentTitle" to the processed vfile * Also gives the ability to strip that content title (used for the blog plugin) */ +// TODO merge this plugin with "transformLinks" +// in general we'd want to avoid traversing multiple times the same AST const plugin: Plugin = function plugin( options, ): Transformer { const {resolveMarkdownLink} = options; + + const onBrokenMarkdownLinks = asFunction(options.onBrokenMarkdownLinks); + return async (root, file) => { const {visit} = await import('unist-util-visit'); @@ -71,18 +110,26 @@ const plugin: Plugin = function plugin( return; } + const sourceFilePath = file.path; + const permalink = resolveMarkdownLink({ - sourceFilePath: file.path, + sourceFilePath, linkPathname: linkURLPath.pathname, }); if (permalink) { // This reapplies the link ?qs#hash part to the resolved pathname - const resolvedUrl = serializeURLPath({ + link.url = serializeURLPath({ ...linkURLPath, pathname: permalink, }); - link.url = resolvedUrl; + } else { + link.url = + onBrokenMarkdownLinks({ + url: link.url, + sourceFilePath, + node: link, + }) ?? link.url; } }); }; diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail.md b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail.md deleted file mode 100644 index d23f36ad8d..0000000000 --- a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail.md +++ /dev/null @@ -1 +0,0 @@ -![img](/img/doesNotExist.png) diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail2.md b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail2.md deleted file mode 100644 index 1779d93e04..0000000000 --- a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail2.md +++ /dev/null @@ -1 +0,0 @@ -![img](./notFound.png) \ No newline at end of file diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/invalid-img.md b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/invalid-img.md deleted file mode 100644 index a41a28b708..0000000000 --- a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/invalid-img.md +++ /dev/null @@ -1 +0,0 @@ -![invalid image](/invalid.png) diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/noUrl.md b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/noUrl.md deleted file mode 100644 index 4763436bab..0000000000 --- a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/noUrl.md +++ /dev/null @@ -1 +0,0 @@ -![img]() diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/pathname.md b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/pathname.md deleted file mode 100644 index 73f37cbd51..0000000000 --- a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/pathname.md +++ /dev/null @@ -1 +0,0 @@ -![img](pathname:///img/unchecked.png) diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__snapshots__/index.test.ts.snap index 8572403706..1620934872 100644 --- a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__snapshots__/index.test.ts.snap @@ -1,16 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`transformImage plugin does not choke on invalid image 1`] = ` -"invalid image/node_modules/url-loader/dist/cjs.js?limit=10000&name=assets/images/[name]-[contenthash].[ext]&fallback=/node_modules/file-loader/dist/cjs.js!./static/invalid.png").default} /> +"invalid image/node_modules/url-loader/dist/cjs.js?limit=10000&name=assets/images/[name]-[contenthash].[ext]&fallback=/node_modules/file-loader/dist/cjs.js!./../static/invalid.png").default} /> " `; -exports[`transformImage plugin fail if image does not exist 1`] = `"Image packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/static/img/doesNotExist.png or packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/static2/img/doesNotExist.png used in packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail.md not found."`; - -exports[`transformImage plugin fail if image relative path does not exist 1`] = `"Image packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/notFound.png used in packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/fail2.md not found."`; - -exports[`transformImage plugin fail if image url is absent 1`] = `"Markdown image URL is mandatory in "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/noUrl.md" file"`; - exports[`transformImage plugin pathname protocol 1`] = ` "![img](/img/unchecked.png) " diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/index.test.ts b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/index.test.ts index f491fd7ac3..1b6b82c413 100644 --- a/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/index.test.ts +++ b/packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/index.test.ts @@ -6,65 +6,361 @@ */ import {jest} from '@jest/globals'; -import path from 'path'; +import * as path from 'path'; import vfile from 'to-vfile'; import plugin, {type PluginOptions} from '../index'; -const processFixture = async ( - name: string, - options: Partial, -) => { - const {remark} = await import('remark'); - const {default: mdx} = await import('remark-mdx'); - const filePath = path.join(__dirname, `__fixtures__/${name}.md`); - const file = await vfile.read(filePath); - - const result = await remark() - .use(mdx) - .use(plugin, {siteDir: __dirname, staticDirs: [], ...options}) - .process(file); - - return result.value; -}; +const siteDir = path.join(__dirname, '__fixtures__'); const staticDirs = [ path.join(__dirname, '__fixtures__/static'), path.join(__dirname, '__fixtures__/static2'), ]; -const siteDir = path.join(__dirname, '__fixtures__'); +const getProcessor = async (options?: Partial) => { + const {remark} = await import('remark'); + const {default: mdx} = await import('remark-mdx'); + return remark() + .use(mdx) + .use(plugin, { + siteDir, + staticDirs, + onBrokenMarkdownImages: 'throw', + ...options, + }); +}; + +const processFixture = async ( + name: string, + options?: Partial, +) => { + const filePath = path.join(__dirname, `__fixtures__/${name}.md`); + const file = await vfile.read(filePath); + const processor = await getProcessor(options); + const result = await processor.process(file); + return result.value; +}; + +const processContent = async ( + content: string, + options?: Partial, +) => { + const processor = await getProcessor(options); + const result = await processor.process({ + value: content, + path: path.posix.join(siteDir, 'docs', 'myFile.mdx'), + }); + return result.value.toString(); +}; describe('transformImage plugin', () => { - it('fail if image does not exist', async () => { - await expect( - processFixture('fail', {staticDirs}), - ).rejects.toThrowErrorMatchingSnapshot(); - }); - it('fail if image relative path does not exist', async () => { - await expect( - processFixture('fail2', {staticDirs}), - ).rejects.toThrowErrorMatchingSnapshot(); - }); - it('fail if image url is absent', async () => { - await expect( - processFixture('noUrl', {staticDirs}), - ).rejects.toThrowErrorMatchingSnapshot(); - }); - it('transform md images to ', async () => { - const result = await processFixture('img', {staticDirs, siteDir}); + // TODO split that large fixture into many smaller test cases? + const result = await processFixture('img'); expect(result).toMatchSnapshot(); }); it('pathname protocol', async () => { - const result = await processFixture('pathname', {staticDirs}); + const result = await processContent( + `![img](pathname:///img/unchecked.png)`, + ); expect(result).toMatchSnapshot(); }); it('does not choke on invalid image', async () => { const errorMock = jest.spyOn(console, 'warn').mockImplementation(() => {}); - const result = await processFixture('invalid-img', {staticDirs}); + const result = await processContent(`![invalid image](/invalid.png)`); expect(result).toMatchSnapshot(); expect(errorMock).toHaveBeenCalledTimes(1); }); + + describe('onBrokenMarkdownImages', () => { + const fixtures = { + doesNotExistAbsolute: `![img](/img/doesNotExist.png)`, + doesNotExistRelative: `![img](./doesNotExist.png)`, + doesNotExistSiteAlias: `![img](@site/doesNotExist.png)`, + urlEmpty: `![img]()`, + }; + + describe('throws', () => { + it('if image absolute path does not exist', async () => { + await expect(processContent(fixtures.doesNotExistAbsolute)).rejects + .toThrowErrorMatchingInlineSnapshot(` + "Markdown image with URL \`/img/doesNotExist.png\` in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved to an existing local image file. + To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownImages\` option, or apply the \`pathname://\` protocol to the broken image URLs." + `); + }); + + it('if image relative path does not exist', async () => { + await expect(processContent(fixtures.doesNotExistRelative)).rejects + .toThrowErrorMatchingInlineSnapshot(` + "Markdown image with URL \`./doesNotExist.png\` in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved to an existing local image file. + To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownImages\` option, or apply the \`pathname://\` protocol to the broken image URLs." + `); + }); + + it('if image @site path does not exist', async () => { + await expect(processContent(fixtures.doesNotExistSiteAlias)).rejects + .toThrowErrorMatchingInlineSnapshot(` + "Markdown image with URL \`@site/doesNotExist.png\` in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved to an existing local image file. + To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownImages\` option, or apply the \`pathname://\` protocol to the broken image URLs." + `); + }); + + it('if image url empty', async () => { + await expect(processContent(fixtures.urlEmpty)).rejects + .toThrowErrorMatchingInlineSnapshot(` + "Markdown image with empty URL found in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1). + To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownImages\` option, or apply the \`pathname://\` protocol to the broken image URLs." + `); + }); + }); + + describe('warns', () => { + function processWarn(content: string) { + return processContent(content, {onBrokenMarkdownImages: 'warn'}); + } + + const warnMock = jest.spyOn(console, 'warn').mockImplementation(() => {}); + beforeEach(() => { + warnMock.mockClear(); + }); + + it('if image absolute path does not exist', async () => { + const result = await processWarn(fixtures.doesNotExistAbsolute); + expect(result).toMatchInlineSnapshot(` + "![img](/img/doesNotExist.png) + " + `); + expect(warnMock).toHaveBeenCalledTimes(1); + expect(warnMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "[WARNING] Markdown image with URL \`/img/doesNotExist.png\` in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved to an existing local image file.", + ], + ] + `); + }); + + it('if image relative path does not exist', async () => { + const result = await processWarn(fixtures.doesNotExistRelative); + expect(result).toMatchInlineSnapshot(` + "![img](./doesNotExist.png) + " + `); + expect(warnMock).toHaveBeenCalledTimes(1); + expect(warnMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "[WARNING] Markdown image with URL \`./doesNotExist.png\` in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved to an existing local image file.", + ], + ] + `); + }); + + it('if image @site path does not exist', async () => { + const result = await processWarn(fixtures.doesNotExistSiteAlias); + expect(result).toMatchInlineSnapshot(` + "![img](@site/doesNotExist.png) + " + `); + expect(warnMock).toHaveBeenCalledTimes(1); + expect(warnMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "[WARNING] Markdown image with URL \`@site/doesNotExist.png\` in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved to an existing local image file.", + ], + ] + `); + }); + + it('if image url empty', async () => { + const result = await processWarn(fixtures.urlEmpty); + expect(result).toMatchInlineSnapshot(` + "![img]() + " + `); + expect(warnMock).toHaveBeenCalledTimes(1); + expect(warnMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "[WARNING] Markdown image with empty URL found in source file "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx" (1:1).", + ], + ] + `); + }); + }); + + describe('function form', () => { + function processWarn(content: string) { + return processContent(content, { + onBrokenMarkdownImages: (params) => { + console.log('onBrokenMarkdownImages called for ', params); + // We can alter the AST Node + params.node.alt = 'new 404 alt'; + params.node.url = 'ignored, less important than returned value'; + // Or return a new URL + return '/404.png'; + }, + }); + } + + const logMock = jest.spyOn(console, 'log').mockImplementation(() => {}); + beforeEach(() => { + logMock.mockClear(); + }); + + it('if image absolute path does not exist', async () => { + const result = await processWarn(fixtures.doesNotExistAbsolute); + expect(result).toMatchInlineSnapshot(` + "![new 404 alt](/404.png) + " + `); + expect(logMock).toHaveBeenCalledTimes(1); + expect(logMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "onBrokenMarkdownImages called for ", + { + "node": { + "alt": "new 404 alt", + "position": { + "end": { + "column": 30, + "line": 1, + "offset": 29, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "title": null, + "type": "image", + "url": "/404.png", + }, + "sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx", + "url": "/img/doesNotExist.png", + }, + ], + ] + `); + }); + + it('if image relative path does not exist', async () => { + const result = await processWarn(fixtures.doesNotExistRelative); + expect(result).toMatchInlineSnapshot(` + "![new 404 alt](/404.png) + " + `); + expect(logMock).toHaveBeenCalledTimes(1); + expect(logMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "onBrokenMarkdownImages called for ", + { + "node": { + "alt": "new 404 alt", + "position": { + "end": { + "column": 27, + "line": 1, + "offset": 26, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "title": null, + "type": "image", + "url": "/404.png", + }, + "sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx", + "url": "./doesNotExist.png", + }, + ], + ] + `); + }); + + it('if image @site path does not exist', async () => { + const result = await processWarn(fixtures.doesNotExistSiteAlias); + expect(result).toMatchInlineSnapshot(` + "![new 404 alt](/404.png) + " + `); + expect(logMock).toHaveBeenCalledTimes(1); + expect(logMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "onBrokenMarkdownImages called for ", + { + "node": { + "alt": "new 404 alt", + "position": { + "end": { + "column": 31, + "line": 1, + "offset": 30, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "title": null, + "type": "image", + "url": "/404.png", + }, + "sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx", + "url": "@site/doesNotExist.png", + }, + ], + ] + `); + }); + + it('if image url empty', async () => { + const result = await processWarn(fixtures.urlEmpty); + expect(result).toMatchInlineSnapshot(` + "![new 404 alt](/404.png) + " + `); + expect(logMock).toHaveBeenCalledTimes(1); + expect(logMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "onBrokenMarkdownImages called for ", + { + "node": { + "alt": "new 404 alt", + "position": { + "end": { + "column": 9, + "line": 1, + "offset": 8, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "title": null, + "type": "image", + "url": "/404.png", + }, + "sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/__fixtures__/docs/myFile.mdx", + "url": "", + }, + ], + ] + `); + }); + }); + }); }); diff --git a/packages/docusaurus-mdx-loader/src/remark/transformImage/index.ts b/packages/docusaurus-mdx-loader/src/remark/transformImage/index.ts index 8cc4af821d..1dc00aa894 100644 --- a/packages/docusaurus-mdx-loader/src/remark/transformImage/index.ts +++ b/packages/docusaurus-mdx-loader/src/remark/transformImage/index.ts @@ -19,22 +19,67 @@ import { import escapeHtml from 'escape-html'; import {imageSizeFromFile} from 'image-size/fromFile'; import logger from '@docusaurus/logger'; -import {assetRequireAttributeValue, transformNode} from '../utils'; +import { + assetRequireAttributeValue, + formatNodePositionExtraMessage, + transformNode, +} from '../utils'; import type {Plugin, Transformer} from 'unified'; import type {MdxJsxTextElement} from 'mdast-util-mdx'; import type {Image, Root} from 'mdast'; import type {Parent} from 'unist'; +import type { + MarkdownConfig, + OnBrokenMarkdownImagesFunction, +} from '@docusaurus/types'; -type PluginOptions = { +export type PluginOptions = { staticDirs: string[]; siteDir: string; + onBrokenMarkdownImages: MarkdownConfig['hooks']['onBrokenMarkdownImages']; }; -type Context = PluginOptions & { +type Context = { + staticDirs: PluginOptions['staticDirs']; + siteDir: PluginOptions['siteDir']; + onBrokenMarkdownImages: OnBrokenMarkdownImagesFunction; filePath: string; inlineMarkdownImageFileLoader: string; }; +function asFunction( + onBrokenMarkdownImages: PluginOptions['onBrokenMarkdownImages'], +): OnBrokenMarkdownImagesFunction { + if (typeof onBrokenMarkdownImages === 'string') { + const extraHelp = + onBrokenMarkdownImages === 'throw' + ? logger.interpolate`\nTo ignore this error, use the code=${'siteConfig.markdown.hooks.onBrokenMarkdownImages'} option, or apply the code=${'pathname://'} protocol to the broken image URLs.` + : ''; + return ({sourceFilePath, url: imageUrl, node}) => { + const relativePath = toMessageRelativeFilePath(sourceFilePath); + if (imageUrl) { + logger.report( + onBrokenMarkdownImages, + )`Markdown image with URL code=${imageUrl} in source file path=${relativePath}${formatNodePositionExtraMessage( + node, + )} couldn't be resolved to an existing local image file.${extraHelp}`; + } else { + logger.report( + onBrokenMarkdownImages, + )`Markdown image with empty URL found in source file path=${relativePath}${formatNodePositionExtraMessage( + node, + )}.${extraHelp}`; + } + }; + } else { + return (params) => + onBrokenMarkdownImages({ + ...params, + sourceFilePath: toMessageRelativeFilePath(params.sourceFilePath), + }); + } +} + type Target = [node: Image, index: number, parent: Parent]; async function toImageRequireNode( @@ -51,7 +96,7 @@ async function toImageRequireNode( ); relativeImagePath = `./${relativeImagePath}`; - const parsedUrl = parseURLOrPath(node.url, 'https://example.com'); + const parsedUrl = parseURLOrPath(node.url); const hash = parsedUrl.hash ?? ''; const search = parsedUrl.search ?? ''; const requireString = `${context.inlineMarkdownImageFileLoader}${ @@ -113,57 +158,53 @@ ${(err as Error).message}`; }); } -async function ensureImageFileExist(imagePath: string, sourceFilePath: string) { - const imageExists = await fs.pathExists(imagePath); - if (!imageExists) { - throw new Error( - `Image ${toMessageRelativeFilePath( - imagePath, - )} used in ${toMessageRelativeFilePath(sourceFilePath)} not found.`, - ); - } -} - -async function getImageAbsolutePath( - imagePath: string, +async function getLocalImageAbsolutePath( + originalImagePath: string, {siteDir, filePath, staticDirs}: Context, ) { - if (imagePath.startsWith('@site/')) { - const imageFilePath = path.join(siteDir, imagePath.replace('@site/', '')); - await ensureImageFileExist(imageFilePath, filePath); + if (originalImagePath.startsWith('@site/')) { + const imageFilePath = path.join( + siteDir, + originalImagePath.replace('@site/', ''), + ); + if (!(await fs.pathExists(imageFilePath))) { + return null; + } return imageFilePath; - } else if (path.isAbsolute(imagePath)) { + } else if (path.isAbsolute(originalImagePath)) { // Absolute paths are expected to exist in the static folder. - const possiblePaths = staticDirs.map((dir) => path.join(dir, imagePath)); + const possiblePaths = staticDirs.map((dir) => + path.join(dir, originalImagePath), + ); const imageFilePath = await findAsyncSequential( possiblePaths, fs.pathExists, ); if (!imageFilePath) { - throw new Error( - `Image ${possiblePaths - .map((p) => toMessageRelativeFilePath(p)) - .join(' or ')} used in ${toMessageRelativeFilePath( - filePath, - )} not found.`, - ); + return null; + } + return imageFilePath; + } else { + // relative paths are resolved against the source file's folder + const imageFilePath = path.join(path.dirname(filePath), originalImagePath); + if (!(await fs.pathExists(imageFilePath))) { + return null; } return imageFilePath; } - // relative paths are resolved against the source file's folder - const imageFilePath = path.join(path.dirname(filePath), imagePath); - await ensureImageFileExist(imageFilePath, filePath); - return imageFilePath; } async function processImageNode(target: Target, context: Context) { const [node] = target; + if (!node.url) { - throw new Error( - `Markdown image URL is mandatory in "${toMessageRelativeFilePath( - context.filePath, - )}" file`, - ); + node.url = + context.onBrokenMarkdownImages({ + url: node.url, + sourceFilePath: context.filePath, + node, + }) ?? node.url; + return; } const parsedUrl = url.parse(node.url); @@ -183,13 +224,27 @@ async function processImageNode(target: Target, context: Context) { // We try to convert image urls without protocol to images with require calls // going through webpack ensures that image assets exist at build time - const imagePath = await getImageAbsolutePath(decodedPathname, context); - await toImageRequireNode(target, imagePath, context); + const localImagePath = await getLocalImageAbsolutePath( + decodedPathname, + context, + ); + if (localImagePath === null) { + node.url = + context.onBrokenMarkdownImages({ + url: node.url, + sourceFilePath: context.filePath, + node, + }) ?? node.url; + } else { + await toImageRequireNode(target, localImagePath, context); + } } const plugin: Plugin = function plugin( options, ): Transformer { + const onBrokenMarkdownImages = asFunction(options.onBrokenMarkdownImages); + return async (root, vfile) => { const {visit} = await import('unist-util-visit'); @@ -201,6 +256,7 @@ const plugin: Plugin = function plugin( filePath: vfile.path!, inlineMarkdownImageFileLoader: fileLoaderUtils.loaders.inlineMarkdownImageFileLoader, + onBrokenMarkdownImages, }; const promises: Promise[] = []; diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/noUrl.md b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/noUrl.md deleted file mode 100644 index a35d39ef45..0000000000 --- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/noUrl.md +++ /dev/null @@ -1 +0,0 @@ -[asset]() diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/nonexistentSiteAlias.md b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/nonexistentSiteAlias.md deleted file mode 100644 index 34247e1440..0000000000 --- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/nonexistentSiteAlias.md +++ /dev/null @@ -1 +0,0 @@ -[nonexistent](@site/foo.pdf) diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/pathname.md b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/pathname.md deleted file mode 100644 index 6e20bcf3d3..0000000000 --- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/pathname.md +++ /dev/null @@ -1 +0,0 @@ -[asset](pathname:///asset/unchecked.pdf) diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__snapshots__/index.test.ts.snap index a0186db7b1..9d18044775 100644 --- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__snapshots__/index.test.ts.snap @@ -1,15 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`transformAsset plugin fail if asset url is absent 1`] = `"Markdown link URL is mandatory in "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/noUrl.md" file (title: asset, line: 1)."`; - -exports[`transformAsset plugin fail if asset with site alias does not exist 1`] = `"Asset packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/foo.pdf used in packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/nonexistentSiteAlias.md not found."`; - -exports[`transformAsset plugin pathname protocol 1`] = ` -"[asset](pathname:///asset/unchecked.pdf) -" -`; - -exports[`transformAsset plugin transform md links to 1`] = ` +exports[`transformLinks plugin transform md links to 1`] = ` "[asset](https://example.com/asset.pdf) /node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default} /> @@ -54,6 +45,5 @@ in paragraph /node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./data.json").default}>JSON -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/static-json.json").default}>static JSON -" +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/static-json.json").default}>static JSON" `; diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/index.test.ts b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/index.test.ts index 346c46e599..7dee411e40 100644 --- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/index.test.ts +++ b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/index.test.ts @@ -5,53 +5,270 @@ * LICENSE file in the root directory of this source tree. */ -import path from 'path'; +import {jest} from '@jest/globals'; +import * as path from 'path'; import vfile from 'to-vfile'; -import plugin from '..'; -import transformImage, {type PluginOptions} from '../../transformImage'; +import plugin, {type PluginOptions} from '..'; +import transformImage from '../../transformImage'; -const processFixture = async (name: string, options?: PluginOptions) => { +const siteDir = path.join(__dirname, `__fixtures__`); + +const staticDirs = [ + path.join(siteDir, 'static'), + path.join(siteDir, 'static2'), +]; + +const getProcessor = async (options?: Partial) => { const {remark} = await import('remark'); const {default: mdx} = await import('remark-mdx'); - const siteDir = path.join(__dirname, `__fixtures__`); - const staticDirs = [ - path.join(siteDir, 'static'), - path.join(siteDir, 'static2'), - ]; - const file = await vfile.read(path.join(siteDir, `${name}.md`)); - const result = await remark() + return remark() .use(mdx) - .use(transformImage, {...options, siteDir, staticDirs}) - .use(plugin, { - ...options, + .use(transformImage, { + siteDir, staticDirs, - siteDir: path.join(__dirname, '__fixtures__'), + onBrokenMarkdownImages: 'throw', }) - .process(file); - - return result.value; + .use(plugin, { + staticDirs, + siteDir, + onBrokenMarkdownLinks: 'throw', + ...options, + }); }; -describe('transformAsset plugin', () => { - it('fail if asset url is absent', async () => { - await expect( - processFixture('noUrl'), - ).rejects.toThrowErrorMatchingSnapshot(); - }); +const processFixture = async ( + name: string, + options?: Partial, +) => { + const processor = await getProcessor(options); + const file = await vfile.read(path.join(siteDir, `${name}.md`)); + const result = await processor.process(file); + return result.value.toString().trim(); +}; - it('fail if asset with site alias does not exist', async () => { - await expect( - processFixture('nonexistentSiteAlias'), - ).rejects.toThrowErrorMatchingSnapshot(); +const processContent = async ( + content: string, + options?: Partial, +) => { + const processor = await getProcessor(options); + const result = await processor.process({ + value: content, + path: path.posix.join(siteDir, 'docs', 'myFile.mdx'), }); + return result.value.toString().trim(); +}; +describe('transformLinks plugin', () => { it('transform md links to ', async () => { + // TODO split fixture in many smaller test cases const result = await processFixture('asset'); expect(result).toMatchSnapshot(); }); it('pathname protocol', async () => { - const result = await processFixture('pathname'); - expect(result).toMatchSnapshot(); + const result = await processContent(`pathname:///unchecked.pdf)`); + expect(result).toMatchInlineSnapshot(`"pathname:///unchecked.pdf)"`); + }); + + it('accepts absolute file that does not exist', async () => { + const result = await processContent(`[file](/dir/file.zip)`); + expect(result).toMatchInlineSnapshot(`"[file](/dir/file.zip)"`); + }); + + it('accepts relative file that does not exist', async () => { + const result = await processContent(`[file](dir/file.zip)`); + expect(result).toMatchInlineSnapshot(`"[file](dir/file.zip)"`); + }); + + describe('onBrokenMarkdownLinks', () => { + const fixtures = { + urlEmpty: `[empty]()`, + fileDoesNotExistSiteAlias: `[file](@site/file.zip)`, + }; + + describe('throws', () => { + it('if url is empty', async () => { + await expect(processContent(fixtures.urlEmpty)).rejects + .toThrowErrorMatchingInlineSnapshot(` + "Markdown link with empty URL found in source file "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/docs/myFile.mdx" (1:1). + To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownLinks\` option, or apply the \`pathname://\` protocol to the broken link URLs." + `); + }); + + it('if file with site alias does not exist', async () => { + await expect(processContent(fixtures.fileDoesNotExistSiteAlias)).rejects + .toThrowErrorMatchingInlineSnapshot(` + "Markdown link with URL \`@site/file.zip\` in source file "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved. + Make sure it references a local Markdown file that exists within the current plugin. + To ignore this error, use the \`siteConfig.markdown.hooks.onBrokenMarkdownLinks\` option, or apply the \`pathname://\` protocol to the broken link URLs." + `); + }); + }); + + describe('warns', () => { + function processWarn(content: string) { + return processContent(content, {onBrokenMarkdownLinks: 'warn'}); + } + + const warnMock = jest.spyOn(console, 'warn').mockImplementation(() => {}); + beforeEach(() => { + warnMock.mockClear(); + }); + + it('if url is empty', async () => { + const result = await processWarn(fixtures.urlEmpty); + expect(result).toMatchInlineSnapshot(`"[empty]()"`); + expect(warnMock).toHaveBeenCalledTimes(1); + expect(warnMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "[WARNING] Markdown link with empty URL found in source file "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/docs/myFile.mdx" (1:1).", + ], + ] + `); + }); + + it('if file with site alias does not exist', async () => { + const result = await processWarn(fixtures.fileDoesNotExistSiteAlias); + expect(result).toMatchInlineSnapshot(`"[file](@site/file.zip)"`); + expect(warnMock).toHaveBeenCalledTimes(1); + expect(warnMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "[WARNING] Markdown link with URL \`@site/file.zip\` in source file "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/docs/myFile.mdx" (1:1) couldn't be resolved. + Make sure it references a local Markdown file that exists within the current plugin.", + ], + ] + `); + }); + }); + + describe('function form', () => { + function processWarn(content: string) { + return processContent(content, { + onBrokenMarkdownLinks: (params) => { + console.log('onBrokenMarkdownLinks called with', params); + // We can alter the AST Node + params.node.title = 'fixed link title'; + params.node.url = 'ignored, less important than returned value'; + // Or return a new URL + return '/404'; + }, + }); + } + + const logMock = jest.spyOn(console, 'log').mockImplementation(() => {}); + beforeEach(() => { + logMock.mockClear(); + }); + + it('if url is empty', async () => { + const result = await processWarn(fixtures.urlEmpty); + expect(result).toMatchInlineSnapshot( + `"[empty](/404 "fixed link title")"`, + ); + expect(logMock).toHaveBeenCalledTimes(1); + expect(logMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "onBrokenMarkdownLinks called with", + { + "node": { + "children": [ + { + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "text", + "value": "empty", + }, + ], + "position": { + "end": { + "column": 10, + "line": 1, + "offset": 9, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "title": "fixed link title", + "type": "link", + "url": "/404", + }, + "sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/docs/myFile.mdx", + "url": "", + }, + ], + ] + `); + }); + + it('if file with site alias does not exist', async () => { + const result = await processWarn(fixtures.fileDoesNotExistSiteAlias); + expect(result).toMatchInlineSnapshot( + `"[file](/404 "fixed link title")"`, + ); + expect(logMock).toHaveBeenCalledTimes(1); + expect(logMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "onBrokenMarkdownLinks called with", + { + "node": { + "children": [ + { + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "text", + "value": "file", + }, + ], + "position": { + "end": { + "column": 23, + "line": 1, + "offset": 22, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "title": "fixed link title", + "type": "link", + "url": "/404", + }, + "sourceFilePath": "packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__fixtures__/docs/myFile.mdx", + "url": "@site/file.zip", + }, + ], + ] + `); + }); + }); }); }); diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.ts b/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.ts index 625d838433..5d2d2d2d95 100644 --- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.ts +++ b/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.ts @@ -17,24 +17,72 @@ import { parseURLOrPath, } from '@docusaurus/utils'; import escapeHtml from 'escape-html'; -import {assetRequireAttributeValue, transformNode} from '../utils'; +import logger from '@docusaurus/logger'; +import { + assetRequireAttributeValue, + formatNodePositionExtraMessage, + transformNode, +} from '../utils'; import type {Plugin, Transformer} from 'unified'; import type {MdxJsxTextElement} from 'mdast-util-mdx'; import type {Parent} from 'unist'; -import type {Link, Literal, Root} from 'mdast'; +import type {Link, Root} from 'mdast'; +import type { + MarkdownConfig, + OnBrokenMarkdownLinksFunction, +} from '@docusaurus/types'; -type PluginOptions = { +export type PluginOptions = { staticDirs: string[]; siteDir: string; + onBrokenMarkdownLinks: MarkdownConfig['hooks']['onBrokenMarkdownLinks']; }; type Context = PluginOptions & { + staticDirs: string[]; + siteDir: string; + onBrokenMarkdownLinks: OnBrokenMarkdownLinksFunction; filePath: string; inlineMarkdownLinkFileLoader: string; }; type Target = [node: Link, index: number, parent: Parent]; +function asFunction( + onBrokenMarkdownLinks: PluginOptions['onBrokenMarkdownLinks'], +): OnBrokenMarkdownLinksFunction { + if (typeof onBrokenMarkdownLinks === 'string') { + const extraHelp = + onBrokenMarkdownLinks === 'throw' + ? logger.interpolate`\nTo ignore this error, use the code=${'siteConfig.markdown.hooks.onBrokenMarkdownLinks'} option, or apply the code=${'pathname://'} protocol to the broken link URLs.` + : ''; + + return ({sourceFilePath, url: linkUrl, node}) => { + const relativePath = toMessageRelativeFilePath(sourceFilePath); + if (linkUrl) { + logger.report( + onBrokenMarkdownLinks, + )`Markdown link with URL code=${linkUrl} in source file path=${relativePath}${formatNodePositionExtraMessage( + node, + )} couldn't be resolved. +Make sure it references a local Markdown file that exists within the current plugin.${extraHelp}`; + } else { + logger.report( + onBrokenMarkdownLinks, + )`Markdown link with empty URL found in source file path=${relativePath}${formatNodePositionExtraMessage( + node, + )}.${extraHelp}`; + } + }; + } else { + return (params) => + onBrokenMarkdownLinks({ + ...params, + sourceFilePath: toMessageRelativeFilePath(params.sourceFilePath), + }); + } +} + /** * Transforms the link node to a JSX `` element with a `require()` call. */ @@ -123,27 +171,15 @@ async function toAssetRequireNode( }); } -async function ensureAssetFileExist(assetPath: string, sourceFilePath: string) { - const assetExists = await fs.pathExists(assetPath); - if (!assetExists) { - throw new Error( - `Asset ${toMessageRelativeFilePath( - assetPath, - )} used in ${toMessageRelativeFilePath(sourceFilePath)} not found.`, - ); - } -} - -async function getAssetAbsolutePath( +async function getLocalFileAbsolutePath( assetPath: string, {siteDir, filePath, staticDirs}: Context, ) { if (assetPath.startsWith('@site/')) { const assetFilePath = path.join(siteDir, assetPath.replace('@site/', '')); - // The @site alias is the only way to believe that the user wants an asset. - // Everything else can just be a link URL - await ensureAssetFileExist(assetFilePath, filePath); - return assetFilePath; + if (await fs.pathExists(assetFilePath)) { + return assetFilePath; + } } else if (path.isAbsolute(assetPath)) { const assetFilePath = await findAsyncSequential( staticDirs.map((dir) => path.join(dir, assetPath)), @@ -164,16 +200,13 @@ async function getAssetAbsolutePath( async function processLinkNode(target: Target, context: Context) { const [node] = target; if (!node.url) { - // Try to improve error feedback - // see https://github.com/facebook/docusaurus/issues/3309#issuecomment-690371675 - const title = - node.title ?? (node.children[0] as Literal | undefined)?.value ?? '?'; - const line = node.position?.start.line ?? '?'; - throw new Error( - `Markdown link URL is mandatory in "${toMessageRelativeFilePath( - context.filePath, - )}" file (title: ${title}, line: ${line}).`, - ); + node.url = + context.onBrokenMarkdownLinks({ + url: node.url, + sourceFilePath: context.filePath, + node, + }) ?? node.url; + return; } const parsedUrl = url.parse(node.url); @@ -189,29 +222,48 @@ async function processLinkNode(target: Target, context: Context) { return; } - const assetPath = await getAssetAbsolutePath( + const localFilePath = await getLocalFileAbsolutePath( decodeURIComponent(parsedUrl.pathname), context, ); - if (assetPath) { - await toAssetRequireNode(target, assetPath, context); + + if (localFilePath) { + await toAssetRequireNode(target, localFilePath, context); + } else { + // The @site alias is the only way to believe that the user wants an asset. + if (hasSiteAlias) { + node.url = + context.onBrokenMarkdownLinks({ + url: node.url, + sourceFilePath: context.filePath, + node, + }) ?? node.url; + } else { + // Even if the url has a dot, and it looks like a file extension + // it can be risky to throw and fail fast by default + // It's perfectly valid for a route path segment to look like a filename + } } } const plugin: Plugin = function plugin( options, ): Transformer { + const onBrokenMarkdownLinks = asFunction(options.onBrokenMarkdownLinks); + return async (root, vfile) => { const {visit} = await import('unist-util-visit'); const fileLoaderUtils = getFileLoaderUtils( vfile.data.compilerName === 'server', ); + const context: Context = { ...options, filePath: vfile.path!, inlineMarkdownLinkFileLoader: fileLoaderUtils.loaders.inlineMarkdownLinkFileLoader, + onBrokenMarkdownLinks, }; const promises: Promise[] = []; diff --git a/packages/docusaurus-mdx-loader/src/remark/unusedDirectives/index.ts b/packages/docusaurus-mdx-loader/src/remark/unusedDirectives/index.ts index 0e0afa14fb..29b458b19c 100644 --- a/packages/docusaurus-mdx-loader/src/remark/unusedDirectives/index.ts +++ b/packages/docusaurus-mdx-loader/src/remark/unusedDirectives/index.ts @@ -8,7 +8,7 @@ import path from 'path'; import process from 'process'; import logger from '@docusaurus/logger'; import {posixPath} from '@docusaurus/utils'; -import {transformNode} from '../utils'; +import {formatNodePositionExtraMessage, transformNode} from '../utils'; import type {Root} from 'mdast'; import type {Parent} from 'unist'; import type {Transformer, Processor, Plugin} from 'unified'; @@ -39,17 +39,9 @@ function formatDirectiveName(directive: Directives) { return `${prefix}${directive.name}`; } -function formatDirectivePosition(directive: Directives): string | undefined { - return directive.position?.start - ? logger.interpolate`number=${directive.position.start.line}:number=${directive.position.start.column}` - : undefined; -} - function formatUnusedDirectiveMessage(directive: Directives) { const name = formatDirectiveName(directive); - const position = formatDirectivePosition(directive); - - return `- ${name} ${position ? `(${position})` : ''}`; + return `- ${name}${formatNodePositionExtraMessage(directive)}`; } function formatUnusedDirectivesMessage({ diff --git a/packages/docusaurus-mdx-loader/src/remark/utils/index.ts b/packages/docusaurus-mdx-loader/src/remark/utils/index.ts index 898f0617a4..3b0c215ec9 100644 --- a/packages/docusaurus-mdx-loader/src/remark/utils/index.ts +++ b/packages/docusaurus-mdx-loader/src/remark/utils/index.ts @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +import logger from '@docusaurus/logger'; import type {Node} from 'unist'; import type {MdxJsxAttributeValueExpression} from 'mdast-util-mdx'; @@ -83,3 +84,16 @@ export function assetRequireAttributeValue( }, }; } + +function formatNodePosition(node: Node): string | undefined { + return node.position?.start + ? logger.interpolate`number=${node.position.start.line}:number=${node.position.start.column}` + : undefined; +} + +// Returns " (line:column)" when position info is available +// The initial space is useful to append easily to any existing message +export function formatNodePositionExtraMessage(node: Node): string { + const position = formatNodePosition(node); + return `${position ? ` (${position})` : ''}`; +} diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index e22f2e54f2..fe38ec471c 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -71,7 +71,7 @@ export default async function pluginContentBlog( ); } - const {onBrokenMarkdownLinks, baseUrl} = siteConfig; + const {baseUrl} = siteConfig; const contentPaths: BlogContentPaths = { contentPath: path.resolve(siteDir, options.path), @@ -154,18 +154,12 @@ export default async function pluginContentBlog( }, markdownConfig: siteConfig.markdown, resolveMarkdownLink: ({linkPathname, sourceFilePath}) => { - const permalink = resolveMarkdownLinkPathname(linkPathname, { + return resolveMarkdownLinkPathname(linkPathname, { sourceFilePath, sourceToPermalink: contentHelpers.sourceToPermalink, siteDir, contentPaths, }); - if (permalink === null) { - logger.report( - onBrokenMarkdownLinks, - )`Blog markdown link couldn't be resolved: (url=${linkPathname}) in source file path=${sourceFilePath}`; - } - return permalink; }, }); diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index a740b7f5e2..d20a88185a 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -7,7 +7,6 @@ import path from 'path'; import fs from 'fs-extra'; -import logger from '@docusaurus/logger'; import { normalizeUrl, docuHash, @@ -158,18 +157,12 @@ export default async function pluginContentDocs( sourceFilePath, versionsMetadata, ); - const permalink = resolveMarkdownLinkPathname(linkPathname, { + return resolveMarkdownLinkPathname(linkPathname, { sourceFilePath, sourceToPermalink: contentHelpers.sourceToPermalink, siteDir, contentPaths: version, }); - if (permalink === null) { - logger.report( - siteConfig.onBrokenMarkdownLinks, - )`Docs markdown link couldn't be resolved: (url=${linkPathname}) in source file path=${sourceFilePath} for version number=${version.versionName}`; - } - return permalink; }, }, }); diff --git a/packages/docusaurus-types/package.json b/packages/docusaurus-types/package.json index db8872ca42..6636f2592d 100644 --- a/packages/docusaurus-types/package.json +++ b/packages/docusaurus-types/package.json @@ -15,6 +15,7 @@ "dependencies": { "@mdx-js/mdx": "^3.0.0", "@types/history": "^4.7.11", + "@types/mdast": "^4.0.2", "@types/react": "*", "commander": "^5.1.0", "joi": "^17.9.2", diff --git a/packages/docusaurus-types/src/config.d.ts b/packages/docusaurus-types/src/config.d.ts index 684aa3992e..ec1c8aee7e 100644 --- a/packages/docusaurus-types/src/config.d.ts +++ b/packages/docusaurus-types/src/config.d.ts @@ -10,12 +10,8 @@ import type {RuleSetRule} from 'webpack'; import type {DeepPartial, Overwrite} from 'utility-types'; import type {I18nConfig} from './i18n'; import type {PluginConfig, PresetConfig, HtmlTagObject} from './plugin'; - -import type {ProcessorOptions} from '@mdx-js/mdx'; - -export type RemarkRehypeOptions = ProcessorOptions['remarkRehypeOptions']; - -export type ReportingSeverity = 'ignore' | 'log' | 'warn' | 'throw'; +import type {ReportingSeverity} from './reporting'; +import type {MarkdownConfig} from './markdown'; export type RouterType = 'browser' | 'hash'; @@ -23,101 +19,6 @@ export type ThemeConfig = { [key: string]: unknown; }; -export type MarkdownPreprocessor = (args: { - filePath: string; - fileContent: string; -}) => string; - -export type MDX1CompatOptions = { - comments: boolean; - admonitions: boolean; - headingIds: boolean; -}; - -export type ParseFrontMatterParams = {filePath: string; fileContent: string}; -export type ParseFrontMatterResult = { - frontMatter: {[key: string]: unknown}; - content: string; -}; -export type DefaultParseFrontMatter = ( - params: ParseFrontMatterParams, -) => Promise; -export type ParseFrontMatter = ( - params: ParseFrontMatterParams & { - defaultParseFrontMatter: DefaultParseFrontMatter; - }, -) => Promise; - -export type MarkdownAnchorsConfig = { - /** - * Preserves the case of the heading text when generating anchor ids. - */ - maintainCase: boolean; -}; - -export type MarkdownConfig = { - /** - * The Markdown format to use by default. - * - * This is the format passed down to the MDX compiler, impacting the way the - * content is parsed. - * - * Possible values: - * - `'mdx'`: use the MDX format (JSX support) - * - `'md'`: use the CommonMark format (no JSX support) - * - `'detect'`: select the format based on file extension (.md / .mdx) - * - * @see https://mdxjs.com/packages/mdx/#optionsformat - * @default 'mdx' - */ - format: 'mdx' | 'md' | 'detect'; - - /** - * A function callback that lets users parse the front matter themselves. - * Gives the opportunity to read it from a different source, or process it. - * - * @see https://github.com/facebook/docusaurus/issues/5568 - */ - parseFrontMatter: ParseFrontMatter; - - /** - * Allow mermaid language code blocks to be rendered into Mermaid diagrams: - * - * - `true`: code blocks with language mermaid will be rendered. - * - `false` | `undefined` (default): code blocks with language mermaid - * will be left as code blocks. - * - * @see https://docusaurus.io/docs/markdown-features/diagrams/ - * @default false - */ - mermaid: boolean; - - /** - * Gives opportunity to preprocess the MDX string content before compiling. - * A good escape hatch that can be used to handle edge cases. - * - * @param args - */ - preprocessor?: MarkdownPreprocessor; - - /** - * Set of flags make it easier to upgrade from MDX 1 to MDX 2 - * See also https://github.com/facebook/docusaurus/issues/4029 - */ - mdx1Compat: MDX1CompatOptions; - - /** - * Ability to provide custom remark-rehype options - * See also https://github.com/remarkjs/remark-rehype#options - */ - remarkRehypeOptions: RemarkRehypeOptions; - - /** - * Options to control the behavior of anchors generated from Markdown headings - */ - anchors: MarkdownAnchorsConfig; -}; - export type StorageConfig = { type: SiteStorage['type']; namespace: boolean | string; @@ -258,7 +159,8 @@ export type DocusaurusConfig = { * @see https://docusaurus.io/docs/api/docusaurus-config#onBrokenMarkdownLinks * @default "warn" */ - onBrokenMarkdownLinks: ReportingSeverity; + // TODO Docusaurus v4 remove + onBrokenMarkdownLinks: ReportingSeverity | undefined; /** * The behavior of Docusaurus when it detects any [duplicate * routes](https://docusaurus.io/docs/creating-pages#duplicate-routes). diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index a6cb0b00b4..d7e61f569d 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -6,19 +6,27 @@ */ export { - ReportingSeverity, RouterType, ThemeConfig, - MarkdownConfig, - DefaultParseFrontMatter, - ParseFrontMatter, DocusaurusConfig, FutureConfig, + FutureV4Config, FasterConfig, StorageConfig, Config, } from './config'; +export { + MarkdownConfig, + MarkdownHooks, + DefaultParseFrontMatter, + ParseFrontMatter, + OnBrokenMarkdownLinksFunction, + OnBrokenMarkdownImagesFunction, +} from './markdown'; + +export {ReportingSeverity} from './reporting'; + export { SiteMetadata, DocusaurusContext, diff --git a/packages/docusaurus-types/src/markdown.d.ts b/packages/docusaurus-types/src/markdown.d.ts new file mode 100644 index 0000000000..fe5e1c3694 --- /dev/null +++ b/packages/docusaurus-types/src/markdown.d.ts @@ -0,0 +1,165 @@ +/** + * 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 type {ProcessorOptions} from '@mdx-js/mdx'; +import type {Image, Definition, Link} from 'mdast'; + +import type {ReportingSeverity} from './reporting'; + +export type RemarkRehypeOptions = ProcessorOptions['remarkRehypeOptions']; + +export type MarkdownPreprocessor = (args: { + filePath: string; + fileContent: string; +}) => string; + +export type MDX1CompatOptions = { + comments: boolean; + admonitions: boolean; + headingIds: boolean; +}; + +export type ParseFrontMatterParams = {filePath: string; fileContent: string}; +export type ParseFrontMatterResult = { + frontMatter: {[key: string]: unknown}; + content: string; +}; +export type DefaultParseFrontMatter = ( + params: ParseFrontMatterParams, +) => Promise; +export type ParseFrontMatter = ( + params: ParseFrontMatterParams & { + defaultParseFrontMatter: DefaultParseFrontMatter; + }, +) => Promise; + +export type MarkdownAnchorsConfig = { + /** + * Preserves the case of the heading text when generating anchor ids. + */ + maintainCase: boolean; +}; + +export type OnBrokenMarkdownLinksFunction = (params: { + /** + * Path of the source file on which the broken link was found + * Relative to the site dir. + * Example: "docs/category/myDoc.mdx" + */ + sourceFilePath: string; + + /** + * The Markdown link url that couldn't be resolved. + * Technically, in this context, it's more a "relative file path", but let's + * name it url for consistency with usual Markdown names and the MDX AST + * Example: "relative/dir/myTargetDoc.mdx?query#hash" + */ + url: string; + /** + * The Markdown Link AST node. + */ + node: Link | Definition; +}) => void | string; + +export type OnBrokenMarkdownImagesFunction = (params: { + /** + * Path of the source file on which the broken image was found + * Relative to the site dir. + * Example: "docs/category/myDoc.mdx" + */ + sourceFilePath: string; + + /** + * The Markdown image url that couldn't be resolved. + * Technically, in this context, it's more a "relative file path", but let's + * name it url for consistency with usual Markdown names and the MDX AST + * Example: "relative/dir/myImage.png" + */ + url: string; + /** + * The Markdown Image AST node. + */ + node: Image; +}) => void | string; + +export type MarkdownHooks = { + /** + * The behavior of Docusaurus when it detects any broken Markdown link. + * + * // TODO refactor doc links! + * @see https://docusaurus.io/docs/api/docusaurus-config#onBrokenMarkdownLinks + * @default "warn" + */ + onBrokenMarkdownLinks: ReportingSeverity | OnBrokenMarkdownLinksFunction; + + onBrokenMarkdownImages: ReportingSeverity | OnBrokenMarkdownImagesFunction; +}; + +export type MarkdownConfig = { + /** + * The Markdown format to use by default. + * + * This is the format passed down to the MDX compiler, impacting the way the + * content is parsed. + * + * Possible values: + * - `'mdx'`: use the MDX format (JSX support) + * - `'md'`: use the CommonMark format (no JSX support) + * - `'detect'`: select the format based on file extension (.md / .mdx) + * + * @see https://mdxjs.com/packages/mdx/#optionsformat + * @default 'mdx' + */ + format: 'mdx' | 'md' | 'detect'; + + /** + * A function callback that lets users parse the front matter themselves. + * Gives the opportunity to read it from a different source, or process it. + * + * @see https://github.com/facebook/docusaurus/issues/5568 + */ + parseFrontMatter: ParseFrontMatter; + + /** + * Allow mermaid language code blocks to be rendered into Mermaid diagrams: + * + * - `true`: code blocks with language mermaid will be rendered. + * - `false` | `undefined` (default): code blocks with language mermaid + * will be left as code blocks. + * + * @see https://docusaurus.io/docs/markdown-features/diagrams/ + * @default false + */ + mermaid: boolean; + + /** + * Gives opportunity to preprocess the MDX string content before compiling. + * A good escape hatch that can be used to handle edge cases. + * + * @param args + */ + preprocessor?: MarkdownPreprocessor; + + /** + * Set of flags make it easier to upgrade from MDX 1 to MDX 2 + * See also https://github.com/facebook/docusaurus/issues/4029 + */ + mdx1Compat: MDX1CompatOptions; + + /** + * Ability to provide custom remark-rehype options + * See also https://github.com/remarkjs/remark-rehype#options + */ + remarkRehypeOptions: RemarkRehypeOptions; + + /** + * Options to control the behavior of anchors generated from Markdown headings + */ + anchors: MarkdownAnchorsConfig; + + hooks: MarkdownHooks; +}; diff --git a/packages/docusaurus-types/src/reporting.d.ts b/packages/docusaurus-types/src/reporting.d.ts new file mode 100644 index 0000000000..0b3ef3d426 --- /dev/null +++ b/packages/docusaurus-types/src/reporting.d.ts @@ -0,0 +1,8 @@ +/** + * 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. + */ + +export type ReportingSeverity = 'ignore' | 'log' | 'warn' | 'throw'; diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap index bc5e437767..29b20ea9e9 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap @@ -42,6 +42,10 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = ` "maintainCase": false, }, "format": "mdx", + "hooks": { + "onBrokenMarkdownImages": "throw", + "onBrokenMarkdownLinks": "warn", + }, "mdx1Compat": { "admonitions": true, "comments": true, @@ -55,7 +59,6 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = ` "noIndex": false, "onBrokenAnchors": "warn", "onBrokenLinks": "throw", - "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", "plugins": [], "presets": [], @@ -117,6 +120,10 @@ exports[`loadSiteConfig website with ts + js config 1`] = ` "maintainCase": false, }, "format": "mdx", + "hooks": { + "onBrokenMarkdownImages": "throw", + "onBrokenMarkdownLinks": "warn", + }, "mdx1Compat": { "admonitions": true, "comments": true, @@ -130,7 +137,6 @@ exports[`loadSiteConfig website with ts + js config 1`] = ` "noIndex": false, "onBrokenAnchors": "warn", "onBrokenLinks": "throw", - "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", "plugins": [], "presets": [], @@ -192,6 +198,10 @@ exports[`loadSiteConfig website with valid JS CJS config 1`] = ` "maintainCase": false, }, "format": "mdx", + "hooks": { + "onBrokenMarkdownImages": "throw", + "onBrokenMarkdownLinks": "warn", + }, "mdx1Compat": { "admonitions": true, "comments": true, @@ -205,7 +215,6 @@ exports[`loadSiteConfig website with valid JS CJS config 1`] = ` "noIndex": false, "onBrokenAnchors": "warn", "onBrokenLinks": "throw", - "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", "plugins": [], "presets": [], @@ -267,6 +276,10 @@ exports[`loadSiteConfig website with valid JS ESM config 1`] = ` "maintainCase": false, }, "format": "mdx", + "hooks": { + "onBrokenMarkdownImages": "throw", + "onBrokenMarkdownLinks": "warn", + }, "mdx1Compat": { "admonitions": true, "comments": true, @@ -280,7 +293,6 @@ exports[`loadSiteConfig website with valid JS ESM config 1`] = ` "noIndex": false, "onBrokenAnchors": "warn", "onBrokenLinks": "throw", - "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", "plugins": [], "presets": [], @@ -342,6 +354,10 @@ exports[`loadSiteConfig website with valid TypeScript CJS config 1`] = ` "maintainCase": false, }, "format": "mdx", + "hooks": { + "onBrokenMarkdownImages": "throw", + "onBrokenMarkdownLinks": "warn", + }, "mdx1Compat": { "admonitions": true, "comments": true, @@ -355,7 +371,6 @@ exports[`loadSiteConfig website with valid TypeScript CJS config 1`] = ` "noIndex": false, "onBrokenAnchors": "warn", "onBrokenLinks": "throw", - "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", "plugins": [], "presets": [], @@ -417,6 +432,10 @@ exports[`loadSiteConfig website with valid TypeScript ESM config 1`] = ` "maintainCase": false, }, "format": "mdx", + "hooks": { + "onBrokenMarkdownImages": "throw", + "onBrokenMarkdownLinks": "warn", + }, "mdx1Compat": { "admonitions": true, "comments": true, @@ -430,7 +449,6 @@ exports[`loadSiteConfig website with valid TypeScript ESM config 1`] = ` "noIndex": false, "onBrokenAnchors": "warn", "onBrokenLinks": "throw", - "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", "plugins": [], "presets": [], @@ -492,6 +510,10 @@ exports[`loadSiteConfig website with valid async config 1`] = ` "maintainCase": false, }, "format": "mdx", + "hooks": { + "onBrokenMarkdownImages": "throw", + "onBrokenMarkdownLinks": "warn", + }, "mdx1Compat": { "admonitions": true, "comments": true, @@ -505,7 +527,6 @@ exports[`loadSiteConfig website with valid async config 1`] = ` "noIndex": false, "onBrokenAnchors": "warn", "onBrokenLinks": "throw", - "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", "organizationName": "endiliey", "plugins": [], @@ -569,6 +590,10 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = ` "maintainCase": false, }, "format": "mdx", + "hooks": { + "onBrokenMarkdownImages": "throw", + "onBrokenMarkdownLinks": "warn", + }, "mdx1Compat": { "admonitions": true, "comments": true, @@ -582,7 +607,6 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = ` "noIndex": false, "onBrokenAnchors": "warn", "onBrokenLinks": "throw", - "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", "organizationName": "endiliey", "plugins": [], @@ -646,6 +670,10 @@ exports[`loadSiteConfig website with valid config creator function 1`] = ` "maintainCase": false, }, "format": "mdx", + "hooks": { + "onBrokenMarkdownImages": "throw", + "onBrokenMarkdownLinks": "warn", + }, "mdx1Compat": { "admonitions": true, "comments": true, @@ -659,7 +687,6 @@ exports[`loadSiteConfig website with valid config creator function 1`] = ` "noIndex": false, "onBrokenAnchors": "warn", "onBrokenLinks": "throw", - "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", "organizationName": "endiliey", "plugins": [], @@ -726,6 +753,10 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = ` "maintainCase": false, }, "format": "mdx", + "hooks": { + "onBrokenMarkdownImages": "throw", + "onBrokenMarkdownLinks": "warn", + }, "mdx1Compat": { "admonitions": true, "comments": true, @@ -739,7 +770,6 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = ` "noIndex": false, "onBrokenAnchors": "warn", "onBrokenLinks": "throw", - "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", "organizationName": "endiliey", "plugins": [ diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap index 3a85ce8cb2..696ef93444 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap @@ -126,6 +126,10 @@ exports[`load loads props for site with custom i18n path 1`] = ` "maintainCase": false, }, "format": "mdx", + "hooks": { + "onBrokenMarkdownImages": "throw", + "onBrokenMarkdownLinks": "warn", + }, "mdx1Compat": { "admonitions": true, "comments": true, @@ -139,7 +143,6 @@ exports[`load loads props for site with custom i18n path 1`] = ` "noIndex": false, "onBrokenAnchors": "warn", "onBrokenLinks": "throw", - "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", "plugins": [], "presets": [], diff --git a/packages/docusaurus/src/server/__tests__/configValidation.test.ts b/packages/docusaurus/src/server/__tests__/configValidation.test.ts index 861faa8cd5..7a56519fe1 100644 --- a/packages/docusaurus/src/server/__tests__/configValidation.test.ts +++ b/packages/docusaurus/src/server/__tests__/configValidation.test.ts @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +import {jest} from '@jest/globals'; import { ConfigSchema, DEFAULT_CONFIG, @@ -16,6 +17,10 @@ import { DEFAULT_STORAGE_CONFIG, validateConfig, } from '../configValidation'; +import type { + MarkdownConfig, + MarkdownHooks, +} from '@docusaurus/types/src/markdown'; import type { FasterConfig, FutureConfig, @@ -36,7 +41,7 @@ const normalizeConfig = (config: DeepPartial) => describe('normalizeConfig', () => { it('normalizes empty config', () => { - const value = normalizeConfig({}); + const value = normalizeConfig({markdown: {}}); expect(value).toEqual({ ...DEFAULT_CONFIG, ...baseConfig, @@ -108,6 +113,10 @@ describe('normalizeConfig', () => { remarkRehypeOptions: { footnoteLabel: 'Pied de page', }, + hooks: { + onBrokenMarkdownLinks: 'log', + onBrokenMarkdownImages: 'log', + }, }, }; const normalizedConfig = normalizeConfig(userConfig); @@ -357,20 +366,15 @@ describe('onBrokenLinks', () => { }); describe('markdown', () => { + function normalizeMarkdown(markdown: DeepPartial) { + return normalizeConfig({markdown}).markdown; + } it('accepts undefined object', () => { - expect( - normalizeConfig({ - markdown: undefined, - }), - ).toEqual(expect.objectContaining({markdown: DEFAULT_CONFIG.markdown})); + expect(normalizeMarkdown(undefined)).toEqual(DEFAULT_CONFIG.markdown); }); it('accepts empty object', () => { - expect( - normalizeConfig({ - markdown: {}, - }), - ).toEqual(expect.objectContaining({markdown: DEFAULT_CONFIG.markdown})); + expect(normalizeMarkdown({})).toEqual(DEFAULT_CONFIG.markdown); }); it('accepts valid markdown object', () => { @@ -393,12 +397,12 @@ describe('markdown', () => { // @ts-expect-error: we don't validate it on purpose anyKey: 'heck we accept it on purpose', }, + hooks: { + onBrokenMarkdownLinks: 'log', + onBrokenMarkdownImages: 'warn', + }, }; - expect( - normalizeConfig({ - markdown, - }), - ).toEqual(expect.objectContaining({markdown})); + expect(normalizeMarkdown(markdown)).toEqual(markdown); }); it('accepts partial markdown object', () => { @@ -408,22 +412,14 @@ describe('markdown', () => { headingIds: false, }, }; - expect( - normalizeConfig({ - markdown, - }), - ).toEqual( - expect.objectContaining({ - markdown: { - ...DEFAULT_CONFIG.markdown, - ...markdown, - mdx1Compat: { - ...DEFAULT_CONFIG.markdown.mdx1Compat, - ...markdown.mdx1Compat, - }, - }, - }), - ); + expect(normalizeMarkdown(markdown)).toEqual({ + ...DEFAULT_CONFIG.markdown, + ...markdown, + mdx1Compat: { + ...DEFAULT_CONFIG.markdown.mdx1Compat, + ...markdown.mdx1Compat, + }, + }); }); it('throw for preprocessor bad arity', () => { @@ -436,10 +432,10 @@ describe('markdown', () => { " `); expect(() => - normalizeConfig({ + normalizeMarkdown( // @ts-expect-error: types forbid this - markdown: {preprocessor: (arg1, arg2) => String(arg1) + String(arg2)}, - }), + {preprocessor: (arg1, arg2) => String(arg1) + String(arg2)}, + ), ).toThrowErrorMatchingInlineSnapshot(` ""markdown.preprocessor" must have an arity of 1 " @@ -447,18 +443,13 @@ describe('markdown', () => { }); it('accepts undefined markdown format', () => { - expect( - normalizeConfig({markdown: {format: undefined}}).markdown.format, - ).toBe('mdx'); + expect(normalizeMarkdown({format: undefined}).format).toBe('mdx'); }); it('throw for bad markdown format', () => { expect(() => - normalizeConfig({ - markdown: { - // @ts-expect-error: bad value - format: null, - }, + normalizeMarkdown({ + format: null, }), ).toThrowErrorMatchingInlineSnapshot(` ""markdown.format" must be one of [mdx, md, detect] @@ -466,9 +457,9 @@ describe('markdown', () => { " `); expect(() => - normalizeConfig( + normalizeMarkdown( // @ts-expect-error: bad value - {markdown: {format: 'xyz'}}, + {format: 'xyz'}, ), ).toThrowErrorMatchingInlineSnapshot(` ""markdown.format" must be one of [mdx, md, detect] @@ -478,15 +469,165 @@ describe('markdown', () => { it('throw for null object', () => { expect(() => { - normalizeConfig({ - // @ts-expect-error: bad value - markdown: null, - }); + normalizeMarkdown(null); }).toThrowErrorMatchingInlineSnapshot(` ""markdown" must be of type object " `); }); + + describe('hooks', () => { + function normalizeHooks(hooks: DeepPartial): MarkdownHooks { + return normalizeMarkdown({ + hooks, + }).hooks; + } + + describe('onBrokenMarkdownLinks', () => { + function normalizeValue( + onBrokenMarkdownLinks?: MarkdownHooks['onBrokenMarkdownLinks'], + ) { + return normalizeHooks({ + onBrokenMarkdownLinks, + }).onBrokenMarkdownLinks; + } + + it('accepts undefined', () => { + expect(normalizeValue(undefined)).toBe('warn'); + }); + + it('accepts severity level', () => { + expect(normalizeValue('log')).toBe('log'); + }); + + it('rejects number', () => { + expect(() => + normalizeValue( + // @ts-expect-error: bad value + 42, + ), + ).toThrowErrorMatchingInlineSnapshot(` + ""markdown.hooks.onBrokenMarkdownLinks" does not match any of the allowed types + " + `); + }); + + it('accepts function', () => { + expect(normalizeValue(() => {})).toBeInstanceOf(Function); + }); + + it('rejects null', () => { + expect(() => normalizeValue(null)).toThrowErrorMatchingInlineSnapshot(` + ""markdown.hooks.onBrokenMarkdownLinks" does not match any of the allowed types + " + `); + }); + + describe('onBrokenMarkdownLinks migration', () => { + const warnMock = jest + .spyOn(console, 'warn') + .mockImplementation(() => {}); + beforeEach(() => { + warnMock.mockClear(); + }); + + it('accepts migrated v3 config', () => { + expect( + normalizeConfig({ + onBrokenMarkdownLinks: undefined, + markdown: { + hooks: { + onBrokenMarkdownLinks: 'throw', + }, + }, + }), + ).toEqual( + expect.objectContaining({ + onBrokenMarkdownLinks: undefined, + markdown: expect.objectContaining({ + hooks: expect.objectContaining({ + onBrokenMarkdownLinks: 'throw', + }), + }), + }), + ); + + expect(warnMock).not.toHaveBeenCalled(); + }); + + it('accepts deprecated v3 config with migration warning', () => { + expect( + normalizeConfig({ + onBrokenMarkdownLinks: 'log', + markdown: { + hooks: { + onBrokenMarkdownLinks: 'throw', + }, + }, + }), + ).toEqual( + expect.objectContaining({ + onBrokenMarkdownLinks: undefined, + markdown: expect.objectContaining({ + hooks: expect.objectContaining({ + onBrokenMarkdownLinks: 'log', + }), + }), + }), + ); + + expect(warnMock).toHaveBeenCalledTimes(1); + expect(warnMock.mock.calls[0]).toMatchInlineSnapshot(` + [ + "[WARNING] The \`siteConfig.onBrokenMarkdownLinks\` config option is deprecated and will be removed in Docusaurus v4. + Please migrate and move this option to \`siteConfig.markdown.hooks.onBrokenMarkdownLinks\` instead.", + ] + `); + }); + }); + }); + + describe('onBrokenMarkdownImages', () => { + function normalizeValue( + onBrokenMarkdownImages?: MarkdownHooks['onBrokenMarkdownImages'], + ) { + return normalizeHooks({ + onBrokenMarkdownImages, + }).onBrokenMarkdownImages; + } + + it('accepts undefined', () => { + expect(normalizeValue(undefined)).toBe('throw'); + }); + + it('accepts severity level', () => { + expect(normalizeValue('log')).toBe('log'); + }); + + it('rejects number', () => { + expect(() => + normalizeValue( + // @ts-expect-error: bad value + 42, + ), + ).toThrowErrorMatchingInlineSnapshot(` + ""markdown.hooks.onBrokenMarkdownImages" does not match any of the allowed types + " + `); + }); + + it('accepts function', () => { + expect(normalizeValue(() => {})).toBeInstanceOf(Function); + }); + + it('rejects null', () => { + expect(() => normalizeValue(null)).toThrowErrorMatchingInlineSnapshot(` + ""markdown.hooks.onBrokenMarkdownImages" does not match any of the allowed types + " + `); + }); + }); + }); }); describe('plugins', () => { @@ -846,7 +987,6 @@ describe('future', () => { }); it('rejects router - null', () => { - // @ts-expect-error: bad value const router: Config['future']['experimental_router'] = null; expect(() => normalizeConfig({ @@ -1055,7 +1195,6 @@ describe('future', () => { }); it('rejects namespace - null', () => { - // @ts-expect-error: bad value const storage: Partial = {namespace: null}; expect(() => normalizeConfig({ diff --git a/packages/docusaurus/src/server/configValidation.ts b/packages/docusaurus/src/server/configValidation.ts index 67fe593f22..1731068e08 100644 --- a/packages/docusaurus/src/server/configValidation.ts +++ b/packages/docusaurus/src/server/configValidation.ts @@ -22,11 +22,10 @@ import type { FutureConfig, FutureV4Config, StorageConfig, -} from '@docusaurus/types/src/config'; -import type { DocusaurusConfig, I18nConfig, MarkdownConfig, + MarkdownHooks, } from '@docusaurus/types'; const DEFAULT_I18N_LOCALE = 'en'; @@ -84,6 +83,11 @@ export const DEFAULT_FUTURE_CONFIG: FutureConfig = { experimental_router: 'browser', }; +export const DEFAULT_MARKDOWN_HOOKS: MarkdownHooks = { + onBrokenMarkdownLinks: 'warn', + onBrokenMarkdownImages: 'throw', +}; + export const DEFAULT_MARKDOWN_CONFIG: MarkdownConfig = { format: 'mdx', // TODO change this to "detect" in Docusaurus v4? mermaid: false, @@ -98,6 +102,7 @@ export const DEFAULT_MARKDOWN_CONFIG: MarkdownConfig = { maintainCase: false, }, remarkRehypeOptions: undefined, + hooks: DEFAULT_MARKDOWN_HOOKS, }; export const DEFAULT_CONFIG: Pick< @@ -128,7 +133,7 @@ export const DEFAULT_CONFIG: Pick< future: DEFAULT_FUTURE_CONFIG, onBrokenLinks: 'throw', onBrokenAnchors: 'warn', // TODO Docusaurus v4: change to throw - onBrokenMarkdownLinks: 'warn', + onBrokenMarkdownLinks: undefined, onDuplicateRoutes: 'warn', plugins: [], themes: [], @@ -350,7 +355,7 @@ export const ConfigSchema = Joi.object({ .default(DEFAULT_CONFIG.onBrokenAnchors), onBrokenMarkdownLinks: Joi.string() .equal('ignore', 'log', 'warn', 'throw') - .default(DEFAULT_CONFIG.onBrokenMarkdownLinks), + .default(() => DEFAULT_CONFIG.onBrokenMarkdownLinks), onDuplicateRoutes: Joi.string() .equal('ignore', 'log', 'warn', 'throw') .default(DEFAULT_CONFIG.onDuplicateRoutes), @@ -455,6 +460,20 @@ export const ConfigSchema = Joi.object({ DEFAULT_CONFIG.markdown.anchors.maintainCase, ), }).default(DEFAULT_CONFIG.markdown.anchors), + hooks: Joi.object({ + onBrokenMarkdownLinks: Joi.alternatives() + .try( + Joi.string().equal('ignore', 'log', 'warn', 'throw'), + Joi.function(), + ) + .default(DEFAULT_CONFIG.markdown.hooks.onBrokenMarkdownLinks), + onBrokenMarkdownImages: Joi.alternatives() + .try( + Joi.string().equal('ignore', 'log', 'warn', 'throw'), + Joi.function(), + ) + .default(DEFAULT_CONFIG.markdown.hooks.onBrokenMarkdownImages), + }).default(DEFAULT_CONFIG.markdown.hooks), }).default(DEFAULT_CONFIG.markdown), }).messages({ 'docusaurus.configValidationWarning': @@ -463,7 +482,16 @@ export const ConfigSchema = Joi.object({ // Expressing this kind of logic in Joi is a pain // We also want to decouple logic from Joi: easier to remove it later! -function ensureDocusaurusConfigConsistency(config: DocusaurusConfig) { +function postProcessDocusaurusConfig(config: DocusaurusConfig) { + if (config.onBrokenMarkdownLinks) { + logger.warn`The code=${'siteConfig.onBrokenMarkdownLinks'} config option is deprecated and will be removed in Docusaurus v4. +Please migrate and move this option to code=${'siteConfig.markdown.hooks.onBrokenMarkdownLinks'} instead.`; + // For v3 retro compatibility we use the old attribute over the new one + config.markdown.hooks.onBrokenMarkdownLinks = config.onBrokenMarkdownLinks; + // We erase the former one to ensure we don't use it anywhere + config.onBrokenMarkdownLinks = undefined; + } + if ( config.future.experimental_faster.ssgWorkerThreads && !config.future.v4.removeLegacyPostBuildHeadAttribute @@ -528,7 +556,7 @@ export function validateConfig( throw new Error(formattedError); } - ensureDocusaurusConfigConsistency(value); + postProcessDocusaurusConfig(value); return value; } diff --git a/website/docs/api/docusaurus.config.js.mdx b/website/docs/api/docusaurus.config.js.mdx index e746377ba7..8cdbe3080e 100644 --- a/website/docs/api/docusaurus.config.js.mdx +++ b/website/docs/api/docusaurus.config.js.mdx @@ -275,6 +275,14 @@ By default, it prints a warning, to let you know about your broken anchors. ### `onBrokenMarkdownLinks` {#onBrokenMarkdownLinks} +:::warning Deprecated + +Deprecated in Docusaurus v3.9, and will be removed in Docusaurus v4. + +Replaced by [`siteConfig.markdown.hooks.onBrokenMarkdownLinks`](#hooks.onBrokenMarkdownLinks) + +::: + - Type: `'ignore' | 'log' | 'warn' | 'throw'` The behavior of Docusaurus when it detects any broken Markdown link. @@ -511,6 +519,25 @@ type MarkdownAnchorsConfig = { maintainCase: boolean; }; +type OnBrokenMarkdownLinksFunction = (params: { + sourceFilePath: string; // MD/MDX source file relative to cwd + url: string; // Link url + node: Link | Definition; // mdast Node +}) => void | string; + +type OnBrokenMarkdownImagesFunction = (params: { + sourceFilePath: string; // MD/MDX source file relative to cwd + url: string; // Image url + node: Image; // mdast node +}) => void | string; + +type ReportingSeverity = 'ignore' | 'log' | 'warn' | 'throw'; + +type MarkdownHooks = { + onBrokenMarkdownLinks: ReportingSeverity | OnBrokenMarkdownLinksFunction; + onBrokenMarkdownImages: ReportingSeverity | OnBrokenMarkdownImagesFunction; +}; + type MarkdownConfig = { format: 'mdx' | 'md' | 'detect'; mermaid: boolean; @@ -519,6 +546,7 @@ type MarkdownConfig = { mdx1Compat: MDX1CompatOptions; remarkRehypeOptions: object; // see https://github.com/remarkjs/remark-rehype#options anchors: MarkdownAnchorsConfig; + hooks: MarkdownHooks; }; ``` @@ -546,6 +574,10 @@ export default { anchors: { maintainCase: true, }, + hooks: { + onBrokenMarkdownLinks: 'warn', + onBrokenMarkdownImages: 'throw', + }, }, }; ``` @@ -563,6 +595,9 @@ export default { | `mdx1Compat` | `MDX1CompatOptions` | `{comments: true, admonitions: true, headingIds: true}` | Compatibility options to make it easier to upgrade to Docusaurus v3+. | | `anchors` | `MarkdownAnchorsConfig` | `{maintainCase: false}` | Options to control the behavior of anchors generated from Markdown headings | | `remarkRehypeOptions` | `object` | `undefined` | Makes it possible to pass custom [`remark-rehype` options](https://github.com/remarkjs/remark-rehype#options). | +| `hooks` | `MarkdownHooks` | `object` | Make it possible to customize the MDX loader behavior with callbacks or built-in options. | +| `hooks.onBrokenMarkdownLinks` | `ReportingSeverity \| OnBrokenMarkdownLinksFunction` | `'warn'` | Hook to customize the behavior when encountering a broken Markdown link URL. With the callback function, you can return a new link URL, or alter the link [mdast node](https://github.com/syntax-tree/mdast). | +| `hooks.onBrokenMarkdownLinks` | `ReportingSeverity \| OnBrokenMarkdownImagesFunction` | `'throw'` | Hook to customize the behavior when encountering a broken Markdown image URL. With the callback function, you can return a new image URL, or alter the image [mdast node](https://github.com/syntax-tree/mdast). | ```mdx-code-block diff --git a/website/docusaurus.config-blog-only.js b/website/docusaurus.config-blog-only.js index af7a53bd00..fb434ffa7b 100644 --- a/website/docusaurus.config-blog-only.js +++ b/website/docusaurus.config-blog-only.js @@ -15,7 +15,6 @@ export default { url: 'https://docusaurus.io', // We can only warn now, since we have blog pages linking to non-blog pages... onBrokenLinks: 'warn', - onBrokenMarkdownLinks: 'warn', favicon: 'img/docusaurus.ico', themes: ['live-codeblock'], plugins: ['ideal-image'], diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index daf01f83f4..47eddc851a 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -217,6 +217,9 @@ export default async function createConfigAsync() { markdown: { format: 'detect', mermaid: true, + hooks: { + onBrokenMarkdownLinks: 'warn', + }, mdx1Compat: { // comments: false, }, @@ -265,7 +268,6 @@ export default async function createConfigAsync() { process.env.DOCUSAURUS_CURRENT_LOCALE !== defaultLocale ? 'warn' : 'throw', - onBrokenMarkdownLinks: 'warn', favicon: 'img/docusaurus.ico', customFields: { crashTest, From e14caf1f78b22bafdef5ef071d23928826e90737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Tue, 24 Jun 2025 16:38:08 +0200 Subject: [PATCH 022/103] feat(core): add `siteConfig.markdown.emoji` config option to disable `remark-emoji` (#11282) --- .../docusaurus-mdx-loader/src/processor.ts | 2 +- packages/docusaurus-types/src/markdown.d.ts | 10 +++ .../__snapshots__/config.test.ts.snap | 10 +++ .../__tests__/__snapshots__/site.test.ts.snap | 1 + .../server/__tests__/configValidation.test.ts | 68 ++++++++++++++++--- .../docusaurus/src/server/configValidation.ts | 2 + website/docs/api/docusaurus.config.js.mdx | 3 + 7 files changed, 87 insertions(+), 9 deletions(-) diff --git a/packages/docusaurus-mdx-loader/src/processor.ts b/packages/docusaurus-mdx-loader/src/processor.ts index 29b0f8170a..f5120150ee 100644 --- a/packages/docusaurus-mdx-loader/src/processor.ts +++ b/packages/docusaurus-mdx-loader/src/processor.ts @@ -95,7 +95,7 @@ async function createProcessorFactory() { headings, {anchorsMaintainCase: options.markdownConfig.anchors.maintainCase}, ], - emoji, + ...(options.markdownConfig.emoji ? [emoji] : []), toc, ]; } diff --git a/packages/docusaurus-types/src/markdown.d.ts b/packages/docusaurus-types/src/markdown.d.ts index fe5e1c3694..e7904f46bc 100644 --- a/packages/docusaurus-types/src/markdown.d.ts +++ b/packages/docusaurus-types/src/markdown.d.ts @@ -136,6 +136,16 @@ export type MarkdownConfig = { */ mermaid: boolean; + /** + * Allow remark-emoji to convert emoji shortcodes to Unicode emoji. + * - `true` (default): enables the remark-emoji plugin to convert shortcodes + * - `false`: disables the remark-emoji plugin + * + * @see https://github.com/rhysd/remark-emoji + * @default true + */ + emoji: boolean; + /** * Gives opportunity to preprocess the MDX string content before compiling. * A good escape hatch that can be used to handle edge cases. diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap index 29b20ea9e9..b868fc8330 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap @@ -41,6 +41,7 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = ` "anchors": { "maintainCase": false, }, + "emoji": true, "format": "mdx", "hooks": { "onBrokenMarkdownImages": "throw", @@ -119,6 +120,7 @@ exports[`loadSiteConfig website with ts + js config 1`] = ` "anchors": { "maintainCase": false, }, + "emoji": true, "format": "mdx", "hooks": { "onBrokenMarkdownImages": "throw", @@ -197,6 +199,7 @@ exports[`loadSiteConfig website with valid JS CJS config 1`] = ` "anchors": { "maintainCase": false, }, + "emoji": true, "format": "mdx", "hooks": { "onBrokenMarkdownImages": "throw", @@ -275,6 +278,7 @@ exports[`loadSiteConfig website with valid JS ESM config 1`] = ` "anchors": { "maintainCase": false, }, + "emoji": true, "format": "mdx", "hooks": { "onBrokenMarkdownImages": "throw", @@ -353,6 +357,7 @@ exports[`loadSiteConfig website with valid TypeScript CJS config 1`] = ` "anchors": { "maintainCase": false, }, + "emoji": true, "format": "mdx", "hooks": { "onBrokenMarkdownImages": "throw", @@ -431,6 +436,7 @@ exports[`loadSiteConfig website with valid TypeScript ESM config 1`] = ` "anchors": { "maintainCase": false, }, + "emoji": true, "format": "mdx", "hooks": { "onBrokenMarkdownImages": "throw", @@ -509,6 +515,7 @@ exports[`loadSiteConfig website with valid async config 1`] = ` "anchors": { "maintainCase": false, }, + "emoji": true, "format": "mdx", "hooks": { "onBrokenMarkdownImages": "throw", @@ -589,6 +596,7 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = ` "anchors": { "maintainCase": false, }, + "emoji": true, "format": "mdx", "hooks": { "onBrokenMarkdownImages": "throw", @@ -669,6 +677,7 @@ exports[`loadSiteConfig website with valid config creator function 1`] = ` "anchors": { "maintainCase": false, }, + "emoji": true, "format": "mdx", "hooks": { "onBrokenMarkdownImages": "throw", @@ -752,6 +761,7 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = ` "anchors": { "maintainCase": false, }, + "emoji": true, "format": "mdx", "hooks": { "onBrokenMarkdownImages": "throw", diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap index 696ef93444..40c87e4b93 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap @@ -125,6 +125,7 @@ exports[`load loads props for site with custom i18n path 1`] = ` "anchors": { "maintainCase": false, }, + "emoji": true, "format": "mdx", "hooks": { "onBrokenMarkdownImages": "throw", diff --git a/packages/docusaurus/src/server/__tests__/configValidation.test.ts b/packages/docusaurus/src/server/__tests__/configValidation.test.ts index 7a56519fe1..aaad1d3bae 100644 --- a/packages/docusaurus/src/server/__tests__/configValidation.test.ts +++ b/packages/docusaurus/src/server/__tests__/configValidation.test.ts @@ -17,17 +17,17 @@ import { DEFAULT_STORAGE_CONFIG, validateConfig, } from '../configValidation'; -import type { - MarkdownConfig, - MarkdownHooks, -} from '@docusaurus/types/src/markdown'; import type { FasterConfig, FutureConfig, FutureV4Config, StorageConfig, -} from '@docusaurus/types/src/config'; -import type {Config, DocusaurusConfig, PluginConfig} from '@docusaurus/types'; + MarkdownConfig, + MarkdownHooks, + Config, + DocusaurusConfig, + PluginConfig, +} from '@docusaurus/types'; import type {DeepPartial} from 'utility-types'; const baseConfig = { @@ -36,7 +36,7 @@ const baseConfig = { url: 'https://mysite.com', } as Config; -const normalizeConfig = (config: DeepPartial) => +const normalizeConfig = (config: DeepPartial): DocusaurusConfig => validateConfig({...baseConfig, ...config}, 'docusaurus.config.js'); describe('normalizeConfig', () => { @@ -99,6 +99,7 @@ describe('normalizeConfig', () => { markdown: { format: 'md', mermaid: true, + emoji: false, parseFrontMatter: async (params) => params.defaultParseFrontMatter(params), preprocessor: ({fileContent}) => fileContent, @@ -366,7 +367,9 @@ describe('onBrokenLinks', () => { }); describe('markdown', () => { - function normalizeMarkdown(markdown: DeepPartial) { + function normalizeMarkdown( + markdown: DeepPartial, + ): MarkdownConfig { return normalizeConfig({markdown}).markdown; } it('accepts undefined object', () => { @@ -381,6 +384,7 @@ describe('markdown', () => { const markdown: Config['markdown'] = { format: 'md', mermaid: true, + emoji: false, parseFrontMatter: async (params) => params.defaultParseFrontMatter(params), preprocessor: ({fileContent}) => fileContent, @@ -476,6 +480,54 @@ describe('markdown', () => { `); }); + describe('emoji', () => { + it('accepts emoji boolean true', () => { + expect( + normalizeMarkdown({ + emoji: true, + }).emoji, + ).toBe(true); + }); + + it('accepts emoji boolean false', () => { + expect( + normalizeMarkdown({ + emoji: false, + }).emoji, + ).toBe(false); + }); + + it('defaults emoji to true when undefined', () => { + expect(normalizeMarkdown({}).emoji).toBe(true); + }); + + it('throw for string emoji value', () => { + expect(() => + normalizeMarkdown({ + // @ts-expect-error: bad value + emoji: 'yes', + }), + ).toThrowErrorMatchingInlineSnapshot(` + ""markdown.emoji" must be a boolean + " + `); + }); + + it('throw for number emoji value', () => { + expect(() => + normalizeConfig({ + markdown: { + // @ts-expect-error: bad value + emoji: 1, + }, + }), + ).toThrowErrorMatchingInlineSnapshot(` + ""markdown.emoji" must be a boolean + " + `); + }); + }); + describe('hooks', () => { function normalizeHooks(hooks: DeepPartial): MarkdownHooks { return normalizeMarkdown({ diff --git a/packages/docusaurus/src/server/configValidation.ts b/packages/docusaurus/src/server/configValidation.ts index 1731068e08..d62e7b14c8 100644 --- a/packages/docusaurus/src/server/configValidation.ts +++ b/packages/docusaurus/src/server/configValidation.ts @@ -91,6 +91,7 @@ export const DEFAULT_MARKDOWN_HOOKS: MarkdownHooks = { export const DEFAULT_MARKDOWN_CONFIG: MarkdownConfig = { format: 'mdx', // TODO change this to "detect" in Docusaurus v4? mermaid: false, + emoji: true, preprocessor: undefined, parseFrontMatter: DEFAULT_PARSE_FRONT_MATTER, mdx1Compat: { @@ -435,6 +436,7 @@ export const ConfigSchema = Joi.object({ () => DEFAULT_CONFIG.markdown.parseFrontMatter, ), mermaid: Joi.boolean().default(DEFAULT_CONFIG.markdown.mermaid), + emoji: Joi.boolean().default(DEFAULT_CONFIG.markdown.emoji), preprocessor: Joi.function() .arity(1) .optional() diff --git a/website/docs/api/docusaurus.config.js.mdx b/website/docs/api/docusaurus.config.js.mdx index 8cdbe3080e..1ac4d1e07b 100644 --- a/website/docs/api/docusaurus.config.js.mdx +++ b/website/docs/api/docusaurus.config.js.mdx @@ -541,6 +541,7 @@ type MarkdownHooks = { type MarkdownConfig = { format: 'mdx' | 'md' | 'detect'; mermaid: boolean; + emoji: boolean; preprocessor?: MarkdownPreprocessor; parseFrontMatter?: ParseFrontMatter; mdx1Compat: MDX1CompatOptions; @@ -557,6 +558,7 @@ export default { markdown: { format: 'mdx', mermaid: true, + emoji: true, preprocessor: ({filePath, fileContent}) => { return fileContent.replaceAll('{{MY_VAR}}', 'MY_VALUE'); }, @@ -590,6 +592,7 @@ export default { | --- | --- | --- | --- | | `format` | `'mdx' \| 'md' \| 'detect'` | `'mdx'` | The default parser format to use for Markdown content. Using 'detect' will select the appropriate format automatically based on file extensions: `.md` vs `.mdx`. | | `mermaid` | `boolean` | `false` | When `true`, allows Docusaurus to render Markdown code blocks with `mermaid` language as Mermaid diagrams. | +| `emoji` | `boolean` | `true` | When `true`, allows Docusaurus to render emoji shortcodes (e.g., `:+1:`) as Unicode emoji (👍). When `false`, emoji shortcodes are left as-is. | | `preprocessor` | `MarkdownPreprocessor` | `undefined` | Gives you the ability to alter the Markdown content string before parsing. Use it as a last-resort escape hatch or workaround: it is almost always better to implement a Remark/Rehype plugin. | | `parseFrontMatter` | `ParseFrontMatter` | `undefined` | Gives you the ability to provide your own front matter parser, or to enhance the default parser. Read our [front matter guide](../guides/markdown-features/markdown-features-intro.mdx#front-matter) for details. | | `mdx1Compat` | `MDX1CompatOptions` | `{comments: true, admonitions: true, headingIds: true}` | Compatibility options to make it easier to upgrade to Docusaurus v3+. | From e82cd488420bb60feca12bd8ccc7ae7ee3908241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Tue, 24 Jun 2025 17:05:58 +0200 Subject: [PATCH 023/103] chore(website): split changelog per version + adjust changelog plugin implementation (#11287) --- .cspell.json | 1 + CHANGELOG-v2.md | 6757 +++++++++++++++++++++++ CHANGELOG.md | 6797 ------------------------ website/src/plugins/changelog/index.ts | 148 +- website/src/plugins/changelog/utils.ts | 134 + 5 files changed, 6921 insertions(+), 6916 deletions(-) create mode 100644 CHANGELOG-v2.md create mode 100644 website/src/plugins/changelog/utils.ts diff --git a/.cspell.json b/.cspell.json index efddcf2a00..d809714ff6 100644 --- a/.cspell.json +++ b/.cspell.json @@ -21,6 +21,7 @@ ], "ignorePaths": [ "CHANGELOG.md", + "CHANGELOG-v*.md", "patches", "packages/docusaurus-theme-translations/locales", "packages/docusaurus-plugin-ideal-image/src/theme/IdealImageLegacy", diff --git a/CHANGELOG-v2.md b/CHANGELOG-v2.md new file mode 100644 index 0000000000..d1fea7c77a --- /dev/null +++ b/CHANGELOG-v2.md @@ -0,0 +1,6757 @@ +# Docusaurus Changelog - v2.x + +## 2.4.3 (2023-09-20) + +#### :bug: Bug Fix + +- `docusaurus-plugin-content-docs` + - [#9107](https://github.com/facebook/docusaurus/pull/9107) fix(content-docs): sidebar generator should return customProps for doc items ([@TheCatLady](https://github.com/TheCatLady)) +- `docusaurus-theme-classic` + - [#9108](https://github.com/facebook/docusaurus/pull/9108) feat(theme-classic): add description & keywords microdata to blog posts ([@TheCatLady](https://github.com/TheCatLady)) + - [#9099](https://github.com/facebook/docusaurus/pull/9099) fix(theme): only set classname on ul elements if they have an existing class ([@homotechsual](https://github.com/homotechsual)) + - [#9243](https://github.com/facebook/docusaurus/pull/9243) fix(theme-common): ThemedComponent should display something when JS is disabled ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#9130](https://github.com/facebook/docusaurus/pull/9130) fix(theme): canonical url should be not change after hydration if url accessed with/without trailing slash ([@ori-shalom](https://github.com/ori-shalom)) + +#### Committers: 4 + +- Mikey O'Toole ([@homotechsual](https://github.com/homotechsual)) +- Ori Shalom ([@ori-shalom](https://github.com/ori-shalom)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- [@TheCatLady](https://github.com/TheCatLady) + +## 2.4.2 (2023-09-20) + +Bad npm publish, please use 2.4.3 + +## 2.4.1 (2023-05-15) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#8971](https://github.com/facebook/docusaurus/pull/8971) fix(theme): fix collapsible sidebar behavior when prefers-reduced-motion ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-translations` + - [#8933](https://github.com/facebook/docusaurus/pull/8933) fix(theme-translations): fix Turkish translation for aria label "Enter key" ([@LiberaTeMetuMortis](https://github.com/LiberaTeMetuMortis)) +- `docusaurus` + - [#8908](https://github.com/facebook/docusaurus/pull/8908) fix(core): Correct yarn upgrade command for yarn 2.x ([@andrewnicols](https://github.com/andrewnicols)) +- `docusaurus-plugin-content-blog`, `docusaurus-theme-common`, `docusaurus-utils-common`, `docusaurus` + - [#8909](https://github.com/facebook/docusaurus/pull/8909) fix(theme): add \_\_ prefix to technical anchors, search crawlers (Algolia) should ignore them ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-common` + - [#8906](https://github.com/facebook/docusaurus/pull/8906) fix(theme-common): fix collapsible component with prefers-reduced-motion ([@slorber](https://github.com/slorber)) + - [#8873](https://github.com/facebook/docusaurus/pull/8873) fix(theme-common): fix confusing theme error message: bad sidebar id suggestions ([@slorber](https://github.com/slorber)) +- `docusaurus-utils` + - [#8874](https://github.com/facebook/docusaurus/pull/8874) fix(utils): handle Markdown links with spaces to route correctly ([@morsko1](https://github.com/morsko1)) +- `docusaurus-theme-classic`, `docusaurus-theme-translations` + - [#8842](https://github.com/facebook/docusaurus/pull/8842) fix(theme-translations): remove redundant navigation text in aria label ([@tarunrajput](https://github.com/tarunrajput)) +- `create-docusaurus` + - [#8831](https://github.com/facebook/docusaurus/pull/8831) fix(create): add missing await ([@SACHINnANYAKKARA](https://github.com/SACHINnANYAKKARA)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#8862](https://github.com/facebook/docusaurus/pull/8862) refactor(theme): expose copy, success and word-wrap icons as standalone components ([@armano2](https://github.com/armano2)) + +#### Committers: 7 + +- Aleksandr Vladykin ([@morsko1](https://github.com/morsko1)) +- Andrew Lyons ([@andrewnicols](https://github.com/andrewnicols)) +- Armano ([@armano2](https://github.com/armano2)) +- MetuMortis ([@LiberaTeMetuMortis](https://github.com/LiberaTeMetuMortis)) +- Sachin Nanayakkara ([@SACHINnANYAKKARA](https://github.com/SACHINnANYAKKARA)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tarun Chauhan ([@tarunrajput](https://github.com/tarunrajput)) + +## 2.4.0 (2023-03-23) + +#### :rocket: New Feature + +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#8236](https://github.com/facebook/docusaurus/pull/8236) feat(content-docs): add support for sidebar item category/link descriptions in generated index page ([@ZarakiKanzaki](https://github.com/ZarakiKanzaki)) +- `docusaurus-theme-classic` + - [#8708](https://github.com/facebook/docusaurus/pull/8708) feat(theme): allow to load a Docusaurus page with theme from query-string: ?docusaurus-theme=dark ([@slorber](https://github.com/slorber)) + - [#8616](https://github.com/facebook/docusaurus/pull/8616) feat(theme): add ability to translate navbar+footer logo alt text ([@Mysterious-Dev](https://github.com/Mysterious-Dev)) +- `docusaurus-remark-plugin-npm2yarn` + - [#8690](https://github.com/facebook/docusaurus/pull/8690) feat(npm-to-yarn): add support for PnPm and custom converters ([@armano2](https://github.com/armano2)) +- `docusaurus` + - [#8677](https://github.com/facebook/docusaurus/pull/8677) feat(core): add script env variables: NODE_ENV + BABEL_ENV + DOCUSAURUS_CURRENT_LOCALE (temporary i18n workaround) ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#8674](https://github.com/facebook/docusaurus/pull/8674) feat(theme-classic): respect `prefers-reduced-motion: reduce` mediaquery, bump Infima to alpha.43 ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-translations` + - [#8668](https://github.com/facebook/docusaurus/pull/8668) feat(theme-translations): add Hungarian theme translations ([@trueqap](https://github.com/trueqap)) + - [#8631](https://github.com/facebook/docusaurus/pull/8631) feat(theme-translations): add Norwegian (Bokmål) theme translation ([@dr0nn1](https://github.com/dr0nn1)) +- `docusaurus-theme-common` + - [#8656](https://github.com/facebook/docusaurus/pull/8656) feat(theme-common): allow passing a string for details summary ([@pReya](https://github.com/pReya)) +- `docusaurus-plugin-google-gtag` + - [#8620](https://github.com/facebook/docusaurus/pull/8620) feat(gtag-plugin): gtag should support multiple tracking ids, notably for the UA => GA4 transition ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#8803](https://github.com/facebook/docusaurus/pull/8803) fix(theme): codeblock buttons should be kept on the right when using RTL locale ([@Vishruta-Patil](https://github.com/Vishruta-Patil)) + - [#8615](https://github.com/facebook/docusaurus/pull/8615) fix(theme): improve color toggle when using dark navbar ([@dewanshDT](https://github.com/dewanshDT)) + - [#8699](https://github.com/facebook/docusaurus/pull/8699) fix(theme-classic): fix tab focus bug in dropdown (#8697) ([@kagankan](https://github.com/kagankan)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#8801](https://github.com/facebook/docusaurus/pull/8801) fix(theme): allow tabs children to be falsy ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-common`, `docusaurus-theme-search-algolia` + - [#8757](https://github.com/facebook/docusaurus/pull/8757) fix(search): search page should react to querystring changes + cleanup/refactor ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#8746](https://github.com/facebook/docusaurus/pull/8746) fix(core): baseUrl error banner link anchor case ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-translations` + - [#8744](https://github.com/facebook/docusaurus/pull/8744) fix(theme-translations): fix wrong arabic words (tip/next) ([@Anasqx](https://github.com/Anasqx)) + +#### :nail_care: Polish + +- `create-docusaurus` + - [#8712](https://github.com/facebook/docusaurus/pull/8712) polish(create-docusaurus): the starter template should use a navbar item "docSidebar" instead of "doc" (less fragile on updates) ([@biplavmz](https://github.com/biplavmz)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-common`, `docusaurus` + - [#8735](https://github.com/facebook/docusaurus/pull/8735) polish(theme): better error messages on navbar item rendering failures + ErrorCauseBoundary API ([@tannerdolby](https://github.com/tannerdolby)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus` + - [#8736](https://github.com/facebook/docusaurus/pull/8736) polish(core): better styling for error screens ([@tannerdolby](https://github.com/tannerdolby)) + +#### Committers: 14 + +- Anas ([@Anasqx](https://github.com/Anasqx)) +- Armano ([@armano2](https://github.com/armano2)) +- Davide Donadio ([@ZarakiKanzaki](https://github.com/ZarakiKanzaki)) +- Dewansh Thakur ([@dewanshDT](https://github.com/dewanshDT)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Kagan ([@kagankan](https://github.com/kagankan)) +- Moritz Stückler ([@pReya](https://github.com/pReya)) +- Mysterious_Dev ([@Mysterious-Dev](https://github.com/Mysterious-Dev)) +- Petter Drønnen ([@dr0nn1](https://github.com/dr0nn1)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tanner Dolby ([@tannerdolby](https://github.com/tannerdolby)) +- TrueQAP ([@trueqap](https://github.com/trueqap)) +- Vishruta Patil ([@Vishruta-Patil](https://github.com/Vishruta-Patil)) +- [@biplavmz](https://github.com/biplavmz) + +## 2.3.1 (2023-02-03) + +#### :bug: Bug Fix + +- `docusaurus-theme-common` + - [#8628](https://github.com/facebook/docusaurus/pull/8628) fix(theme-common): fix issue in tab scroll position restoration on tab click ([@slorber](https://github.com/slorber)) + - [#8619](https://github.com/facebook/docusaurus/pull/8619) fix(theme-common): localStorage utils dispatch too many storage events leading to infinite loop ([@slorber](https://github.com/slorber)) + - [#8618](https://github.com/facebook/docusaurus/pull/8618) fix(theme-common): prepare usage of useSyncExternalStore compatibility with React 18 ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#8593](https://github.com/facebook/docusaurus/pull/8593) fix(theme-classic): allow rendering single tab item ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-utils` + - [#8606](https://github.com/facebook/docusaurus/pull/8606) fix(utils): handle CRLF when parsing MDX imports ([@scastiel](https://github.com/scastiel)) +- `docusaurus-preset-classic` + - [#8597](https://github.com/facebook/docusaurus/pull/8597) fix(preset-classic): install the right plugin for googleTagManager ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :nail_care: Polish + +- `docusaurus-theme-translations` + - [#8614](https://github.com/facebook/docusaurus/pull/8614) chore(theme-translations): complete zh translations ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :robot: Dependencies + +- `docusaurus-plugin-client-redirects`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#8610](https://github.com/facebook/docusaurus/pull/8610) chore(deps): bump eta from 1.12.3 to 2.0.0 ([@dependabot[bot]](https://github.com/apps/dependabot)) + +#### Committers: 3 + +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Sébastien Castiel ([@scastiel](https://github.com/scastiel)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) + +## 2.3.0 (2023-01-26) + +#### :rocket: New Feature + +- `docusaurus-theme-translations` + - [#8541](https://github.com/facebook/docusaurus/pull/8541) feat(theme-translations): default translations for Slovenian (sl-SI) ([@MatijaSi](https://github.com/MatijaSi)) +- `docusaurus-plugin-content-blog` + - [#8378](https://github.com/facebook/docusaurus/pull/8378) feat(blog): add options.createFeedItems to filter/limit/transform feed items ([@johnnyreilly](https://github.com/johnnyreilly)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus` + - [#8225](https://github.com/facebook/docusaurus/pull/8225) feat(theme-classic): store selected tab in query string. ([@mturoci](https://github.com/mturoci)) +- `docusaurus` + - [#8397](https://github.com/facebook/docusaurus/pull/8397) feat(core): deploy CLI - add support for git url "insteadOf": use 'remote get-url' to determine source repo url ([@friederbluemle](https://github.com/friederbluemle)) +- `docusaurus-theme-search-algolia` + - [#8428](https://github.com/facebook/docusaurus/pull/8428) feat(theme-algolia): add option.replaceSearchResultPathname to process/replaceAll search result urls +- `docusaurus-plugin-google-tag-manager` + - [#8470](https://github.com/facebook/docusaurus/pull/8470) feat(plugin-google-tag-manager): add new google-tag-manager plugin + deprecate google-analytics plugin ([@lanegoolsby](https://github.com/lanegoolsby)) + +#### :bug: Bug Fix + +- `docusaurus-mdx-loader` + - [#8303](https://github.com/facebook/docusaurus/pull/8303) fix(mdx-loader): support nested admonitions + - [#8282](https://github.com/facebook/docusaurus/pull/8282) fix(mermaid): fix Mermaid integration for v9.2 release +- `docusaurus-theme-common` + - [#8539](https://github.com/facebook/docusaurus/pull/8539) fix(algolia): make search footer respect searchPagePath ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#8538](https://github.com/facebook/docusaurus/pull/8538) fix(core): avoid hash collision when generating chunk names ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#8481](https://github.com/facebook/docusaurus/pull/8481) fix(core): explicitly define CopyWebpackPlugin toType: 'dir' ([@Thomascogez](https://github.com/Thomascogez)) + - [#8342](https://github.com/facebook/docusaurus/pull/8342) fix(core): normalize input for poll option ([@mhnaeem](https://github.com/mhnaeem)) +- `docusaurus-theme-classic`, `docusaurus` + - [#8445](https://github.com/facebook/docusaurus/pull/8445) fix(theme-classic) extract HomeBreadcrumbItem + fix swizzle bugs ([@3v0k4](https://github.com/3v0k4)) +- `docusaurus-theme-search-algolia` + - [#8462](https://github.com/facebook/docusaurus/pull/8462) fix(search-algolia): pass custom transformItems function to SearchBar ([@mturoci](https://github.com/mturoci)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#8486](https://github.com/facebook/docusaurus/pull/8486) fix(theme): refactor Tabs, make groupId + queryString work fine together ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#8463](https://github.com/facebook/docusaurus/pull/8463) fix(theme-classic): content container grow to take all the available space ([@Djunnni](https://github.com/Djunnni)) + - [#8328](https://github.com/facebook/docusaurus/pull/8328) fix(theme): preserve sidebar height on collapse ([@0916dhkim](https://github.com/0916dhkim)) + - [#8350](https://github.com/facebook/docusaurus/pull/8350) fix(theme): forward className prop in theme-classic's Heading ([@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)) +- `docusaurus-theme-translations` + - [#8424](https://github.com/facebook/docusaurus/pull/8424) fix(translations): typo in lastUpdatedAtBy Vietnamese translation ([@slorber](https://github.com/slorber)) + - [#8289](https://github.com/facebook/docusaurus/pull/8289) fix(theme-translations): complete Turkish theme translations + - [#8406](https://github.com/facebook/docusaurus/pull/8406) fix(translations): complete farsi theme translations + - [#8450](https://github.com/facebook/docusaurus/pull/8450) fix(theme-translations): complete Vietnamese theme translations + - [#8525](https://github.com/facebook/docusaurus/pull/8525) chore(theme-translations): complete pl translations +- `docusaurus-plugin-content-blog` + - [#8381](https://github.com/facebook/docusaurus/pull/8381) fix(content-blog): blog Atom feed id + RSS feed guid should be fully qualified urls ([@johnnyreilly](https://github.com/johnnyreilly)) +- `docusaurus-plugin-content-docs` + - [#8275](https://github.com/facebook/docusaurus/pull/8275) fix(content-docs): add trailing slash to contentDirs, before passing it to isMDXPartial ([@denis-alkhelali](https://github.com/denis-alkhelali)) +- `docusaurus-utils` + - [#8314](https://github.com/facebook/docusaurus/pull/8314) fix(utils): allow partially backticked markdown h1 contentTitles ([@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)) +- `create-docusaurus`, `docusaurus-theme-classic` + - [#8279](https://github.com/facebook/docusaurus/pull/8279) fix(create-docusaurus): improve init template misleading doc + add Docuaurus social card ([@slorber](https://github.com/slorber)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic`, `docusaurus` + - [#8445](https://github.com/facebook/docusaurus/pull/8445) fix(theme-classic) extract HomeBreadcrumbItem + fix swizzle bugs ([@3v0k4](https://github.com/3v0k4)) +- `docusaurus-theme-translations` + - [#8423](https://github.com/facebook/docusaurus/pull/8423) fix(translations): complete Chinese theme translations ([@SJFCS](https://github.com/SJFCS)) + - [#8312](https://github.com/facebook/docusaurus/pull/8312) fix(theme-translations): complete Swedish theme translations ([@stnor](https://github.com/stnor)) +- `eslint-plugin` + - [#8281](https://github.com/facebook/docusaurus/pull/8281) feat(eslint-plugin): add plugin to exported configs ([@lachieh](https://github.com/lachieh)) + +#### Committers: 16 + +- Danny Kim ([@0916dhkim](https://github.com/0916dhkim)) +- Denis Al-Khelali ([@denis-alkhelali](https://github.com/denis-alkhelali)) +- Dongjoon Lee ([@Djunnni](https://github.com/Djunnni)) +- Frieder Bluemle ([@friederbluemle](https://github.com/friederbluemle)) +- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) +- Josh Goldberg ([@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Lachlan Heywood ([@lachieh](https://github.com/lachieh)) +- Lane Goolsby ([@lanegoolsby](https://github.com/lanegoolsby)) +- Matija Sirk ([@MatijaSi](https://github.com/MatijaSi)) +- Muhammad Hammad ([@mhnaeem](https://github.com/mhnaeem)) +- Riccardo ([@3v0k4](https://github.com/3v0k4)) +- Stefan Norberg ([@stnor](https://github.com/stnor)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Thomas.CA ([@Thomascogez](https://github.com/Thomascogez)) +- [@mturoci](https://github.com/mturoci) +- 宋锦丰 ([@SJFCS](https://github.com/SJFCS)) + +## 2.2.0 (2022-10-29) + +#### :rocket: New Feature + +- `docusaurus-plugin-client-redirects` + - [#8227](https://github.com/facebook/docusaurus/pull/8227) feat(plugin-client-redirects): keep the query string + hash ([@Xabilahu](https://github.com/Xabilahu)) +- `docusaurus` + - [#8210](https://github.com/facebook/docusaurus/pull/8210) feat(core): add --config param to swizzle command ([@e-im](https://github.com/e-im)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-mermaid`, `docusaurus-types`, `docusaurus` + - [#7490](https://github.com/facebook/docusaurus/pull/7490) feat: support mermaid code blocks in Markdown ([@sjwall](https://github.com/sjwall)) +- `docusaurus-types`, `docusaurus` + - [#8151](https://github.com/facebook/docusaurus/pull/8151) feat(core): siteConfig.headTags API to render extra tags in document head ([@johnnyreilly](https://github.com/johnnyreilly)) + +#### :bug: Bug Fix + +- `docusaurus-plugin-ideal-image` + - [#8250](https://github.com/facebook/docusaurus/pull/8250) fix(ideal-image): do not pass down `img` prop ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-common` + - [#8246](https://github.com/facebook/docusaurus/pull/8246) fix(mdx-loader): properly unwrap mdxAdmonitionTitle placeholder ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs` + - [#8234](https://github.com/facebook/docusaurus/pull/8234) fix(plugin-content-docs): fix error message context (error cause) when doc processing fails ([@shanpriyan](https://github.com/shanpriyan)) +- `docusaurus-theme-classic`, `docusaurus-theme-translations` + - [#8207](https://github.com/facebook/docusaurus/pull/8207) fix(theme-classic): hamburger menu control navigation by keyboard ([@jeferson-sb](https://github.com/jeferson-sb)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#8204](https://github.com/facebook/docusaurus/pull/8204) fix(theme-classic): fix SkipToContent without JS , refactor, make it public theming API ([@mturoci](https://github.com/mturoci)) + - [#8059](https://github.com/facebook/docusaurus/pull/8059) fix(theme): preserve url ?search#hash on navbar version/locale dropdowns navigations ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#8192](https://github.com/facebook/docusaurus/pull/8192) fix(core): throw error for invalid URL in config file ([@forgeRW](https://github.com/forgeRW)) +- `docusaurus-theme-classic` + - [#8174](https://github.com/facebook/docusaurus/pull/8174) fix(theme): announce theme switches ([@mturoci](https://github.com/mturoci)) + - [#8190](https://github.com/facebook/docusaurus/pull/8190) fix(theme): add more tag names to inline code element set ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#8163](https://github.com/facebook/docusaurus/pull/8163) fix(theme): mobile navbar & skipToContent should cover announcementBar ([@adnanhashmi09](https://github.com/adnanhashmi09)) + - [#8068](https://github.com/facebook/docusaurus/pull/8068) fix(theme): preserve line breaks when copying code with showLineNumbers in Firefox ([@LittleboyHarry](https://github.com/LittleboyHarry)) +- `docusaurus-utils` + - [#8137](https://github.com/facebook/docusaurus/pull/8137) fix(utils): remove non-ASCII limitation for path normalization ([@birjj](https://github.com/birjj)) + - [#8158](https://github.com/facebook/docusaurus/pull/8158) fix(content-blog): make RSS feed generation work with slugs with .html extension ([@Pranav2612000](https://github.com/Pranav2612000)) +- `docusaurus-theme-translations` + - [#8105](https://github.com/facebook/docusaurus/pull/8105) fix(theme-translations): complete turkish theme default translations ([@ramazansancar](https://github.com/ramazansancar)) + - [#8087](https://github.com/facebook/docusaurus/pull/8087) fix(theme-translations): remove extra vi translations ([@namnguyenthanhwork](https://github.com/namnguyenthanhwork)) +- `docusaurus-plugin-client-redirects` + - [#8067](https://github.com/facebook/docusaurus/pull/8067) fix(redirect): tolerate trailing slash difference if config is undefined ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :nail_care: Polish + +- `docusaurus-theme-translations` + - [#8253](https://github.com/facebook/docusaurus/pull/8253) chore(theme-translations): complete ru translations ([@lex111](https://github.com/lex111)) + - [#8243](https://github.com/facebook/docusaurus/pull/8243) chore(theme-translations): complete French translations ([@forresst](https://github.com/forresst)) + - [#8075](https://github.com/facebook/docusaurus/pull/8075) fix(theme-translation): complete Japanese theme default translation ([@pasora](https://github.com/pasora)) +- `docusaurus` + - [#8159](https://github.com/facebook/docusaurus/pull/8159) fix(core): throw error for invalid URL in config file ([@forgeRW](https://github.com/forgeRW)) + - [#8109](https://github.com/facebook/docusaurus/pull/8109) feat(core): prefetch on mobile touchstart ([@sanjaiyan-dev](https://github.com/sanjaiyan-dev)) +- `docusaurus-theme-classic` + - [#8161](https://github.com/facebook/docusaurus/pull/8161) fix(theme): do not show tab content when tabbing over it; show after selection only ([@mturoci](https://github.com/mturoci)) + - [#8062](https://github.com/facebook/docusaurus/pull/8062) refactor(theme): remove hard-coded tag border-radius ([@homotechsual](https://github.com/homotechsual)) +- `docusaurus-utils-validation`, `docusaurus` + - [#8066](https://github.com/facebook/docusaurus/pull/8066) fix(core): normalize slashes for url/baseUrl instead of throwing ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### Committers: 22 + +- Adnan Hashmi ([@adnanhashmi09](https://github.com/adnanhashmi09)) +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Forresst ([@forresst](https://github.com/forresst)) +- Jan Peer Stöcklmair ([@JPeer264](https://github.com/JPeer264)) +- Jeferson S. Brito ([@jeferson-sb](https://github.com/jeferson-sb)) +- Johan Fagerberg ([@birjj](https://github.com/birjj)) +- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- LittleboyHarry ([@LittleboyHarry](https://github.com/LittleboyHarry)) +- Masahiko Hara ([@pasora](https://github.com/pasora)) +- Mikey O'Toole ([@homotechsual](https://github.com/homotechsual)) +- Nguyễn Thành Nam ([@namnguyenthanhwork](https://github.com/namnguyenthanhwork)) +- Pranav Joglekar ([@Pranav2612000](https://github.com/Pranav2612000)) +- Ramazan SANCAR ([@ramazansancar](https://github.com/ramazansancar)) +- Sam Wall ([@sjwall](https://github.com/sjwall)) +- Sanjaiyan Parthipan ([@sanjaiyan-dev](https://github.com/sanjaiyan-dev)) +- Shanmughapriyan S ([@shanpriyan](https://github.com/shanpriyan)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Xabier Lahuerta Vazquez ([@Xabilahu](https://github.com/Xabilahu)) +- [@forgeRW](https://github.com/forgeRW) +- [@mturoci](https://github.com/mturoci) +- evan ([@e-im](https://github.com/e-im)) + +## 2.1.0 (2022-09-01) + +#### :rocket: New Feature + +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#8008](https://github.com/facebook/docusaurus/pull/8008) feat(theme): ability to use `` without items prop, on any doc page ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#7963](https://github.com/facebook/docusaurus/pull/7963) feat(docs): allow to configure noIndex per doc version ([@slorber](https://github.com/slorber)) + - [#7949](https://github.com/facebook/docusaurus/pull/7949) feat(plugin-docs): docs sidebar item link: support "autoAddBaseUrl" attribute ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-translations` + - [#7953](https://github.com/facebook/docusaurus/pull/7953) feat(theme): adds Ukrainian default theme translations ([@b-ovsepian](https://github.com/b-ovsepian)) + +#### :bug: Bug Fix + +- `create-docusaurus` + - [#8032](https://github.com/facebook/docusaurus/pull/8032) fix(create-docusaurus): tutorial and init template improvements ([@slorber](https://github.com/slorber)) +- `docusaurus-preset-classic` + - [#8029](https://github.com/facebook/docusaurus/pull/8029) fix(preset-classic): broken link in "unrecognized keys" error message ([@mdubus](https://github.com/mdubus)) +- `docusaurus` + - [#7977](https://github.com/facebook/docusaurus/pull/7977) fix(core): preload should support encoded page links ([@adventure-yunfei](https://github.com/adventure-yunfei)) + - [#7996](https://github.com/facebook/docusaurus/pull/7996) fix(core): CLI command write-translations should extract translations from @docu… ([@slorber](https://github.com/slorber)) + - [#7952](https://github.com/facebook/docusaurus/pull/7952) fix(core): allow overriding ssr/dev template meta tags ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-sitemap` + - [#7964](https://github.com/facebook/docusaurus/pull/7964) fix(sitemap): filter all routes with robots meta containing noindex ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#7910](https://github.com/facebook/docusaurus/pull/7910) fix(theme-classic): code block line number display with line wrapping ([@yzhe819](https://github.com/yzhe819)) + - [#7786](https://github.com/facebook/docusaurus/pull/7786) fix: collapse siblings when first category is selected ([@whiteand](https://github.com/whiteand)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#7982](https://github.com/facebook/docusaurus/pull/7982) fix(theme): add aria-label to skip to content link region ([@YoniChechik](https://github.com/YoniChechik)) + - [#7940](https://github.com/facebook/docusaurus/pull/7940) refactor(theme-classic): split AnnouncementBar, increase z-index, use shadow ([@slorber](https://github.com/slorber)) + - [#7876](https://github.com/facebook/docusaurus/pull/7876) refactor(theme-classic): make tag text visually certered ([@Kosai106](https://github.com/Kosai106)) +- `docusaurus-utils` + - [#7941](https://github.com/facebook/docusaurus/pull/7941) feat(core): add new Webpack file-loader extensions: avif, mov, mkv, mpg, avi... ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-types` + - [#7942](https://github.com/facebook/docusaurus/pull/7942) feat(theme-classic): use lang attribute in navbar locale dropdown items ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-translations` + - [#7928](https://github.com/facebook/docusaurus/pull/7928) chore(theme-translations): complete vi translations ([@datlechin](https://github.com/datlechin)) + +#### :memo: Documentation + +- `create-docusaurus` + - [#8032](https://github.com/facebook/docusaurus/pull/8032) fix(create-docusaurus): tutorial and init template improvements ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic` + - [#7905](https://github.com/facebook/docusaurus/pull/7905) docs: remove mention of beta ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### Committers: 10 + +- Bagdasar Ovsepyan ([@b-ovsepian](https://github.com/b-ovsepian)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Kevin Østerkilde ([@Kosai106](https://github.com/Kosai106)) +- Morgane Dubus ([@mdubus](https://github.com/mdubus)) +- Ngô Quốc Đạt ([@datlechin](https://github.com/datlechin)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Yoni Chechik ([@YoniChechik](https://github.com/YoniChechik)) +- [@whiteand](https://github.com/whiteand) +- [@yzhe819](https://github.com/yzhe819) +- adventure-yunfei ([@adventure-yunfei](https://github.com/adventure-yunfei)) + +## 2.0.1 (2022-08-01) + +Fix bad npm publish of 2.0.0 + +#### Committers: 1 + +- Sébastien Lorber ([@slorber](https://github.com/slorber)) + +## 2.0.0 (2022-08-01) + +Bad npm publish, please use 2.0.1 + +#### :nail_care: Polish + +- `docusaurus` + - [#7781](https://github.com/facebook/docusaurus/pull/7781) refactor(core): log Docusaurus & Node version before exiting ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### Committers: 2 + +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) + +## 2.0.0-rc.1 (2022-07-14) + +#### :bug: Bug Fix + +- `docusaurus` + - [#7776](https://github.com/facebook/docusaurus/pull/7776) fix(core): swizzle --eject js should not copy theme .d.ts files ([@slorber](https://github.com/slorber)) + - [#7750](https://github.com/facebook/docusaurus/pull/7750) fix(deploy): revert "feat(deploy): copy local git config to tmp repo (#7702)" ([@ghostsquad](https://github.com/ghostsquad)) +- `docusaurus-plugin-sitemap` + - [#7774](https://github.com/facebook/docusaurus/pull/7774) fix(sitemap): complete gracefully when all pages have noIndex meta ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#7771](https://github.com/facebook/docusaurus/pull/7771) chore: bump Infima to 0.2.0-alpha.42, fix a:hover link bug ([@slorber](https://github.com/slorber)) + - [#7755](https://github.com/facebook/docusaurus/pull/7755) fix(theme-classic): validate options properly ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7752](https://github.com/facebook/docusaurus/pull/7752) fix(theme-classic): fix Layout theme height CSS ([@LichLord91](https://github.com/LichLord91)) +- `docusaurus-migrate` + - [#7766](https://github.com/facebook/docusaurus/pull/7766) fix(migrate): import siteConfig with file extension ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-search-algolia` + - [#7761](https://github.com/facebook/docusaurus/pull/7761) fix(algolia-search): test for canUseIntersectionObserver ([@RoiArthurB](https://github.com/RoiArthurB)) + +#### :nail_care: Polish + +- `docusaurus-theme-translations` + - [#7762](https://github.com/facebook/docusaurus/pull/7762) chore(theme-translations): complete ko translations ([@anaclumos](https://github.com/anaclumos)) + +#### :memo: Documentation + +- `docusaurus-plugin-content-docs` + - [#7706](https://github.com/facebook/docusaurus/pull/7706) docs: release process, versioning, breaking changes, public API surface ([@slorber](https://github.com/slorber)) + +#### :wrench: Maintenance + +- `docusaurus-theme-classic` + - [#7777](https://github.com/facebook/docusaurus/pull/7777) refactor(theme): fix duplicate page metadata usage ([@slorber](https://github.com/slorber)) + - [#7771](https://github.com/facebook/docusaurus/pull/7771) chore: bump Infima to 0.2.0-alpha.42, fix a:hover link bug ([@slorber](https://github.com/slorber)) + +#### Committers: 11 + +- Arthur Brugière ([@RoiArthurB](https://github.com/RoiArthurB)) +- Bruce Song ([@recallwei](https://github.com/recallwei)) +- Evan ([@DigiPie](https://github.com/DigiPie)) +- Jeffrey Aven ([@jeffreyaven](https://github.com/jeffreyaven)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Sunghyun Cho ([@anaclumos](https://github.com/anaclumos)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- The Nguyen ([@treoden](https://github.com/treoden)) +- Wes McNamee ([@ghostsquad](https://github.com/ghostsquad)) +- [@LichLord91](https://github.com/LichLord91) +- 凱恩 Kane ([@Gary50613](https://github.com/Gary50613)) + +## 2.0.0-beta.22 (2022-07-08) + +#### :boom: Breaking Change + +- `docusaurus-theme-classic` + - [#7740](https://github.com/facebook/docusaurus/pull/7740) refactor(theme): nest theme icons under subfolder @theme/Icon/\* ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#7716](https://github.com/facebook/docusaurus/pull/7716) refactor(theme): split BlogPostItem into smaller theme subcomponents ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia` + - [#7660](https://github.com/facebook/docusaurus/pull/7660) refactor(theme-common): split package into public/internal API entrypoints ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#7644](https://github.com/facebook/docusaurus/pull/7644) refactor(docs,theme): split DocItem comp, useDoc hook ([@slorber](https://github.com/slorber)) +- `docusaurus-logger`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#7642](https://github.com/facebook/docusaurus/pull/7642) refactor: remove "error" reporting level, move reportMessage to logger ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-utils-validation`, `docusaurus` + - [#7152](https://github.com/facebook/docusaurus/pull/7152) refactor: handle all admonitions via JSX component ([@lex111](https://github.com/lex111)) + +#### :rocket: New Feature + +- `docusaurus-theme-translations` + - [#7732](https://github.com/facebook/docusaurus/pull/7732) feat(theme-translations): Dutch translation ([@reinvanhaaren](https://github.com/reinvanhaaren)) + - [#7715](https://github.com/facebook/docusaurus/pull/7715) feat(theme-translations): Swedish translation ([@johnie](https://github.com/johnie)) +- `docusaurus-theme-search-algolia`, `docusaurus-theme-translations` + - [#7666](https://github.com/facebook/docusaurus/pull/7666) feat(algolia-search): allow translating search modal ([@forresst](https://github.com/forresst)) +- `create-docusaurus`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#7643](https://github.com/facebook/docusaurus/pull/7643) feat(theme-classic): themeConfig navbar/footer logos accept className/style + update Meta Open-Source Logo ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects` + - [#7649](https://github.com/facebook/docusaurus/pull/7649) feat(client-redirects): make plugin respect onDuplicateRoutes config ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#7624](https://github.com/facebook/docusaurus/pull/7624) feat: allow customizing localization path of each locale ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#7581](https://github.com/facebook/docusaurus/pull/7581) feat(core): allow opting out of HTML minification ([@alexandernst](https://github.com/alexandernst)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#7557](https://github.com/facebook/docusaurus/pull/7557) feat: allow specifying custom target for FooterLogo ([@vannyle](https://github.com/vannyle)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-translations` + - [#7556](https://github.com/facebook/docusaurus/pull/7556) feat: add admonition type title translations ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#7386](https://github.com/facebook/docusaurus/pull/7386) feat(core): allow customizing the i18n directory path ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-live-codeblock` + - [#7514](https://github.com/facebook/docusaurus/pull/7514) feat(live-codeblock): add support for noInline to interactive code blocks ([@jpdriver](https://github.com/jpdriver)) +- `docusaurus-plugin-content-docs` + - [#7461](https://github.com/facebook/docusaurus/pull/7461) feat(content-docs): last_update front matter ([@dpang314](https://github.com/dpang314)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#7727](https://github.com/facebook/docusaurus/pull/7727) fix(theme): show blog post edit link even when no tag & not truncated ([@anaclumos](https://github.com/anaclumos)) + - [#7659](https://github.com/facebook/docusaurus/pull/7659) fix(theme-classic): expose empty string alt text in navbar logos ([@BenDMyers](https://github.com/BenDMyers)) + - [#7595](https://github.com/facebook/docusaurus/pull/7595) fix(content-pages): add article wrapper around MDXContent ([@matkoch](https://github.com/matkoch)) +- `docusaurus-theme-translations` + - [#7694](https://github.com/facebook/docusaurus/pull/7694) fix(theme-translations): typo in vi locale ([@saosangmo](https://github.com/saosangmo)) +- `docusaurus-plugin-content-docs` + - [#7638](https://github.com/facebook/docusaurus/pull/7638) fix(docs): forward doc frontMatter.sidebar_custom_props to linking sidebar category ([@slorber](https://github.com/slorber)) + - [#7634](https://github.com/facebook/docusaurus/pull/7634) fix(content-docs): allow translating doc labels in sidebars.js ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-utils` + - [#7604](https://github.com/facebook/docusaurus/pull/7604) fix(utils): allow any non-boundary characters in Markdown heading ID ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-cssnano-preset` + - [#7593](https://github.com/facebook/docusaurus/pull/7593) fix(cssnano-preset): disable z-index minification ([@dpang314](https://github.com/dpang314)) +- `docusaurus-theme-common` + - [#7551](https://github.com/facebook/docusaurus/pull/7551) fix(theme-classic): code block wrap mode should allow wrapping in the middle of a word ([@slorber](https://github.com/slorber)) + - [#7485](https://github.com/facebook/docusaurus/pull/7485) fix(theme-classic): inconsistent code block wrapping ([@dpang314](https://github.com/dpang314)) +- `docusaurus-mdx-loader`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils` + - [#7521](https://github.com/facebook/docusaurus/pull/7521) fix: make type-checking work in Yarn PnP ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :nail_care: Polish + +- `docusaurus-theme-translations` + - [#7696](https://github.com/facebook/docusaurus/pull/7696) fix(theme-translations): improve grammar of zh translation ([@AkagiYui](https://github.com/AkagiYui)) + - [#7691](https://github.com/facebook/docusaurus/pull/7691) chore(theme-translations): complete vi translations ([@datlechin](https://github.com/datlechin)) + - [#7683](https://github.com/facebook/docusaurus/pull/7683) chore(theme-translations): complete ar translations ([@Altomy](https://github.com/Altomy)) + - [#7633](https://github.com/facebook/docusaurus/pull/7633) chore(theme-translations): complete ko translations ([@HyunseungLee-Travis](https://github.com/HyunseungLee-Travis)) +- `docusaurus` + - [#7702](https://github.com/facebook/docusaurus/pull/7702) feat(deploy): copy local git config to tmp repo ([@ghostsquad](https://github.com/ghostsquad)) + - [#7600](https://github.com/facebook/docusaurus/pull/7600) fix: force refresh on chunk preload error ([@yangshun](https://github.com/yangshun)) +- `docusaurus-plugin-content-docs` + - [#7673](https://github.com/facebook/docusaurus/pull/7673) fix(content-docs): format last update date as "Jun 19, 2020" ([@sigwinch28](https://github.com/sigwinch28)) +- `docusaurus-theme-common`, `docusaurus-theme-search-algolia` + - [#7671](https://github.com/facebook/docusaurus/pull/7671) refactor(theme-common): rename useDynamicCallback to useEvent ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-common` + - [#7648](https://github.com/facebook/docusaurus/pull/7648) fix(theme-common): make useShallowMemoObject key-order-insensitive ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus` + - [#7639](https://github.com/facebook/docusaurus/pull/7639) chore(create): update the facebook template with current assets ([@zpao](https://github.com/zpao)) + - [#7520](https://github.com/facebook/docusaurus/pull/7520) feat: add engines field to templates' package.json ([@johnnyreilly](https://github.com/johnnyreilly)) +- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus` + - [#7579](https://github.com/facebook/docusaurus/pull/7579) refactor(pwa): simplify registerSW code, fix ESLint errors ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag` + - [#7545](https://github.com/facebook/docusaurus/pull/7545) feat(analytics): allow query/hash changes to be sent to GA ([@lanegoolsby](https://github.com/lanegoolsby)) + +#### :memo: Documentation + +- Other + - [#7739](https://github.com/facebook/docusaurus/pull/7739) docs: swizzle react-live with eject ([@SheetJSDev](https://github.com/SheetJSDev)) + - [#7723](https://github.com/facebook/docusaurus/pull/7723) docs: add GitHub pages deployment troubleshooting guide ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7705](https://github.com/facebook/docusaurus/pull/7705) docs: mention MDXContent ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7675](https://github.com/facebook/docusaurus/pull/7675) docs: add docusaurus-openapi-docs to resources ([@sserrata](https://github.com/sserrata)) + - [#7677](https://github.com/facebook/docusaurus/pull/7677) docs: add more info on github cross repo deployment ([@bcabanes](https://github.com/bcabanes)) + - [#7563](https://github.com/facebook/docusaurus/pull/7563) docs: add awesome-docusaurus resource ([@webbertakken](https://github.com/webbertakken)) + - [#7665](https://github.com/facebook/docusaurus/pull/7665) docs: add link from every category index page to the guide page ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7519](https://github.com/facebook/docusaurus/pull/7519) docs: multiple documentation elaborations ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7518](https://github.com/facebook/docusaurus/pull/7518) docs: remove useless front matter ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7512](https://github.com/facebook/docusaurus/pull/7512) docs: update Kent C. Dodds Twitter avatar ([@DharsanB](https://github.com/DharsanB)) +- `create-docusaurus` + - [#7611](https://github.com/facebook/docusaurus/pull/7611) docs: advise using Node 18 in deployment ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7582](https://github.com/facebook/docusaurus/pull/7582) docs: make localhost links clickable ([@dht](https://github.com/dht)) +- `docusaurus-plugin-client-redirects` + - [#7607](https://github.com/facebook/docusaurus/pull/7607) refactor(client-redirects): elaborate documentation, minor refactor ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :wrench: Maintenance + +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#7676](https://github.com/facebook/docusaurus/pull/7676) refactor(theme): move LayoutProviders to Layout/Provider; composeProviders util ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#7674](https://github.com/facebook/docusaurus/pull/7674) chore: prevent importing theme components with relative paths ([@slorber](https://github.com/slorber)) + - [#7664](https://github.com/facebook/docusaurus/pull/7664) chore: upgrade Infima to alpha.40 ([@slorber](https://github.com/slorber)) +- Other + - [#7663](https://github.com/facebook/docusaurus/pull/7663) misc: share .vscode/extensions.json ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#7583](https://github.com/facebook/docusaurus/pull/7583) refactor(cli): make the CLI an even thinner wrapper around command functions ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7547](https://github.com/facebook/docusaurus/pull/7547) chore: update static-site-generator-webpack-plugin ([@slorber](https://github.com/slorber)) +- `create-docusaurus`, `docusaurus-cssnano-preset`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `eslint-plugin`, `lqip-loader`, `stylelint-copyright` + - [#7586](https://github.com/facebook/docusaurus/pull/7586) chore: upgrade to TS 4.7, compile with NodeNext ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### Committers: 51 + +- 7Wate ([@7Wate](https://github.com/7Wate)) +- Ahmed Altomy ([@Altomy](https://github.com/Altomy)) +- Alexander Nestorov ([@alexandernst](https://github.com/alexandernst)) +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Ben Myers ([@BenDMyers](https://github.com/BenDMyers)) +- Benjamin Cabanes ([@bcabanes](https://github.com/bcabanes)) +- Boulet ([@Boulet-](https://github.com/Boulet-)) +- Charles Ancheta ([@cbebe](https://github.com/cbebe)) +- Clemie McCartney ([@clemiee](https://github.com/clemiee)) +- DOLLE ([@JeremyDolle](https://github.com/JeremyDolle)) +- Dharsan B ([@DharsanB](https://github.com/DharsanB)) +- Diego França ([@difranca](https://github.com/difranca)) +- Dima Grossman ([@scopsy](https://github.com/scopsy)) +- Dzung Do ([@saosangmo](https://github.com/saosangmo)) +- Flávio Silva ([@201flaviosilva](https://github.com/201flaviosilva)) +- Forresst ([@forresst](https://github.com/forresst)) +- Huy Nguyen ([@Smilefounder](https://github.com/Smilefounder)) +- Hyunseung Lee ([@HyunseungLee-Travis](https://github.com/HyunseungLee-Travis)) +- JP ([@jpdriver](https://github.com/jpdriver)) +- Joe Harrison ([@sigwinch28](https://github.com/sigwinch28)) +- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) +- Johnie Hjelm ([@johnie](https://github.com/johnie)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Joshua Schmitt ([@jqshuv](https://github.com/jqshuv)) +- Kürşat Şimşek ([@kursatsmsek](https://github.com/kursatsmsek)) +- Lane Goolsby ([@lanegoolsby](https://github.com/lanegoolsby)) +- Le Thi Van ([@vannyle](https://github.com/vannyle)) +- Matthias Koch ([@matkoch](https://github.com/matkoch)) +- Ngô Quốc Đạt ([@datlechin](https://github.com/datlechin)) +- Paul O’Shannessy ([@zpao](https://github.com/zpao)) +- Redcamel ([@redcamel](https://github.com/redcamel)) +- Rein van Haaren ([@reinvanhaaren](https://github.com/reinvanhaaren)) +- Rudra Sen ([@RudraSen2](https://github.com/RudraSen2)) +- Steven Serrata ([@sserrata](https://github.com/sserrata)) +- Sunghyun Cho ([@anaclumos](https://github.com/anaclumos)) +- Szilárd Dóró ([@szilarddoro](https://github.com/szilarddoro)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tom Mrazauskas ([@mrazauskas](https://github.com/mrazauskas)) +- Webber Takken ([@webbertakken](https://github.com/webbertakken)) +- Wes McNamee ([@ghostsquad](https://github.com/ghostsquad)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) +- [@SheetJSDev](https://github.com/SheetJSDev) +- [@alewolf](https://github.com/alewolf) +- [@dpang314](https://github.com/dpang314) +- dht ([@dht](https://github.com/dht)) +- emattia ([@emattia](https://github.com/emattia)) +- pincman ([@pincman](https://github.com/pincman)) +- sado ([@sado0823](https://github.com/sado0823)) +- 凱恩 Kane ([@Gary50613](https://github.com/Gary50613)) +- 李小雨 ([@metal-young](https://github.com/metal-young)) +- 赤城结衣 ([@AkagiYui](https://github.com/AkagiYui)) + +## 2.0.0-beta.21 (2022-05-27) + +#### :boom: Breaking Change + +- `docusaurus-plugin-pwa` + - [#7422](https://github.com/facebook/docusaurus/pull/7422) refactor(pwa): remove reloadPopup option in favor of swizzling ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-cssnano-preset`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `eslint-plugin`, `lqip-loader` + - [#7501](https://github.com/facebook/docusaurus/pull/7501) chore: require Node 16.14 ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :rocket: New Feature + +- `docusaurus-plugin-sitemap` + - [#7469](https://github.com/facebook/docusaurus/pull/7469) feat(sitemap): allow customizing the output name ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-utils`, `docusaurus` + - [#7371](https://github.com/facebook/docusaurus/pull/7371) feat(core): support docusaurus.config.cjs as default file name ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#7500](https://github.com/facebook/docusaurus/pull/7500) feat: make docusaurus serve automatically open in browser ([@Zamiell](https://github.com/Zamiell)) + - [#7452](https://github.com/facebook/docusaurus/pull/7452) feat: add --no-minify flag to docusaurus start ([@lanegoolsby](https://github.com/lanegoolsby)) +- `docusaurus-theme-classic` + - [#7357](https://github.com/facebook/docusaurus/pull/7357) feat(theme-classic): allow className as option for type: "search" ([@JPeer264](https://github.com/JPeer264)) + +#### :bug: Bug Fix + +- `docusaurus` + - [#7362](https://github.com/facebook/docusaurus/pull/7362) fix: always emit SEO title + og:title meta ([@charleskorn](https://github.com/charleskorn)) + - [#7453](https://github.com/facebook/docusaurus/pull/7453) fix(core): avoid using logger and fs.readJSON in SSR ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7369](https://github.com/facebook/docusaurus/pull/7369) fix(cli): output correct path when swizzling bare-file component in subfolder ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7360](https://github.com/facebook/docusaurus/pull/7360) fix(core): allow githubPort in config validation ([@mhughes2k](https://github.com/mhughes2k)) +- `docusaurus-plugin-google-gtag` + - [#7424](https://github.com/facebook/docusaurus/pull/7424) fix(gtag): send the newly rendered page's title instead of the old one's ([@ori-shalom](https://github.com/ori-shalom)) +- `create-docusaurus`, `docusaurus-utils` + - [#7507](https://github.com/facebook/docusaurus/pull/7507) fix(create-docusaurus): potential security issue with command injection ([@slorber](https://github.com/slorber)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus` + - [#7492](https://github.com/facebook/docusaurus/pull/7492) fix(core): always treat error boundary fallback as a callback ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#7438](https://github.com/facebook/docusaurus/pull/7438) fix(theme-classic): allow nested task lists to preserve the indent ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7430](https://github.com/facebook/docusaurus/pull/7430) fix(theme-classic): consistently apply the right active class name for all navbar items ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7411](https://github.com/facebook/docusaurus/pull/7411) fix(theme-classic): autocollapse sidebar categories when navigating with paginator ([@pranabdas](https://github.com/pranabdas)) + - [#7363](https://github.com/facebook/docusaurus/pull/7363) fix(theme-classic): resolve customCss from site dir ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-utils` + - [#7464](https://github.com/facebook/docusaurus/pull/7464) fix(utils): fix Markdown link replacement when link text is same as href ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7458](https://github.com/facebook/docusaurus/pull/7458) fix(utils): avoid replacing Markdown links missing the directly next link ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader` + - [#7392](https://github.com/facebook/docusaurus/pull/7392) fix(mdx-loader): use React.Fragment as fragment factory ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs` + - [#7385](https://github.com/facebook/docusaurus/pull/7385) fix(content-docs): restore functionality when a category only has index page ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :nail_care: Polish + +- `docusaurus-theme-translations` + - [#7493](https://github.com/facebook/docusaurus/pull/7493) chore(theme-translations): complete French translations ([@forresst](https://github.com/forresst)) + - [#7474](https://github.com/facebook/docusaurus/pull/7474) chore(theme-translations): complete zh translations ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7400](https://github.com/facebook/docusaurus/pull/7400) chore(theme-translations): complete Farsi translations ([@massoudmaboudi](https://github.com/massoudmaboudi)) +- `docusaurus` + - [#7499](https://github.com/facebook/docusaurus/pull/7499) fix: avoid printing period after localhost URL ([@Zamiell](https://github.com/Zamiell)) +- `create-docusaurus` + - [#7374](https://github.com/facebook/docusaurus/pull/7374) refactor(create): clean up logic when prompting for unspecified arguments ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :memo: Documentation + +- [#7503](https://github.com/facebook/docusaurus/pull/7503) docs: document MDXComponents scope ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#7497](https://github.com/facebook/docusaurus/pull/7497) docs: link every reference of types in API table to the type definition ([@Zamiell](https://github.com/Zamiell)) +- [#7407](https://github.com/facebook/docusaurus/pull/7407) docs: add Azure SWA as deployment option ([@nitya](https://github.com/nitya)) +- [#7390](https://github.com/facebook/docusaurus/pull/7390) fix(website): use react-lite-youtube-embed for lazy YouTube video ([@matkoch](https://github.com/matkoch)) + +#### :wrench: Maintenance + +- `create-docusaurus`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` + - [#7477](https://github.com/facebook/docusaurus/pull/7477) refactor: fix a lot of errors in type-aware linting ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-translations` + - [#7447](https://github.com/facebook/docusaurus/pull/7447) refactor(theme-classic): migrate to tsc for build ([@Josh-Cena](https://github.com/Josh-Cena)) +- `stylelint-copyright` + - [#7441](https://github.com/facebook/docusaurus/pull/7441) refactor(stylelint-copyright): migrate to TS ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-cssnano-preset` + - [#7440](https://github.com/facebook/docusaurus/pull/7440) refactor(cssnano-preset): migrate to TS ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `eslint-plugin`, `lqip-loader` + - [#7437](https://github.com/facebook/docusaurus/pull/7437) refactor: use TS project references instead of running tsc multiple times ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-pwa` + - [#7421](https://github.com/facebook/docusaurus/pull/7421) refactor(pwa): migrate client modules to TS ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#7415](https://github.com/facebook/docusaurus/pull/7415) refactor(theme-classic): always collocate stylesheets with components in one folder ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#7405](https://github.com/facebook/docusaurus/pull/7405) refactor(core): properly code-split NotFound page ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### Committers: 23 + +- Akara ([@Messiahhh](https://github.com/Messiahhh)) +- Benjamin Diolez ([@BenDz](https://github.com/BenDz)) +- Charles Korn ([@charleskorn](https://github.com/charleskorn)) +- Designatory ([@Designatory](https://github.com/Designatory)) +- Forresst ([@forresst](https://github.com/forresst)) +- Ggicci ([@ggicci](https://github.com/ggicci)) +- James ([@Zamiell](https://github.com/Zamiell)) +- Jan Peer Stöcklmair ([@JPeer264](https://github.com/JPeer264)) +- Jeremy ([@jrmyw92](https://github.com/jrmyw92)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Junjie ([@junjieweb](https://github.com/junjieweb)) +- Lane Goolsby ([@lanegoolsby](https://github.com/lanegoolsby)) +- Massoud Maboudi ([@massoudmaboudi](https://github.com/massoudmaboudi)) +- Matthias Koch ([@matkoch](https://github.com/matkoch)) +- Michael Hughes ([@mhughes2k](https://github.com/mhughes2k)) +- Ngô Quốc Đạt ([@datlechin](https://github.com/datlechin)) +- Nitya Narasimhan ([@nitya](https://github.com/nitya)) +- Oluwatobi Sofela ([@oluwatobiss](https://github.com/oluwatobiss)) +- Ori Shalom ([@ori-shalom](https://github.com/ori-shalom)) +- Pranab Das ([@pranabdas](https://github.com/pranabdas)) +- Rui Peres ([@RuiAAPeres](https://github.com/RuiAAPeres)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- 凱恩 Kane ([@Gary50613](https://github.com/Gary50613)) + +## 2.0.0-beta.20 (2022-05-05) + +#### :bug: Bug Fix + +- `docusaurus` + - [#7342](https://github.com/facebook/docusaurus/pull/7342) fix: avoid flash of page scrolling to top on refresh ([@slorber](https://github.com/slorber)) + - [#7329](https://github.com/facebook/docusaurus/pull/7329) fix(core): inject docusaurus version into SSR as local ([@RDIL](https://github.com/RDIL)) +- `docusaurus-theme-classic` + - [#7341](https://github.com/facebook/docusaurus/pull/7341) fix(theme-classic): properly highlight code block line numbers ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :memo: Documentation + +- [#7334](https://github.com/facebook/docusaurus/pull/7334) feat(website): make canary release page display actual canary version name ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#7343](https://github.com/facebook/docusaurus/pull/7343) docs: add page for create-docusaurus API documentation ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#7340](https://github.com/facebook/docusaurus/pull/7340) docs: add Yandex Metrika plugin to community plugins ([@sgromkov](https://github.com/sgromkov)) +- [#7336](https://github.com/facebook/docusaurus/pull/7336) fix(website): fix multiple accessibility issues around color contrast ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#7327](https://github.com/facebook/docusaurus/pull/7327) docs: add clarity to versioning behavior ([@pepopowitz](https://github.com/pepopowitz)) + +#### Committers: 6 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Reece Dunham ([@RDIL](https://github.com/RDIL)) +- Sergey Gromkov ([@sgromkov](https://github.com/sgromkov)) +- Steven Hicks ([@pepopowitz](https://github.com/pepopowitz)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) + +## 2.0.0-beta.19 (2022-05-04) + +#### :rocket: New Feature + +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#7178](https://github.com/facebook/docusaurus/pull/7178) feat(theme-classic): extensible code block magic comment system ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7007](https://github.com/facebook/docusaurus/pull/7007) feat(theme-classic): code block showLineNumbers ([@lex111](https://github.com/lex111)) + - [#7012](https://github.com/facebook/docusaurus/pull/7012) feat(theme-classic): show blog sidebar on mobile ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus`, `eslint-plugin` + - [#7206](https://github.com/facebook/docusaurus/pull/7206) feat: Docusaurus ESLint plugin to enforce best Docusaurus practices ([@elias-pap](https://github.com/elias-pap)) +- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#6732](https://github.com/facebook/docusaurus/pull/6732) feat(core): rework client modules lifecycles, officially make API public ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#7231](https://github.com/facebook/docusaurus/pull/7231) feat: allow custom navbarItem types to pass through validation ([@slorber](https://github.com/slorber)) + - [#7058](https://github.com/facebook/docusaurus/pull/7058) feat(theme-classic): new 'html' type navbar item ([@lex111](https://github.com/lex111)) + - [#7079](https://github.com/facebook/docusaurus/pull/7079) feat: allow using pure HTML as label in navbar links ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-translations` + - [#7036](https://github.com/facebook/docusaurus/pull/7036) feat(theme-classic): toggle code wrap button ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6457](https://github.com/facebook/docusaurus/pull/6457) feat(content-docs): draft docs excluded from build & sidebars ([@jodyheavener](https://github.com/jodyheavener)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` + - [#6430](https://github.com/facebook/docusaurus/pull/6430) feat: allow setting calendar for i18n date formatting ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` + - [#7083](https://github.com/facebook/docusaurus/pull/7083) feat(core): fail-safe global data fetching ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs` + - [#7106](https://github.com/facebook/docusaurus/pull/7106) feat(content-docs): make docs:version command work on localized docs ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-types`, `docusaurus` + - [#7082](https://github.com/facebook/docusaurus/pull/7082) feat(core): allow plugins to declare custom route context ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7124](https://github.com/facebook/docusaurus/pull/7124) feat(core): allow plugin/preset config to contain false/null ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-sitemap`, `docusaurus-utils` + - [#6979](https://github.com/facebook/docusaurus/pull/6979) feat(sitemap): add ignorePatterns option ([@ApsarasX](https://github.com/ApsarasX)) + +#### :boom: Breaking Change + +- `docusaurus-types`, `docusaurus` + - [#7257](https://github.com/facebook/docusaurus/pull/7257) refactor: remove long-deprecated routesLoaded lifecycle ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#7277](https://github.com/facebook/docusaurus/pull/7277) refactor(theme-classic): move all sidebar-related config under themeConfig.docs.sidebar ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#6732](https://github.com/facebook/docusaurus/pull/6732) feat(core): rework client modules lifecycles, officially make API public ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-theme-classic` + - [#7176](https://github.com/facebook/docusaurus/pull/7176) refactor: customize code block line highlight color via CSS var ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils` + - [#7117](https://github.com/facebook/docusaurus/pull/7117) refactor(content-{blog,docs}): unify handling of tags ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#7027](https://github.com/facebook/docusaurus/pull/7027) refactor(content-docs): deduplicate types, JSDoc for some APIs ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#7304](https://github.com/facebook/docusaurus/pull/7304) fix(theme-classic): remove breadcrumb items without href from microdata ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7179](https://github.com/facebook/docusaurus/pull/7179) fix(theme-classic): do not add microdata item prop to trailing breadcrumb ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7173](https://github.com/facebook/docusaurus/pull/7173) fix(theme-classic): admonition title: disable text-transform on inline code blocks ([@chelproc](https://github.com/chelproc)) + - [#7048](https://github.com/facebook/docusaurus/pull/7048) fix(theme-classic): add caret for dropdown on mobile ([@lex111](https://github.com/lex111)) + - [#7025](https://github.com/facebook/docusaurus/pull/7025) fix: make docs page wrapper take full height ([@lex111](https://github.com/lex111)) + - [#7013](https://github.com/facebook/docusaurus/pull/7013) fix(theme-classic): adjust shadow on code block ([@chernodub](https://github.com/chernodub)) + - [#7015](https://github.com/facebook/docusaurus/pull/7015) fix(theme-classic): do not add caret for non-collapsible categories ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic` + - [#7294](https://github.com/facebook/docusaurus/pull/7294) fix(\*): make TypeScript realize that each plugin package has a default export ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#7285](https://github.com/facebook/docusaurus/pull/7285) fix(core): allow empty static directories ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7180](https://github.com/facebook/docusaurus/pull/7180) fix: pass pollOptions to webpack ([@JohnnyMcWeed](https://github.com/JohnnyMcWeed)) + - [#7184](https://github.com/facebook/docusaurus/pull/7184) fix(core): prevent 404 when accessing /page.html ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7225](https://github.com/facebook/docusaurus/pull/7225) fix: allow swizzling a component's parent folder ([@slorber](https://github.com/slorber)) + - [#7066](https://github.com/facebook/docusaurus/pull/7066) fix(core): all plugin lifecycles should receive translated content ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs` + - [#7233](https://github.com/facebook/docusaurus/pull/7233) fix(content-docs): make category index text translatable ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-common` + - [#7200](https://github.com/facebook/docusaurus/pull/7200) fix(theme-common): do not persist color mode for OS-triggered changes ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7057](https://github.com/facebook/docusaurus/pull/7057) fix(theme-common): use native scrolling when smooth behavior set in CSS ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7033](https://github.com/facebook/docusaurus/pull/7033) fix(theme): only parse HTML- and JSX-style comments in MD code ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog` + - [#7212](https://github.com/facebook/docusaurus/pull/7212) fix(content-blog): make footnote reference DOM ID unique on post listing page ([@AkiraVoid](https://github.com/AkiraVoid)) +- `docusaurus-utils`, `docusaurus` + - [#7187](https://github.com/facebook/docusaurus/pull/7187) fix(core): handle case where package.json is not available at CWD ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-translations` + - [#7222](https://github.com/facebook/docusaurus/pull/7222) fix(theme-translations): fix invalid pluralization in cs ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7166](https://github.com/facebook/docusaurus/pull/7166) fix(theme-translations): always try all possible locale resolutions ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#7164](https://github.com/facebook/docusaurus/pull/7164) fix: adjust spacing for custom search properly ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-debug`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-types`, `docusaurus` + - [#7143](https://github.com/facebook/docusaurus/pull/7143) fix(sitemap): exclude pages with robots noindex from sitemap ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-types` + - [#7078](https://github.com/facebook/docusaurus/pull/7078) fix(create): install types for JS template as well ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-utils` + - [#7043](https://github.com/facebook/docusaurus/pull/7043) fix(utils): parse Markdown headings with CRLF line break ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils`, `docusaurus` + - [#7023](https://github.com/facebook/docusaurus/pull/7023) refactor: fix a few places of path handling ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-types` + - [#7014](https://github.com/facebook/docusaurus/pull/7014) fix(types): declare history and react-loadable as dependencies ([@sulu5890](https://github.com/sulu5890)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic`, `docusaurus-theme-translations` + - [#7299](https://github.com/facebook/docusaurus/pull/7299) refactor: minor improvements for breadcrumbs ([@lex111](https://github.com/lex111)) +- `create-docusaurus` + - [#7290](https://github.com/facebook/docusaurus/pull/7290) refactor(create): add i18n config in init template ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7286](https://github.com/facebook/docusaurus/pull/7286) refactor(create): update screenshots in quick start tutorial ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7223](https://github.com/facebook/docusaurus/pull/7223) refactor: use generated-index in init templates ([@slorber](https://github.com/slorber)) + - [#7118](https://github.com/facebook/docusaurus/pull/7118) refactor(create): mention that the edit links can be removed ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-debug`, `docusaurus-theme-classic` + - [#7306](https://github.com/facebook/docusaurus/pull/7306) chore: upgrade Infima to alpha.39 ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-debug`, `docusaurus-types`, `docusaurus` + - [#7291](https://github.com/facebook/docusaurus/pull/7291) feat(types): JSDoc for docusaurus config fields ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#7267](https://github.com/facebook/docusaurus/pull/7267) fix(theme-common): allow details to not provide a summary ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7172](https://github.com/facebook/docusaurus/pull/7172) refactor: control base styling of code blocks via CSS vars ([@lex111](https://github.com/lex111)) + - [#7129](https://github.com/facebook/docusaurus/pull/7129) refactor(theme-classic): fix a few margin inconsistencies ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs`, `docusaurus-utils` + - [#7248](https://github.com/facebook/docusaurus/pull/7248) refactor: normalize Markdown linkification behavior, elaborate in documentation ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#7244](https://github.com/facebook/docusaurus/pull/7244) refactor: semantic markup improvement, fix validation warnings ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7183](https://github.com/facebook/docusaurus/pull/7183) refactor: use SVG icon for home breadcrumb ([@Dr-Electron](https://github.com/Dr-Electron)) + - [#7139](https://github.com/facebook/docusaurus/pull/7139) fix: proper spacing between generated card items on mobiles ([@lex111](https://github.com/lex111)) + - [#7134](https://github.com/facebook/docusaurus/pull/7134) fix(theme-classic): fix docs sidebar layout shifts when expanding categories ([@slorber](https://github.com/slorber)) + - [#7068](https://github.com/facebook/docusaurus/pull/7068) refactor(theme-classic): blog mobile secondary menu use consistent styles ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7004](https://github.com/facebook/docusaurus/pull/7004) fix(theme-classic): shrink title size on mobile ([@Pierre-Gilles](https://github.com/Pierre-Gilles)) +- `docusaurus-theme-translations` + - [#7214](https://github.com/facebook/docusaurus/pull/7214) chore(theme-translations): complete Polish translations ([@rev4324](https://github.com/rev4324)) + - [#7031](https://github.com/facebook/docusaurus/pull/7031) chore(theme-translations): complete German translations ([@deployn](https://github.com/deployn)) +- `create-docusaurus`, `docusaurus-theme-classic` + - [#7176](https://github.com/facebook/docusaurus/pull/7176) refactor: customize code block line highlight color via CSS var ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#7218](https://github.com/facebook/docusaurus/pull/7218) fix(cli): always show error stack to unhandled rejection ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7142](https://github.com/facebook/docusaurus/pull/7142) refactor(core): lower timeout before rendering progress bar to 200ms ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7103](https://github.com/facebook/docusaurus/pull/7103) fix(core): preserve Interpolate children semantics ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7029](https://github.com/facebook/docusaurus/pull/7029) refactor: console output improvements ([@lex111](https://github.com/lex111)) + - [#7017](https://github.com/facebook/docusaurus/pull/7017) refactor: remove copyright comment from swizzled components ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs`, `docusaurus-preset-classic`, `docusaurus-theme-classic` + - [#7148](https://github.com/facebook/docusaurus/pull/7148) feat(preset-classic, content-docs/client): JSDoc ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-debug`, `docusaurus-preset-classic` + - [#7122](https://github.com/facebook/docusaurus/pull/7122) feat(preset-classic): exclude debug plugin routes from sitemap ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` + - [#7113](https://github.com/facebook/docusaurus/pull/7113) test: improve test coverage ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus` + - [#7080](https://github.com/facebook/docusaurus/pull/7080) refactor: replace non-prop interface with type; allow plugin lifecycles to have sync type ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-logger`, `docusaurus-plugin-content-docs`, `docusaurus` + - [#7019](https://github.com/facebook/docusaurus/pull/7019) feat(logger): new "url" format, add double quotes around paths ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#7006](https://github.com/facebook/docusaurus/pull/7006) refactor: split and cleanup theme/DocPage ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#7005](https://github.com/facebook/docusaurus/pull/7005) refactor: split DocSidebarItem by item type ([@slorber](https://github.com/slorber)) + +#### :memo: Documentation + +- `docusaurus-logger` + - [#7305](https://github.com/facebook/docusaurus/pull/7305) docs: update docs for logger, add API docs to website ([@Josh-Cena](https://github.com/Josh-Cena)) +- Other + - [#7284](https://github.com/facebook/docusaurus/pull/7284) docs: add a paragraph about SSR as an optimization technique ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7278](https://github.com/facebook/docusaurus/pull/7278) docs: enhance docs about Markdown TOC and metadata ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7271](https://github.com/facebook/docusaurus/pull/7271) docs: specify Node version requirement to a minor ([@DanRoscigno](https://github.com/DanRoscigno)) + - [#7252](https://github.com/facebook/docusaurus/pull/7252) docs: update gtag docs to reflect what a GA4 tag looks like ([@johnnyreilly](https://github.com/johnnyreilly)) + - [#7240](https://github.com/facebook/docusaurus/pull/7240) docs: add PCC Archive site to showcase ([@CuratorCat](https://github.com/CuratorCat)) + - [#7239](https://github.com/facebook/docusaurus/pull/7239) docs: add Chaos mesh site to showcase ([@cwen0](https://github.com/cwen0)) + - [#7235](https://github.com/facebook/docusaurus/pull/7235) docs: add TiDB community books to showcase ([@shczhen](https://github.com/shczhen)) + - [#7236](https://github.com/facebook/docusaurus/pull/7236) docs: add documentation about pluralization ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7230](https://github.com/facebook/docusaurus/pull/7230) docs: add OSS Insight to showcase ([@sykp241095](https://github.com/sykp241095)) + - [#7208](https://github.com/facebook/docusaurus/pull/7208) docs: remove mention of "template" from README installation guide ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7159](https://github.com/facebook/docusaurus/pull/7159) docs: explain more clearly the purpose of a ref sidebar type ([@andrewnicols](https://github.com/andrewnicols)) + - [#7126](https://github.com/facebook/docusaurus/pull/7126) docs: multiple documentation improvements ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7123](https://github.com/facebook/docusaurus/pull/7123) refactor(showcase): enforce descriptions with maximum length of 120 characters ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7026](https://github.com/facebook/docusaurus/pull/7026) docs: correct plugin example filename ([@mxhdx](https://github.com/mxhdx)) + - [#7110](https://github.com/facebook/docusaurus/pull/7110) docs: add a note about additional languages needing to be Prism component names ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6746](https://github.com/facebook/docusaurus/pull/6746) fix(website): lazy-load YT iframe ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7061](https://github.com/facebook/docusaurus/pull/7061) docs: add docusaurus-plugin-typedoc to resources ([@nartc](https://github.com/nartc)) + - [#7059](https://github.com/facebook/docusaurus/pull/7059) docs: add firelordjs to showcase ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7050](https://github.com/facebook/docusaurus/pull/7050) docs: add import React statement in JSX file example ([@kaycebasques](https://github.com/kaycebasques)) + - [#7022](https://github.com/facebook/docusaurus/pull/7022) docs: add Easypanel to showcase ([@deiucanta](https://github.com/deiucanta)) + - [#7016](https://github.com/facebook/docusaurus/pull/7016) docs: consistently use sidebars.js filename ([@leedom92](https://github.com/leedom92)) + - [#7020](https://github.com/facebook/docusaurus/pull/7020) docs: add Divine WSF and Ghostly to showcase ([@LeviticusMB](https://github.com/LeviticusMB)) + - [#7000](https://github.com/facebook/docusaurus/pull/7000) docs: remove unnecessary semicolon ([@imsingh](https://github.com/imsingh)) +- `docusaurus-plugin-content-docs`, `docusaurus-utils` + - [#7248](https://github.com/facebook/docusaurus/pull/7248) refactor: normalize Markdown linkification behavior, elaborate in documentation ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils` + - [#7081](https://github.com/facebook/docusaurus/pull/7081) docs: fix some casing inconsistencies ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :wrench: Maintenance + +- Other + - [#7309](https://github.com/facebook/docusaurus/pull/7309) chore: use "Maintenance" instead of "Internal" in changelog ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7300](https://github.com/facebook/docusaurus/pull/7300) misc: check doc page by Lighthouse CI ([@lex111](https://github.com/lex111)) + - [#7266](https://github.com/facebook/docusaurus/pull/7266) misc: add links section to PR template ([@slorber](https://github.com/slorber)) + - [#7224](https://github.com/facebook/docusaurus/pull/7224) chore: GitHub Actions cancel-in-progress ([@slorber](https://github.com/slorber)) + - [#7216](https://github.com/facebook/docusaurus/pull/7216) chore: remove netlify-cli from devDependencies ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7211](https://github.com/facebook/docusaurus/pull/7211) chore: replace node 17 with 18 in CI matrix ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7168](https://github.com/facebook/docusaurus/pull/7168) misc: add CI actions/dependency-review-action for security ([@slorber](https://github.com/slorber)) + - [#6984](https://github.com/facebook/docusaurus/pull/6984) misc: pin actions to a full-length commit SHA ([@naveensrinivasan](https://github.com/naveensrinivasan)) + - [#7002](https://github.com/facebook/docusaurus/pull/7002) chore: regen examples for 2.0 beta.18 ([@slorber](https://github.com/slorber)) +- `docusaurus-logger`, `docusaurus-remark-plugin-npm2yarn` + - [#7295](https://github.com/facebook/docusaurus/pull/7295) refactor: use export = syntax for Node utility packages ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#7293](https://github.com/facebook/docusaurus/pull/7293) refactor(types): move non-core, non-public types out of the types package ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-types`, `docusaurus` + - [#7292](https://github.com/facebook/docusaurus/pull/7292) refactor(core): collocate CLI commands and their option types ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7084](https://github.com/facebook/docusaurus/pull/7084) refactor(core): code cleanup ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus` + - [#7282](https://github.com/facebook/docusaurus/pull/7282) refactor(core): prefetch/preload refactor ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#7273](https://github.com/facebook/docusaurus/pull/7273) refactor(theme-classic): multiple re-arrangements ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7268](https://github.com/facebook/docusaurus/pull/7268) refactor(theme-classic): DocPage theme refactors polish ([@slorber](https://github.com/slorber)) + - [#7269](https://github.com/facebook/docusaurus/pull/7269) refactor: extract useSkipToContent() ([@slorber](https://github.com/slorber)) + - [#7175](https://github.com/facebook/docusaurus/pull/7175) refactor(theme-classic): split CodeBlock ([@slorber](https://github.com/slorber)) + - [#7067](https://github.com/facebook/docusaurus/pull/7067) refactor(theme-classic): extract doc-related navbar items' logic to theme-common ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7021](https://github.com/facebook/docusaurus/pull/7021) refactor(theme): extract plumbing code of BTT button into theme-common ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#7270](https://github.com/facebook/docusaurus/pull/7270) refactor(theme-classic): refactor TOC-related theme components ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#7220](https://github.com/facebook/docusaurus/pull/7220) refactor(cli): normalize the application of default option values ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7141](https://github.com/facebook/docusaurus/pull/7141) refactor(core): minor PendingNavigation refactor ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs` + - [#7243](https://github.com/facebook/docusaurus/pull/7243) chore: upgrade Jest to 28; add GitHub-actions reporter ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#7140](https://github.com/facebook/docusaurus/pull/7140) refactor(content-docs): split version handling into several files ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-live-codeblock`, `docusaurus` + - [#7194](https://github.com/facebook/docusaurus/pull/7194) fix: fix a few internal declaration semantic errors ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-migrate`, `docusaurus-theme-translations`, `docusaurus` + - [#7186](https://github.com/facebook/docusaurus/pull/7186) refactor: prefer fs.readJSON over readFile.then(JSON.parse) ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages` + - [#7145](https://github.com/facebook/docusaurus/pull/7145) refactor: unify how MDX content types are represented ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#7138](https://github.com/facebook/docusaurus/pull/7138) chore: upgrade dependencies + upgrade React types ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#7131](https://github.com/facebook/docusaurus/pull/7131) chore: disable string escaping in snapshots ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#7054](https://github.com/facebook/docusaurus/pull/7054) refactor(core): refactor routes generation logic ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-types`, `docusaurus` + - [#7042](https://github.com/facebook/docusaurus/pull/7042) refactor(core): reorganize files ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs`, `docusaurus-utils`, `docusaurus` + - [#7037](https://github.com/facebook/docusaurus/pull/7037) refactor(core): reorganize functions ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#7027](https://github.com/facebook/docusaurus/pull/7027) refactor(content-docs): deduplicate types, JSDoc for some APIs ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :running_woman: Performance + +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils-common` + - [#7085](https://github.com/facebook/docusaurus/pull/7085) refactor: mark a few client-side packages as side-effect-free ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-remark-plugin-npm2yarn` + - [#4997](https://github.com/facebook/docusaurus/pull/4997) perf(mdx-loader): cache mdx/remark compiler instances ([@phryneas](https://github.com/phryneas)) + +#### Committers: 47 + +- Aaron Nwabuoku ([@aerovulpe](https://github.com/aerovulpe)) +- AkiraVoid ([@AkiraVoid](https://github.com/AkiraVoid)) +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Andrei Canta ([@deiucanta](https://github.com/deiucanta)) +- Andrew Lyons ([@andrewnicols](https://github.com/andrewnicols)) +- ApsarasX ([@ApsarasX](https://github.com/ApsarasX)) +- Chau Tran ([@nartc](https://github.com/nartc)) +- Chinazaekpere Ngubo ([@dr-ngubo](https://github.com/dr-ngubo)) +- Cwen Yin ([@cwen0](https://github.com/cwen0)) +- Dan Roscigno ([@DanRoscigno](https://github.com/DanRoscigno)) +- Elias Papavasileiou ([@elias-pap](https://github.com/elias-pap)) +- Evan ([@sulu5890](https://github.com/sulu5890)) +- Fusang❀ ([@cxOrz](https://github.com/cxOrz)) +- Indermohan Singh ([@imsingh](https://github.com/imsingh)) +- JMW ([@JohnnyMcWeed](https://github.com/JohnnyMcWeed)) +- Jeffrey Aven ([@jeffreyaven](https://github.com/jeffreyaven)) +- Jody Heavener ([@jodyheavener](https://github.com/jodyheavener)) +- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Karl Ward ([@mjau-mjau](https://github.com/mjau-mjau)) +- Kayce Basques ([@kaycebasques](https://github.com/kaycebasques)) +- Leedom ([@leedom92](https://github.com/leedom92)) +- Lenz Weber-Tronic ([@phryneas](https://github.com/phryneas)) +- Lukas Bach ([@lukasbach](https://github.com/lukasbach)) +- Martin Blom ([@LeviticusMB](https://github.com/LeviticusMB)) +- Naveen ([@naveensrinivasan](https://github.com/naveensrinivasan)) +- Pablo Cordon ([@pcordon](https://github.com/pcordon)) +- Pierre-Gilles Leymarie ([@Pierre-Gilles](https://github.com/Pierre-Gilles)) +- Qi Zhang ([@zzzhangqi](https://github.com/zzzhangqi)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Viktor Chernodub ([@chernodub](https://github.com/chernodub)) +- Zac A ([@sandypockets](https://github.com/sandypockets)) +- [@Dr-Electron](https://github.com/Dr-Electron) +- [@chelproc](https://github.com/chelproc) +- [@deployn](https://github.com/deployn) +- [@duanwilliam](https://github.com/duanwilliam) +- [@kgolubic](https://github.com/kgolubic) +- [@redhat123456](https://github.com/redhat123456) +- [@surendran82](https://github.com/surendran82) +- [@svix-ken](https://github.com/svix-ken) +- apq ([@AntonPalmqvist](https://github.com/AntonPalmqvist)) +- curatorcat.pcc.eth ([@CuratorCat](https://github.com/CuratorCat)) +- czhen ([@shczhen](https://github.com/shczhen)) +- loic ([@layerzzzio](https://github.com/layerzzzio)) +- mehdim ([@mxhdx](https://github.com/mxhdx)) +- rev ([@rev4324](https://github.com/rev4324)) +- sykp241095 ([@sykp241095](https://github.com/sykp241095)) + +## 2.0.0-beta.18 (2022-03-25) + +#### :rocket: New Feature + +- `docusaurus-mdx-loader`, `docusaurus-theme-classic` + - [#6990](https://github.com/facebook/docusaurus/pull/6990) feat: lazy-load external images + ability to customize image display ([@slorber](https://github.com/slorber)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus` + - [#6933](https://github.com/facebook/docusaurus/pull/6933) feat(core,theme): useRouteContext + HtmlClassNameProvider ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus` + - [#6921](https://github.com/facebook/docusaurus/pull/6921) feat(core): allow plugin lifecycles to return relative paths ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#6697](https://github.com/facebook/docusaurus/pull/6697) feat: add SEO microdata for doc breadcrumbs ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6842](https://github.com/facebook/docusaurus/pull/6842) feat(theme-classic): MDXContent wrapper component ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs` + - [#6780](https://github.com/facebook/docusaurus/pull/6780) feat(content-docs): allow custom props through _category_.json ([@taejs](https://github.com/taejs)) + +#### :boom: Breaking Change + +- `docusaurus-plugin-content-docs` + - [#6859](https://github.com/facebook/docusaurus/pull/6859) feat(content-docs): autogenerate category with linked doc metadata as fallback ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#6989](https://github.com/facebook/docusaurus/pull/6989) refactor: extract MDX components ([@slorber](https://github.com/slorber)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#6925](https://github.com/facebook/docusaurus/pull/6925) refactor(theme-{classic,common}): refactor site/page/search metadata + apply className on html element ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6895](https://github.com/facebook/docusaurus/pull/6895) refactor(theme-{classic,common}): split navbar into smaller components + cleanup + swizzle config ([@slorber](https://github.com/slorber)) + - [#6930](https://github.com/facebook/docusaurus/pull/6930) refactor(theme-{classic,common}): refactor ColorModeToggle + useColorMode() hook ([@lex111](https://github.com/lex111)) + +#### :bug: Bug Fix + +- `docusaurus` + - [#6993](https://github.com/facebook/docusaurus/pull/6993) fix(core): prevent useBaseUrl returning /base/base when on /base ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6936](https://github.com/facebook/docusaurus/pull/6936) fix: remove semicolon from HTML output ([@lex111](https://github.com/lex111)) + - [#6849](https://github.com/facebook/docusaurus/pull/6849) fix(cli): write-heading-id should not generate colliding slugs when not overwriting ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#6983](https://github.com/facebook/docusaurus/pull/6983) fix(search): bump Infima, fix search issue due to broken CSS selector ([@slorber](https://github.com/slorber)) +- `docusaurus-utils-validation` + - [#6977](https://github.com/facebook/docusaurus/pull/6977) fix(validation): allow non-object params to remark/rehype plugins ([@aloisklink](https://github.com/aloisklink)) +- `docusaurus-plugin-content-docs`, `docusaurus-utils` + - [#6973](https://github.com/facebook/docusaurus/pull/6973) fix(content-docs): suppress git error on multiple occurrences ([@felipecrs](https://github.com/felipecrs)) +- `docusaurus-plugin-content-blog` + - [#6947](https://github.com/facebook/docusaurus/pull/6947) fix(content-blog): only create archive route if there are blog posts ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6918](https://github.com/facebook/docusaurus/pull/6918) fix(content-blog): remove double leading slash in blog-only paginated view ([@heowc](https://github.com/heowc)) +- `docusaurus-theme-search-algolia` + - [#6888](https://github.com/facebook/docusaurus/pull/6888) fix(theme-algolia): declare content-docs as dependency ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-translations` + - [#6847](https://github.com/facebook/docusaurus/pull/6847) fix: minor Chinese translation fixes ([@rccttwd](https://github.com/rccttwd)) + +#### :nail_care: Polish + +- `docusaurus-plugin-content-docs` + - [#6859](https://github.com/facebook/docusaurus/pull/6859) feat(content-docs): autogenerate category with linked doc metadata as fallback ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6887](https://github.com/facebook/docusaurus/pull/6887) fix(content-docs): give context about sidebar loading failure ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs`, `docusaurus-utils-validation`, `docusaurus` + - [#6997](https://github.com/facebook/docusaurus/pull/6997) fix(validation): improve error messages for a few schemas ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#6971](https://github.com/facebook/docusaurus/pull/6971) refactor: improve a11y of dropdown menu ([@lex111](https://github.com/lex111)) + - [#6987](https://github.com/facebook/docusaurus/pull/6987) refactor(theme-classic): cleanup of code blocks ([@lex111](https://github.com/lex111)) + - [#6950](https://github.com/facebook/docusaurus/pull/6950) refactor(theme-classic): clean up CSS of doc cards ([@lex111](https://github.com/lex111)) + - [#6994](https://github.com/facebook/docusaurus/pull/6994) refactor: better external link icon positioning ([@lex111](https://github.com/lex111)) + - [#6989](https://github.com/facebook/docusaurus/pull/6989) refactor: extract MDX components ([@slorber](https://github.com/slorber)) + - [#6985](https://github.com/facebook/docusaurus/pull/6985) refactor(theme-classic): remove span wrappers from layout links ([@lex111](https://github.com/lex111)) + - [#6986](https://github.com/facebook/docusaurus/pull/6986) fix(theme-classic): minor code copy button improvements ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6964](https://github.com/facebook/docusaurus/pull/6964) refactor: replace text-based copy code button with icons ([@lex111](https://github.com/lex111)) + - [#6932](https://github.com/facebook/docusaurus/pull/6932) refactor(theme-classic): little breadcrumbs improvements ([@lex111](https://github.com/lex111)) + - [#6914](https://github.com/facebook/docusaurus/pull/6914) feat(theme-classic): set aria-expanded on expandable sidebar categories ([@pkowaluk](https://github.com/pkowaluk)) + - [#6844](https://github.com/facebook/docusaurus/pull/6844) refactor(theme-classic): split sidebar into smaller parts ([@slorber](https://github.com/slorber)) + - [#6846](https://github.com/facebook/docusaurus/pull/6846) refactor(theme-classic): consistently add span wrapper for layout links ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#6980](https://github.com/facebook/docusaurus/pull/6980) feat(utils): JSDoc for all APIs ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-common` + - [#6974](https://github.com/facebook/docusaurus/pull/6974) feat(theme-common): JSDoc for all APIs ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#6784](https://github.com/facebook/docusaurus/pull/6784) feat(core): allow configureWebpack to return undefined ([@yorkie](https://github.com/yorkie)) + - [#6941](https://github.com/facebook/docusaurus/pull/6941) refactor(core): improve error message when a page has no default-export ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6878](https://github.com/facebook/docusaurus/pull/6878) fix(core): ensure stable webpack theme aliases sorting ([@jrvidal](https://github.com/jrvidal)) + - [#6854](https://github.com/facebook/docusaurus/pull/6854) fix(core): fix swizzle legend typo ([@DigiPie](https://github.com/DigiPie)) + - [#6850](https://github.com/facebook/docusaurus/pull/6850) fix(core): make plugin lifecycles consistently bound to the plugin instance ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils` + - [#6937](https://github.com/facebook/docusaurus/pull/6937) fix(content-docs): warn when files are not tracked ([@felipecrs](https://github.com/felipecrs)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#6925](https://github.com/facebook/docusaurus/pull/6925) refactor(theme-{classic,common}): refactor site/page/search metadata + apply className on html element ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6895](https://github.com/facebook/docusaurus/pull/6895) refactor(theme-{classic,common}): split navbar into smaller components + cleanup + swizzle config ([@slorber](https://github.com/slorber)) + - [#6930](https://github.com/facebook/docusaurus/pull/6930) refactor(theme-{classic,common}): refactor ColorModeToggle + useColorMode() hook ([@lex111](https://github.com/lex111)) + - [#6894](https://github.com/facebook/docusaurus/pull/6894) refactor(theme-classic): split theme footer into smaller components + swizzle config ([@slorber](https://github.com/slorber)) +- `docusaurus-types`, `docusaurus` + - [#6929](https://github.com/facebook/docusaurus/pull/6929) refactor(core): minor routes type improvement ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap` + - [#6928](https://github.com/facebook/docusaurus/pull/6928) chore(pwa, sitemap, client-redirects, ideal-image): JSDoc for types ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic`, `docusaurus-utils` + - [#6922](https://github.com/facebook/docusaurus/pull/6922) refactor(content-blog): clean up type definitions; in-code documentation ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-translations` + - [#6781](https://github.com/facebook/docusaurus/pull/6781) feat(theme-translations): complete Russian translations ([@dragomano](https://github.com/dragomano)) + - [#6877](https://github.com/facebook/docusaurus/pull/6877) chore(theme-translations): complete Vietnamese translations ([@datlechin](https://github.com/datlechin)) +- `docusaurus-plugin-content-blog` + - [#6909](https://github.com/facebook/docusaurus/pull/6909) refactor(content-blog): improve error message of authors map validation ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus` + - [#6860](https://github.com/facebook/docusaurus/pull/6860) fix(create): load entry file after node version checking ([@taejs](https://github.com/taejs)) + +#### :memo: Documentation + +- Other + - [#6988](https://github.com/facebook/docusaurus/pull/6988) docs: fix example admonition syntax ([@kaycebasques](https://github.com/kaycebasques)) + - [#6978](https://github.com/facebook/docusaurus/pull/6978) docs: npm run tsc -> npx tsc ([@jadonn](https://github.com/jadonn)) + - [#6952](https://github.com/facebook/docusaurus/pull/6952) docs: add K3ai to showcase ([@alefesta](https://github.com/alefesta)) + - [#6948](https://github.com/facebook/docusaurus/pull/6948) docs: add pdfme docs to showcase ([@hand-dot](https://github.com/hand-dot)) + - [#6943](https://github.com/facebook/docusaurus/pull/6943) docs: add SeaORM docs to showcase ([@billy1624](https://github.com/billy1624)) + - [#6926](https://github.com/facebook/docusaurus/pull/6926) docs: clarify the usage of slug ([@kaycebasques](https://github.com/kaycebasques)) + - [#6911](https://github.com/facebook/docusaurus/pull/6911) docs: add Reactive Button site to showcase ([@arifszn](https://github.com/arifszn)) + - [#6904](https://github.com/facebook/docusaurus/pull/6904) docs: update image for digital support services ([@PatelN123](https://github.com/PatelN123)) + - [#6892](https://github.com/facebook/docusaurus/pull/6892) docs: add EduLinks site to showcase ([@odarpi](https://github.com/odarpi)) + - [#6889](https://github.com/facebook/docusaurus/pull/6889) docs: editorial fixes ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6883](https://github.com/facebook/docusaurus/pull/6883) docs(cli): add info about development on github codespaces ([@vedantmgoyal2009](https://github.com/vedantmgoyal2009)) + - [#6856](https://github.com/facebook/docusaurus/pull/6856) docs: add Reddit Image Fetcher site to showcase ([@arifszn](https://github.com/arifszn)) + - [#6875](https://github.com/facebook/docusaurus/pull/6875) docs: update TRPG Engine showcase ([@moonrailgun](https://github.com/moonrailgun)) + - [#6871](https://github.com/facebook/docusaurus/pull/6871) docs: mark clutch and gulp as open-source ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6862](https://github.com/facebook/docusaurus/pull/6862) docs: update showcase data ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6837](https://github.com/facebook/docusaurus/pull/6837) docs: add PcapPlusPlus to showcase ([@seladb](https://github.com/seladb)) + - [#6832](https://github.com/facebook/docusaurus/pull/6832) docs: add Spicetify site to showcase ([@afonsojramos](https://github.com/afonsojramos)) + - [#6830](https://github.com/facebook/docusaurus/pull/6830) docs: simplify imported code blocks syntax ([@nathan-contino-mongo](https://github.com/nathan-contino-mongo)) +- `docusaurus-types` + - [#6881](https://github.com/facebook/docusaurus/pull/6881) docs: mention configureWebpack devServer return value ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus` + - [#6833](https://github.com/facebook/docusaurus/pull/6833) docs: make tutorial code block directly copyable ([@samgutentag](https://github.com/samgutentag)) + +#### :house: Internal + +- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#6995](https://github.com/facebook/docusaurus/pull/6995) refactor: ensure all types are using index signature instead of Record ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-cssnano-preset`, `docusaurus-plugin-pwa`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#6991](https://github.com/facebook/docusaurus/pull/6991) chore: upgrade dependencies ([@Josh-Cena](https://github.com/Josh-Cena)) +- `lqip-loader` + - [#6992](https://github.com/facebook/docusaurus/pull/6992) refactor(lqip-loader): remove unused palette option ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#6975](https://github.com/facebook/docusaurus/pull/6975) chore: update static-site-generator-webpack-plugin ([@slorber](https://github.com/slorber)) +- `stylelint-copyright` + - [#6967](https://github.com/facebook/docusaurus/pull/6967) chore: publish stylelint-copyright again ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus` + - [#6961](https://github.com/facebook/docusaurus/pull/6961) refactor: unify how validateOptions is handled ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-types` + - [#6957](https://github.com/facebook/docusaurus/pull/6957) chore(types): remove querystring from dependencies ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-common`, `docusaurus` + - [#6956](https://github.com/facebook/docusaurus/pull/6956) test: improve test coverage; reorder theme-common files ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6955](https://github.com/facebook/docusaurus/pull/6955) refactor(core): move browserContext and docusaurusContext out of client exports ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6944](https://github.com/facebook/docusaurus/pull/6944) chore: migrate Jest and website to SWC ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-utils` + - [#6951](https://github.com/facebook/docusaurus/pull/6951) test: fix Windows test for gitUtils ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` + - [#6931](https://github.com/facebook/docusaurus/pull/6931) chore: tighten ESLint config ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects` + - [#6924](https://github.com/facebook/docusaurus/pull/6924) refactor(client-redirects): migrate validation to validateOptions lifecycle ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-cssnano-preset`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#6916](https://github.com/facebook/docusaurus/pull/6916) chore: upgrade dependencies ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-plugin-content-docs`, `docusaurus-theme-translations`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` + - [#6912](https://github.com/facebook/docusaurus/pull/6912) test: improve test coverage; multiple internal refactors ([@Josh-Cena](https://github.com/Josh-Cena)) +- Other + - [#6910](https://github.com/facebook/docusaurus/pull/6910) refactor: convert Jest infrastructure to TS ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6838](https://github.com/facebook/docusaurus/pull/6838) fix(website): changelog plugin leads to CI bugs on release ([@slorber](https://github.com/slorber)) +- `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` + - [#6908](https://github.com/facebook/docusaurus/pull/6908) chore: do not print prototype in jest snapshot ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#6906](https://github.com/facebook/docusaurus/pull/6906) refactor: install eslint-plugin-regexp ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus` + - [#6905](https://github.com/facebook/docusaurus/pull/6905) test: improve test coverage; properly test core client APIs ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-sitemap`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus` + - [#6903](https://github.com/facebook/docusaurus/pull/6903) chore: spell-check test files ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#6902](https://github.com/facebook/docusaurus/pull/6902) test(theme-common): improve test coverage ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-cssnano-preset`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` + - [#6900](https://github.com/facebook/docusaurus/pull/6900) test: enable a few jest eslint rules ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#6898](https://github.com/facebook/docusaurus/pull/6898) refactor: import jest as global; unify import style of some modules ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6891](https://github.com/facebook/docusaurus/pull/6891) refactor(theme-classic): avoid using clsx class dict with CSS modules ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus` + - [#6880](https://github.com/facebook/docusaurus/pull/6880) refactor: prefer fs.outputFile to ensureDir + writeFile ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-pwa`, `docusaurus-types`, `docusaurus` + - [#6866](https://github.com/facebook/docusaurus/pull/6866) refactor: improve types ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus`, `lqip-loader` + - [#6864](https://github.com/facebook/docusaurus/pull/6864) refactor: remove unnecessary default values normalized during validation ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-migrate`, `docusaurus` + - [#6861](https://github.com/facebook/docusaurus/pull/6861) refactor: make JS executables included in the tsconfig for editor hints ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` + - [#6857](https://github.com/facebook/docusaurus/pull/6857) test: improve test coverage ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#6852](https://github.com/facebook/docusaurus/pull/6852) refactor: enable a few TS flags ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### Committers: 28 + +- Afonso Jorge Ramos ([@afonsojramos](https://github.com/afonsojramos)) +- Alessandro Festa ([@alefesta](https://github.com/alefesta)) +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Alois Klink ([@aloisklink](https://github.com/aloisklink)) +- Ariful Alam ([@arifszn](https://github.com/arifszn)) +- Begula ([@vedantmgoyal2009](https://github.com/vedantmgoyal2009)) +- Billy Chan ([@billy1624](https://github.com/billy1624)) +- Bugo ([@dragomano](https://github.com/dragomano)) +- Evan ([@DigiPie](https://github.com/DigiPie)) +- Felipe Santos ([@felipecrs](https://github.com/felipecrs)) +- Jadon N ([@jadonn](https://github.com/jadonn)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Kayce Basques ([@kaycebasques](https://github.com/kaycebasques)) +- Kyohei Fukuda ([@hand-dot](https://github.com/hand-dot)) +- Nayan Patel ([@PatelN123](https://github.com/PatelN123)) +- Ngô Quốc Đạt ([@datlechin](https://github.com/datlechin)) +- Odarpi ([@odarpi](https://github.com/odarpi)) +- Pawel Kowaluk ([@pkowaluk](https://github.com/pkowaluk)) +- Roberto Vidal ([@jrvidal](https://github.com/jrvidal)) +- Sam Gutentag ([@samgutentag](https://github.com/samgutentag)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tsz W. TAM ([@rccttwd](https://github.com/rccttwd)) +- WonChul Heo ([@heowc](https://github.com/heowc)) +- Yorkie Liu ([@yorkie](https://github.com/yorkie)) +- [@seladb](https://github.com/seladb) +- moonrailgun ([@moonrailgun](https://github.com/moonrailgun)) +- nate contino ([@nathan-contino-mongo](https://github.com/nathan-contino-mongo)) +- tae ([@taejs](https://github.com/taejs)) + +## 2.0.0-beta.17 (2022-03-03) + +#### :rocket: New Feature + +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#6783](https://github.com/facebook/docusaurus/pull/6783) feat: allow blog authors email ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :boom: Breaking Change + +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6771](https://github.com/facebook/docusaurus/pull/6771) refactor(theme-classic): replace color mode toggle with button; remove switchConfig ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#6827](https://github.com/facebook/docusaurus/pull/6827) fix(theme-classic): restore docusaurus search meta ([@slorber](https://github.com/slorber)) + - [#6767](https://github.com/facebook/docusaurus/pull/6767) fix(theme-classic): allow code tags containing inline elements to stay inline ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-common` + - [#6824](https://github.com/facebook/docusaurus/pull/6824) fix(theme-common): breadcrumbs home bug in docs-only ([@slorber](https://github.com/slorber)) + - [#6816](https://github.com/facebook/docusaurus/pull/6816) fix(theme-common): docs breadcrumbs not working with baseUrl ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs` + - [#6700](https://github.com/facebook/docusaurus/pull/6700) fix(content-docs): always sort autogenerated sidebar items by file/folder name by default ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#6812](https://github.com/facebook/docusaurus/pull/6812) fix(core): remove hash/query when filtering existing files for broken link check ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader` + - [#6779](https://github.com/facebook/docusaurus/pull/6779) fix(mdx-loader): suppress image reading warning in Yarn PnP; log warning instead of error ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus` + - [#6762](https://github.com/facebook/docusaurus/pull/6762) fix(create): update broken SVG paths in templates ([@anicholls](https://github.com/anicholls)) + +#### :nail_care: Polish + +- `docusaurus-theme-common` + - [#6826](https://github.com/facebook/docusaurus/pull/6826) refactor(theme-common): unify missing context errors ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6771](https://github.com/facebook/docusaurus/pull/6771) refactor(theme-classic): replace color mode toggle with button; remove switchConfig ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#6769](https://github.com/facebook/docusaurus/pull/6769) refactor(theme-classic): use Material icon for language dropdown ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader` + - [#6792](https://github.com/facebook/docusaurus/pull/6792) fix(mdx-loader): allow image paths to be URL encoded ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :memo: Documentation + +- Other + - [#6825](https://github.com/facebook/docusaurus/pull/6825) docs: Adds Netlify one click deploy to README ([@PatelN123](https://github.com/PatelN123)) + - [#6818](https://github.com/facebook/docusaurus/pull/6818) docs: add deploy with vercel button to README ([@PatelN123](https://github.com/PatelN123)) + - [#6817](https://github.com/facebook/docusaurus/pull/6817) docs: fix broken links ([@PatelN123](https://github.com/PatelN123)) + - [#6811](https://github.com/facebook/docusaurus/pull/6811) docs: add homepage banner in support of Ukraine ([@dmitryvinn](https://github.com/dmitryvinn)) + - [#6813](https://github.com/facebook/docusaurus/pull/6813) docs: mark dyte as opensource in showcase ([@vaibhavshn](https://github.com/vaibhavshn)) + - [#6776](https://github.com/facebook/docusaurus/pull/6776) docs: make GitHub actions explanation aligned with the code ([@arifszn](https://github.com/arifszn)) + - [#6772](https://github.com/facebook/docusaurus/pull/6772) docs: add basic documentation about client modules ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus` + - [#6815](https://github.com/facebook/docusaurus/pull/6815) fix: consistently use `max-width: 996px` in media queries ([@dstotijn](https://github.com/dstotijn)) + +#### :house: Internal + +- `docusaurus-plugin-content-docs` + - [#6821](https://github.com/facebook/docusaurus/pull/6821) test(content-docs): refactor navigation test snapshot ([@Josh-Cena](https://github.com/Josh-Cena)) +- Other + - [#6768](https://github.com/facebook/docusaurus/pull/6768) test: add TypeScript template to E2E test matrix ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-utils` + - [#6773](https://github.com/facebook/docusaurus/pull/6773) refactor(utils): categorize functions into separate files ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate` + - [#6761](https://github.com/facebook/docusaurus/pull/6761) chore: various internal fixes ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### Committers: 8 + +- Alex Nicholls ([@anicholls](https://github.com/anicholls)) +- Ariful Alam ([@arifszn](https://github.com/arifszn)) +- David Stotijn ([@dstotijn](https://github.com/dstotijn)) +- Dmitry Vinnik ([@dmitryvinn](https://github.com/dmitryvinn)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Nayan Patel ([@PatelN123](https://github.com/PatelN123)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Vaibhav Shinde ([@vaibhavshn](https://github.com/vaibhavshn)) + +## 2.0.0-beta.16 (2022-02-25) + +#### :rocket: New Feature + +- `docusaurus-logger`, `docusaurus-module-type-aliases`, `docusaurus-plugin-debug`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus` + - [#6243](https://github.com/facebook/docusaurus/pull/6243) feat(core): brand new swizzle CLI experience ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus` + - [#6750](https://github.com/facebook/docusaurus/pull/6750) feat(create): new --package-manager option; interactive package manager selection ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6610](https://github.com/facebook/docusaurus/pull/6610) feat(create): allow specifying a git clone strategy ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6723](https://github.com/facebook/docusaurus/pull/6723) feat: sync color mode between browser tabs ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-search-algolia` + - [#6692](https://github.com/facebook/docusaurus/pull/6692) feat(search-algolia): allow disabling search page and configuring path ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6517](https://github.com/facebook/docusaurus/pull/6517) feat(docs,theme-classic): docs breadcrumbs ([@jodyheavener](https://github.com/jodyheavener)) + - [#6519](https://github.com/facebook/docusaurus/pull/6519) feat(content-docs): sidebar item type "html" for rendering pure markup ([@jodyheavener](https://github.com/jodyheavener)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils` + - [#6593](https://github.com/facebook/docusaurus/pull/6593) feat(content-blog): infer blog post date from git history ([@felipecrs](https://github.com/felipecrs)) +- `docusaurus-plugin-content-docs` + - [#6619](https://github.com/facebook/docusaurus/pull/6619) feat(content-docs): add custom props front matter ([@TheCatLady](https://github.com/TheCatLady)) + - [#6452](https://github.com/facebook/docusaurus/pull/6452) feat(content-docs): allow explicitly disabling index page for generated category ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog` + - [#6603](https://github.com/facebook/docusaurus/pull/6603) feat(content-blog): allow customizing blog archive component through option ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#6221](https://github.com/facebook/docusaurus/pull/6221) feat(content-blog): Allow pagination for BlogTagsPostsPage ([@redhoyasa](https://github.com/redhoyasa)) + +#### :boom: Breaking Change + +- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` + - [#6752](https://github.com/facebook/docusaurus/pull/6752) chore: upgrade docsearch-react to v3 stable, bump dependencies ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types` + - [#6729](https://github.com/facebook/docusaurus/pull/6729) refactor: make MDX export a flat TOC list instead of tree ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus` + - [#6740](https://github.com/facebook/docusaurus/pull/6740) refactor: remove deprecated Webpack utils & validation escape hatch ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#6707](https://github.com/facebook/docusaurus/pull/6707) refactor(theme-classic): bias again search metadata toward Algolia DocSearch ([@slorber](https://github.com/slorber)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-common`, `docusaurus` + - [#6651](https://github.com/facebook/docusaurus/pull/6651) refactor: reduce exported members of docusaurus router ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :bug: Bug Fix + +- `docusaurus-theme-common` + - [#6758](https://github.com/facebook/docusaurus/pull/6758) fix(theme-common): isSamePath should be case-insensitive ([@slorber](https://github.com/slorber)) + - [#6748](https://github.com/facebook/docusaurus/pull/6748) fix(theme-classic): temporarily disable toc heading autoscrolling ([@slorber](https://github.com/slorber)) + - [#6696](https://github.com/facebook/docusaurus/pull/6696) fix(theme-common): do not run useLocationChange when hot reloading ([@lex111](https://github.com/lex111)) + - [#6490](https://github.com/facebook/docusaurus/pull/6490) fix(theme-classic): do not switch color modes when printing ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6749](https://github.com/facebook/docusaurus/pull/6749) fix(theme-classic): fix breadcrumb home link bug with new useHomePageRoute() hook ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs` + - [#6720](https://github.com/facebook/docusaurus/pull/6720) fix(content-docs): create assets for frontmatter images ([@lebalz](https://github.com/lebalz)) + - [#6592](https://github.com/facebook/docusaurus/pull/6592) fix(content-docs): read last update from inner git repositories ([@felipecrs](https://github.com/felipecrs)) + - [#6477](https://github.com/facebook/docusaurus/pull/6477) fix(content-docs): export versioning utils ([@milesj](https://github.com/milesj)) +- `docusaurus-mdx-loader` + - [#6712](https://github.com/facebook/docusaurus/pull/6712) fix(mdx-loader): make headings containing links properly formatted in ToC ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#6701](https://github.com/facebook/docusaurus/pull/6701) fix(cli): disable directory listing in serve ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6607](https://github.com/facebook/docusaurus/pull/6607) fix(cli): log error itself on unhandled rejection ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6500](https://github.com/facebook/docusaurus/pull/6500) fix(cli): allow passing a list of file names to write-heading-ids ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6496](https://github.com/facebook/docusaurus/pull/6496) fix(core): configValidation should allow inline theme functions ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#6652](https://github.com/facebook/docusaurus/pull/6652) fix(theme-classic): minor BTT button fixes ([@lex111](https://github.com/lex111)) + - [#6612](https://github.com/facebook/docusaurus/pull/6612) fix(theme-classic): make Prism additional languages properly server-side rendered ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6599](https://github.com/facebook/docusaurus/pull/6599) fix(theme-classic): add docSidebar as allowed item in dropdown ([@homotechsual](https://github.com/homotechsual)) + - [#6531](https://github.com/facebook/docusaurus/pull/6531) fix(theme-classic): highlight active collapsible doc category properly ([@lex111](https://github.com/lex111)) + - [#6515](https://github.com/facebook/docusaurus/pull/6515) fix(theme-classic): add key prop for SimpleLinks map ([@kgajera](https://github.com/kgajera)) + - [#6508](https://github.com/facebook/docusaurus/pull/6508) fix(theme-classic): apply width/height for footer logos without href ([@kgajera](https://github.com/kgajera)) +- `docusaurus-utils` + - [#6617](https://github.com/facebook/docusaurus/pull/6617) fix(utils): convert Markdown links in reference-style links with multiple spaces ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6489](https://github.com/facebook/docusaurus/pull/6489) fix(utils): do not resolve Markdown paths with @site prefix ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6478](https://github.com/facebook/docusaurus/pull/6478) fix(utils): Markdown linkification match local paths beginning with http ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#6495](https://github.com/facebook/docusaurus/pull/6495) fix(content-docs): render category with no subitems as a normal link ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :nail_care: Polish + +- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#6755](https://github.com/facebook/docusaurus/pull/6755) refactor: unify error handling behavior ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus` + - [#6679](https://github.com/facebook/docusaurus/pull/6679) feat(create): better detection of package manager preference ([@lex111](https://github.com/lex111)) + - [#6481](https://github.com/facebook/docusaurus/pull/6481) refactor(init): promote good practices; use site alias ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs` + - [#6745](https://github.com/facebook/docusaurus/pull/6745) fix(content-docs): improve sidebar shorthand normalization error message ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6602](https://github.com/facebook/docusaurus/pull/6602) feat(content-docs): allow omitting enclosing array consistently for category shorthand ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6596](https://github.com/facebook/docusaurus/pull/6596) refactor(content-docs): clean up sidebars logic; validate generator returns ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6586](https://github.com/facebook/docusaurus/pull/6586) refactor(content-docs): read category metadata files before autogenerating ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus` + - [#6730](https://github.com/facebook/docusaurus/pull/6730) refactor: declare all props as interfaces ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-translations` + - [#6711](https://github.com/facebook/docusaurus/pull/6711) chore(theme-translations): complete Korean translations ([@revi](https://github.com/revi)) + - [#6686](https://github.com/facebook/docusaurus/pull/6686) fix(theme-translations): improve Korean translations ([@winterlood](https://github.com/winterlood)) + - [#6635](https://github.com/facebook/docusaurus/pull/6635) refactor(theme-translation): improve Traditional Chinese translation quality ([@toto6038](https://github.com/toto6038)) +- `docusaurus-theme-classic`, `docusaurus-theme-translations` + - [#6674](https://github.com/facebook/docusaurus/pull/6674) fix(theme-classic): improve aria label of color mode toggle ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-theme-classic` + - [#6668](https://github.com/facebook/docusaurus/pull/6668) refactor: recommend using data-theme without html element selector ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#6622](https://github.com/facebook/docusaurus/pull/6622) refactor(theme-classic): clean up CSS of doc sidebar item ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#6644](https://github.com/facebook/docusaurus/pull/6644) fix(core): forward ref to Link's anchor element ([@koistya](https://github.com/koistya)) + - [#6646](https://github.com/facebook/docusaurus/pull/6646) fix(cli): make docusaurus clear also remove .yarn/.cache folder ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6306](https://github.com/facebook/docusaurus/pull/6306) feat(core): use react-helmet-async ([@seyoon20087](https://github.com/seyoon20087)) +- `docusaurus-utils-validation` + - [#6656](https://github.com/facebook/docusaurus/pull/6656) feat: allow numbers in plugin ID ([@cdemonchy-pro](https://github.com/cdemonchy-pro)) +- `docusaurus-mdx-loader`, `docusaurus-utils`, `lqip-loader` + - [#6650](https://github.com/facebook/docusaurus/pull/6650) refactor(utils): replace hash with contenthash for file loader ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus-utils` + - [#6615](https://github.com/facebook/docusaurus/pull/6615) fix: remove more peer dependency warnings ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader` + - [#6598](https://github.com/facebook/docusaurus/pull/6598) feat: make Markdown images lazy loaded ([@johnnyreilly](https://github.com/johnnyreilly)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6505](https://github.com/facebook/docusaurus/pull/6505) fix(theme-classic): make focused link outlined with JS disabled ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#6507](https://github.com/facebook/docusaurus/pull/6507) refactor: improve internal typing ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus-utils` + - [#6498](https://github.com/facebook/docusaurus/pull/6498) fix: updating peerDependency fields for yarn berry ([@vidarc](https://github.com/vidarc)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations` + - [#6482](https://github.com/facebook/docusaurus/pull/6482) feat: mark some text labels as translatable ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :memo: Documentation + +- Other + - [#6727](https://github.com/facebook/docusaurus/pull/6727) docs: add Blog Matheus Brunelli site to showcase ([@mrbrunelli](https://github.com/mrbrunelli)) + - [#6721](https://github.com/facebook/docusaurus/pull/6721) docs: add Butterfly Documentation to showcase ([@CodeDoctorDE](https://github.com/CodeDoctorDE)) + - [#6710](https://github.com/facebook/docusaurus/pull/6710) docs(website): Add techharvesting to showcase ([@NaseelNiyas](https://github.com/NaseelNiyas)) + - [#6708](https://github.com/facebook/docusaurus/pull/6708) docs: add doc for generated-index keyword/image metadata ([@slorber](https://github.com/slorber)) + - [#6709](https://github.com/facebook/docusaurus/pull/6709) docs(website): fix video responsiveness ([@lex111](https://github.com/lex111)) + - [#6687](https://github.com/facebook/docusaurus/pull/6687) docs: add deep dive video for Docusaurus ([@dmitryvinn](https://github.com/dmitryvinn)) + - [#6704](https://github.com/facebook/docusaurus/pull/6704) docs(website): search doc typo searchParameters ([@slorber](https://github.com/slorber)) + - [#6682](https://github.com/facebook/docusaurus/pull/6682) docs: add redux-cool site to showcase ([@Ruben-Arushanyan](https://github.com/Ruben-Arushanyan)) + - [#6677](https://github.com/facebook/docusaurus/pull/6677) docs: add Rivalis to showcase ([@kalevski](https://github.com/kalevski)) + - [#6676](https://github.com/facebook/docusaurus/pull/6676) docs: add SmartCookieWeb site to showcase ([@CookieJarApps](https://github.com/CookieJarApps)) + - [#6675](https://github.com/facebook/docusaurus/pull/6675) docs: mention that all official themes are TypeScript-covered ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6673](https://github.com/facebook/docusaurus/pull/6673) docs: mention about blog date in front matter ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6672](https://github.com/facebook/docusaurus/pull/6672) refactor(website): extract homepage data from UI; feature text updates ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6670](https://github.com/facebook/docusaurus/pull/6670) docs: add CyberDrain Improved Partner Portal (CIPP) to showcase ([@homotechsual](https://github.com/homotechsual)) + - [#6667](https://github.com/facebook/docusaurus/pull/6667) fix(website): make YT iframe responsive ([@lex111](https://github.com/lex111)) + - [#6659](https://github.com/facebook/docusaurus/pull/6659) docs: add eli5 video to home page ([@dmitryvinn-fb](https://github.com/dmitryvinn-fb)) + - [#6633](https://github.com/facebook/docusaurus/pull/6633) docs: improve wording of using Markdown file paths ([@BigDataWriter](https://github.com/BigDataWriter)) + - [#6624](https://github.com/facebook/docusaurus/pull/6624) docs: add Resoto & Some Engineering Inc. to showcase ([@TheCatLady](https://github.com/TheCatLady)) + - [#6611](https://github.com/facebook/docusaurus/pull/6611) docs: fix bad anchor link syntax ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6591](https://github.com/facebook/docusaurus/pull/6591) docs: improve GitHub Actions example jobs ([@ebarojas](https://github.com/ebarojas)) + - [#6426](https://github.com/facebook/docusaurus/pull/6426) feat(website): add Tweets section ([@yangshun](https://github.com/yangshun)) + - [#6532](https://github.com/facebook/docusaurus/pull/6532) docs: add SAP Cloud SDK to showcase ([@artemkovalyov](https://github.com/artemkovalyov)) + - [#6513](https://github.com/facebook/docusaurus/pull/6513) docs: clean up CONTRIBUTING ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6501](https://github.com/facebook/docusaurus/pull/6501) docs: add Cloudflare pages deployment guide ([@apidev234](https://github.com/apidev234)) + - [#6499](https://github.com/facebook/docusaurus/pull/6499) docs: mention how env vars can be read ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6492](https://github.com/facebook/docusaurus/pull/6492) docs: mention where to find the sitemap ([@tamalweb](https://github.com/tamalweb)) + - [#6491](https://github.com/facebook/docusaurus/pull/6491) docs: add developers.verida to showcase ([@nick-verida](https://github.com/nick-verida)) + - [#6414](https://github.com/facebook/docusaurus/pull/6414) feat(website): new plugin to load CHANGELOG and render as blog ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6404](https://github.com/facebook/docusaurus/pull/6404) docs: elaborate on Markdown asset linking; document pathname:// protocol ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6484](https://github.com/facebook/docusaurus/pull/6484) docs: remove mention that CDN resources are cached cross-domain ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6429](https://github.com/facebook/docusaurus/pull/6429) refactor: self-host KaTeX assets ([@pranabdas](https://github.com/pranabdas)) + - [#6483](https://github.com/facebook/docusaurus/pull/6483) docs: mark a lot of website texts as translatable ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-preset-classic` + - [#6627](https://github.com/facebook/docusaurus/pull/6627) docs: fix presets documentation link ([@thedanielhanke](https://github.com/thedanielhanke)) + +#### :house: Internal + +- `docusaurus-theme-classic` + - [#6759](https://github.com/facebook/docusaurus/pull/6759) refactor(theme-classic): merge CSS files for Heading ([@slorber](https://github.com/slorber)) + - [#6584](https://github.com/facebook/docusaurus/pull/6584) misc: enable jsx-key eslint rule ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate` + - [#6756](https://github.com/facebook/docusaurus/pull/6756) test: sort migration test FS mock calls ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6609](https://github.com/facebook/docusaurus/pull/6609) refactor(migrate): change internal methods' parameter style ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6476](https://github.com/facebook/docusaurus/pull/6476) chore: fix Stylelint globs for editor support ([@nschonni](https://github.com/nschonni)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#6744](https://github.com/facebook/docusaurus/pull/6744) fix(content-docs): properly display collocated social card image ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-types`, `docusaurus` + - [#6742](https://github.com/facebook/docusaurus/pull/6742) refactor: improve client modules types ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases` + - [#6741](https://github.com/facebook/docusaurus/pull/6741) chore(module-type-aliases): add react as peer dependency ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6658](https://github.com/facebook/docusaurus/pull/6658) refactor(module-aliases): remove react-helmet dependency ([@Josh-Cena](https://github.com/Josh-Cena)) +- Other + - [#6726](https://github.com/facebook/docusaurus/pull/6726) misc: improve bug report template ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6512](https://github.com/facebook/docusaurus/pull/6512) misc: configure linguist behavior to show better language stats ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6487](https://github.com/facebook/docusaurus/pull/6487) chore: fix codesandbox example link + mention npm publish recovery ([@slorber](https://github.com/slorber)) + - [#6486](https://github.com/facebook/docusaurus/pull/6486) chore: update examples for beta.15 ([@slorber](https://github.com/slorber)) + - [#6485](https://github.com/facebook/docusaurus/pull/6485) fix(website): bad translate tags without default translation ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#6716](https://github.com/facebook/docusaurus/pull/6716) refactor: ensure lodash is default-imported ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-logger`, `docusaurus-migrate`, `docusaurus` + - [#6661](https://github.com/facebook/docusaurus/pull/6661) refactor: convert CLI entry points to ESM; migrate create-docusaurus to ESM ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-common`, `docusaurus` + - [#6651](https://github.com/facebook/docusaurus/pull/6651) refactor: reduce exported members of docusaurus router ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#6629](https://github.com/facebook/docusaurus/pull/6629) refactor: move module declarations for non-route components to theme-classic ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-pwa`, `docusaurus-theme-classic` + - [#6614](https://github.com/facebook/docusaurus/pull/6614) refactor: remove Babel plugins that are included in preset-env ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#6605](https://github.com/facebook/docusaurus/pull/6605) chore: fix ESLint warnings, restrict export all syntax ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia` + - [#6583](https://github.com/facebook/docusaurus/pull/6583) refactor(live-codeblock): migrate theme to TS ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#6524](https://github.com/facebook/docusaurus/pull/6524) refactor: enforce named capture groups; clean up regexes ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate`, `docusaurus-plugin-content-docs`, `docusaurus` + - [#6521](https://github.com/facebook/docusaurus/pull/6521) refactor: mark all functions that import external modules as async ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-cssnano-preset`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` + - [#6514](https://github.com/facebook/docusaurus/pull/6514) chore: clean up ESLint config, enable a few rules ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-types`, `docusaurus` + - [#6511](https://github.com/facebook/docusaurus/pull/6511) refactor(core): convert theme-fallback to TS ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-utils` + - [#6506](https://github.com/facebook/docusaurus/pull/6506) test: add test for readOutputHTMLFile ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate`, `docusaurus-theme-common` + - [#6502](https://github.com/facebook/docusaurus/pull/6502) refactor: fix all eslint warnings ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus` + - [#6474](https://github.com/facebook/docusaurus/pull/6474) test: rename 'fixtures' to '**fixtures**' ([@nschonni](https://github.com/nschonni)) + +#### :running_woman: Performance + +- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus` + - [#6725](https://github.com/facebook/docusaurus/pull/6725) refactor: convert all fs methods to async ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### Committers: 38 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Artem Kovalov ([@artemkovalyov](https://github.com/artemkovalyov)) +- Balthasar Hofer ([@lebalz](https://github.com/lebalz)) +- Clement Demonchy ([@cdemonchy-pro](https://github.com/cdemonchy-pro)) +- CodeDoctor ([@CodeDoctorDE](https://github.com/CodeDoctorDE)) +- Daniel Hanke ([@thedanielhanke](https://github.com/thedanielhanke)) +- Daniel Kalevski ([@kalevski](https://github.com/kalevski)) +- Dmitry Vinnik ([@dmitryvinn](https://github.com/dmitryvinn)) +- Dmitry Vinnik | Meta ([@dmitryvinn-fb](https://github.com/dmitryvinn-fb)) +- Erick Zhao ([@erickzhao](https://github.com/erickzhao)) +- Everardo J. Barojas M. ([@ebarojas](https://github.com/ebarojas)) +- Felipe Santos ([@felipecrs](https://github.com/felipecrs)) +- Gaurish ([@apidev234](https://github.com/apidev234)) +- Hong Yongmin ([@revi](https://github.com/revi)) +- Jody Heavener ([@jodyheavener](https://github.com/jodyheavener)) +- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Kishan Gajera ([@kgajera](https://github.com/kgajera)) +- Konstantin Tarkus ([@koistya](https://github.com/koistya)) +- Matheus Ricardo Brunelli ([@mrbrunelli](https://github.com/mrbrunelli)) +- Matthew Ailes ([@vidarc](https://github.com/vidarc)) +- Mikey O'Toole ([@homotechsual](https://github.com/homotechsual)) +- Miles Johnson ([@milesj](https://github.com/milesj)) +- Muhammad Redho Ayassa ([@redhoyasa](https://github.com/redhoyasa)) +- Naseel Niyas ([@NaseelNiyas](https://github.com/NaseelNiyas)) +- Nick Schonning ([@nschonni](https://github.com/nschonni)) +- Pranab Das ([@pranabdas](https://github.com/pranabdas)) +- Ruben Arushanyan ([@Ruben-Arushanyan](https://github.com/Ruben-Arushanyan)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tamal Web ([@tamalweb](https://github.com/tamalweb)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) +- [@BigDataWriter](https://github.com/BigDataWriter) +- [@CookieJarApps](https://github.com/CookieJarApps) +- [@TheCatLady](https://github.com/TheCatLady) +- [@nick-verida](https://github.com/nick-verida) +- [@seyoon20087](https://github.com/seyoon20087) +- [@toto6038](https://github.com/toto6038) +- 이정환 ([@winterlood](https://github.com/winterlood)) + +## 2.0.0-beta.15 (2022-01-26) + +#### :rocket: New Feature + +- `docusaurus-plugin-content-docs` + - [#6451](https://github.com/facebook/docusaurus/pull/6451) feat(content-docs): expose isCategoryIndex matcher to customize conventions ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5782](https://github.com/facebook/docusaurus/pull/5782) feat(content-docs): displayed_sidebar front matter ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6466](https://github.com/facebook/docusaurus/pull/6466) feat(theme-classic): add stable class for DocSidebarContainer ([@homotechsual](https://github.com/homotechsual)) + - [#3811](https://github.com/facebook/docusaurus/pull/3811) feat(theme-classic): auto-collapse sibling categories in doc sidebar ([@josephriosIO](https://github.com/josephriosIO)) + - [#6216](https://github.com/facebook/docusaurus/pull/6216) feat(theme-classic): usable CodeBlock outside markdown ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#6416](https://github.com/facebook/docusaurus/pull/6416) feat(content-blog): allow authors list to contain images only ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog` + - [#6415](https://github.com/facebook/docusaurus/pull/6415) feat(content-blog): allow disabling generating archive ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6245](https://github.com/facebook/docusaurus/pull/6245) feat(content-blog): parse date from middle of file path ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6388](https://github.com/facebook/docusaurus/pull/6388) feat(content-blog): include tags in feed ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#6371](https://github.com/facebook/docusaurus/pull/6371) feat(core, theme-classic): allow overriding htmlLang ([@noomorph](https://github.com/noomorph)) +- `docusaurus-mdx-loader` + - [#6323](https://github.com/facebook/docusaurus/pull/6323) feat(mdx-loader): preserve hash in image src; support GH themed images ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#6139](https://github.com/facebook/docusaurus/pull/6139) feat(theme-classic): new navbar item linking to a sidebar ([@lmpham1](https://github.com/lmpham1)) + - [#6239](https://github.com/facebook/docusaurus/pull/6239) feat(content-docs): allow SEO metadata for category index pages ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-sitemap` + - [#6248](https://github.com/facebook/docusaurus/pull/6248) feat(sitemap): remove trailingSlash option; respect noIndex config ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-ideal-image`, `docusaurus-theme-translations` + - [#6173](https://github.com/facebook/docusaurus/pull/6173) feat(ideal-image): allow translating status messages ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-ideal-image` + - [#6155](https://github.com/facebook/docusaurus/pull/6155) feat(ideal-image): new option disableInDev ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-translations` + - [#6169](https://github.com/facebook/docusaurus/pull/6169) feat(theme-translations): add Italian translations ([@mcallisto](https://github.com/mcallisto)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-types`, `docusaurus` + - [#6166](https://github.com/facebook/docusaurus/pull/6166) feat: async plugin creator functions ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#6165](https://github.com/facebook/docusaurus/pull/6165) feat(core): async docusaurus.config.js creator function ([@slorber](https://github.com/slorber)) + +#### :boom: Breaking Change + +- `docusaurus-theme-search-algolia` + - [#6407](https://github.com/facebook/docusaurus/pull/6407) feat(search): enable contextual search by default ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia` + - [#6289](https://github.com/facebook/docusaurus/pull/6289) refactor: move @theme/hooks to @docusaurus/theme-common ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#6283](https://github.com/facebook/docusaurus/pull/6283) refactor(theme-classic): apply import/no-named-export eslint rule ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-sitemap` + - [#6248](https://github.com/facebook/docusaurus/pull/6248) feat(sitemap): remove trailingSlash option; respect noIndex config ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :bug: Bug Fix + +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus` + - [#6454](https://github.com/facebook/docusaurus/pull/6454) fix(content-blog): generate feed by reading build output ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus` + - [#6468](https://github.com/facebook/docusaurus/pull/6468) fix(init): cd to correct path when installing ([@gabrielcsapo](https://github.com/gabrielcsapo)) +- `docusaurus-mdx-loader` + - [#4827](https://github.com/facebook/docusaurus/pull/4827) fix: allow links to JSON in .md files to be transformed as asset links ([@antmcc49](https://github.com/antmcc49)) +- `docusaurus-plugin-content-docs` + - [#6435](https://github.com/facebook/docusaurus/pull/6435) fix(content-docs): make getActivePlugin match plugin paths more exactly ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6310](https://github.com/facebook/docusaurus/pull/6310) fix: highlight appropriate navItem when browsing generated category index ([@tapanchudasama](https://github.com/tapanchudasama)) + - [#6202](https://github.com/facebook/docusaurus/pull/6202) fix(content-docs): quotify path when retrieving git history ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#6424](https://github.com/facebook/docusaurus/pull/6424) fix(core): fix css url("image.png"), use css-loader v6 with esModules: false ([@slorber](https://github.com/slorber)) + - [#6378](https://github.com/facebook/docusaurus/pull/6378) fix(core): do not coerce webpack warning to string ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6197](https://github.com/facebook/docusaurus/pull/6197) fix(cli): quotify temp path in deploy command ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6168](https://github.com/facebook/docusaurus/pull/6168) fix(core): update webpack-dev-server + fix deprecation warning ([@slorber](https://github.com/slorber)) +- `docusaurus-logger`, `docusaurus-utils` + - [#6384](https://github.com/facebook/docusaurus/pull/6384) fix(logger): properly stringify objects for logging ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus` + - [#6338](https://github.com/facebook/docusaurus/pull/6338) fix(core): error boundary should allow no children ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#6314](https://github.com/facebook/docusaurus/pull/6314) fix(theme-classic): fix mobile version dropdown label with only one version ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6288](https://github.com/facebook/docusaurus/pull/6288) fix(theme-classic): add missing role=region to SkipToContent ([@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)) + - [#6213](https://github.com/facebook/docusaurus/pull/6213) refactor(theme-classic): extract common PaginatorNavLink component ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6177](https://github.com/facebook/docusaurus/pull/6177) fix(theme-classic): make React elements in pre render correctly ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#6300](https://github.com/facebook/docusaurus/pull/6300) refactor: move exported type definitions to declaration file ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate` + - [#6276](https://github.com/facebook/docusaurus/pull/6276) fix(migrate): migration CLI should correctly migrate gtag options ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog` + - [#6244](https://github.com/facebook/docusaurus/pull/6244) fix(content-blog): always convert front matter date as UTC ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-utils`, `docusaurus` + - [#6190](https://github.com/facebook/docusaurus/pull/6190) fix(utils): properly escape Windows paths ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :nail_care: Polish + +- `docusaurus-module-type-aliases` + - [#6469](https://github.com/facebook/docusaurus/pull/6469) fix(module-type-aliases): fix type def for translate params ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-search-algolia` + - [#6407](https://github.com/facebook/docusaurus/pull/6407) feat(search): enable contextual search by default ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader` + - [#6443](https://github.com/facebook/docusaurus/pull/6443) refactor(mdx-loader): use vfile.path to access Markdown file path ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#6427](https://github.com/facebook/docusaurus/pull/6427) feat(theme-classic): add aria-current to sidebar category link ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6391](https://github.com/facebook/docusaurus/pull/6391) refactor(theme-classic): add comments to Prism setup; minor refactor ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6240](https://github.com/facebook/docusaurus/pull/6240) refactor(theme-classic): use front matter from metadata for BlogPostPage ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#6419](https://github.com/facebook/docusaurus/pull/6419) feat(core): warn users about hand-modifying generated files ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6405](https://github.com/facebook/docusaurus/pull/6405) feat(core): check imported API name when extracting translations ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6291](https://github.com/facebook/docusaurus/pull/6291) feat(core): improve error message for BrowserOnly; better docs ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus` + - [#5822](https://github.com/facebook/docusaurus/pull/5822) feat: update website & init template palette to pass WCAG test; include contrast check in ColorGenerator ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6368](https://github.com/facebook/docusaurus/pull/6368) fix(create-docusaurus): add useBaseUrl for image URLs ([@alias-mac](https://github.com/alias-mac)) +- `docusaurus-plugin-content-pages`, `docusaurus-theme-classic` + - [#6400](https://github.com/facebook/docusaurus/pull/6400) feat(content-pages): front matter validation, include front matter in metadata ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-theme-classic` + - [#6339](https://github.com/facebook/docusaurus/pull/6339) feat(mdx-loader): read image dimensions when processing Markdown ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog` + - [#6388](https://github.com/facebook/docusaurus/pull/6388) feat(content-blog): include tags in feed ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6189](https://github.com/facebook/docusaurus/pull/6189) feat(content-blog): include front matter in loaded content metadata ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-common` + - [#6317](https://github.com/facebook/docusaurus/pull/6317) feat(theme-classic): autoscroll TOC with active link ([@cerkiewny](https://github.com/cerkiewny)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#6303](https://github.com/facebook/docusaurus/pull/6303) test(utils, mdx-loader, core): improve coverage ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-preset-classic` + - [#6284](https://github.com/facebook/docusaurus/pull/6284) fix(preset-classic): throw if preset finds GA options in theme config ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus` + - [#6186](https://github.com/facebook/docusaurus/pull/6186) refactor: print trailing new line when outputting JSON ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :memo: Documentation + +- Other + - [#6296](https://github.com/facebook/docusaurus/pull/6296) docs: add advanced guides ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6459](https://github.com/facebook/docusaurus/pull/6459) docs: add replicad to showcase ([@sgenoud](https://github.com/sgenoud)) + - [#6334](https://github.com/facebook/docusaurus/pull/6334) docs: 2021 recap blog post ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6458](https://github.com/facebook/docusaurus/pull/6458) docs: add Kuizuo's Personal Website to showcase ([@kuizuo](https://github.com/kuizuo)) + - [#6431](https://github.com/facebook/docusaurus/pull/6431) docs: add Koyeb as a deployment option ([@edouardb](https://github.com/edouardb)) + - [#6455](https://github.com/facebook/docusaurus/pull/6455) docs: add Sass Fairy to showcase ([@roydukkey](https://github.com/roydukkey)) + - [#6453](https://github.com/facebook/docusaurus/pull/6453) docs: document embedding generated index in doc page ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6450](https://github.com/facebook/docusaurus/pull/6450) docs: split sidebar documentation into sections ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6449](https://github.com/facebook/docusaurus/pull/6449) docs: multiple doc improvements ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6448](https://github.com/facebook/docusaurus/pull/6448) fix(website): update colors correctly when palette is only customized in one color mode ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6385](https://github.com/facebook/docusaurus/pull/6385) chore: add height/width for front page images ([@nschonni](https://github.com/nschonni)) + - [#6445](https://github.com/facebook/docusaurus/pull/6445) docs: update showcase data of InfraQL ([@jeffreyaven](https://github.com/jeffreyaven)) + - [#6433](https://github.com/facebook/docusaurus/pull/6433) docs: add kube-green to showcase ([@davidebianchi](https://github.com/davidebianchi)) + - [#6428](https://github.com/facebook/docusaurus/pull/6428) docs: elaborate on i18n tutorial ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6422](https://github.com/facebook/docusaurus/pull/6422) docs: add 404Lab wiki to showcase ([@HiChen404](https://github.com/HiChen404)) + - [#6420](https://github.com/facebook/docusaurus/pull/6420) fix(website): restore some site CSS in light mode ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6410](https://github.com/facebook/docusaurus/pull/6410) docs: add SODA for SPARC to showcase ([@megasanjay](https://github.com/megasanjay)) + - [#6417](https://github.com/facebook/docusaurus/pull/6417) docs: fix accessibility of search modal ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6406](https://github.com/facebook/docusaurus/pull/6406) docs(i18n): add docs for htmlLang config ([@noomorph](https://github.com/noomorph)) + - [#6393](https://github.com/facebook/docusaurus/pull/6393) docs: update Algolia docs for new DocSearch infra ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6383](https://github.com/facebook/docusaurus/pull/6383) docs: elaborate on different CSS class names ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6348](https://github.com/facebook/docusaurus/pull/6348) docs: add KaustubhK24's site to showcase ([@kaustubhk24](https://github.com/kaustubhk24)) + - [#6333](https://github.com/facebook/docusaurus/pull/6333) feat(website): search in showcase ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6344](https://github.com/facebook/docusaurus/pull/6344) fix(website): make ColorGenerator functional ([@shwaka](https://github.com/shwaka)) + - [#6340](https://github.com/facebook/docusaurus/pull/6340) docs: minor fix in the sample config for ESM ([@pranabdas](https://github.com/pranabdas)) + - [#6336](https://github.com/facebook/docusaurus/pull/6336) docs: make upgrade guide always show the latest version ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6320](https://github.com/facebook/docusaurus/pull/6320) chore: upgrade rehype-katex with ESM support, update docs ([@pranabdas](https://github.com/pranabdas)) + - [#6335](https://github.com/facebook/docusaurus/pull/6335) docs: add Pglet website to showcase ([@FeodorFitsner](https://github.com/FeodorFitsner)) + - [#6327](https://github.com/facebook/docusaurus/pull/6327) docs: remove typo bracket ([@MorookaKotaro](https://github.com/MorookaKotaro)) + - [#6316](https://github.com/facebook/docusaurus/pull/6316) docs: add bandwidth.com to showcase ([@ajrice6713](https://github.com/ajrice6713)) + - [#6313](https://github.com/facebook/docusaurus/pull/6313) docs: add Refine site to showcase ([@omeraplak](https://github.com/omeraplak)) + - [#6318](https://github.com/facebook/docusaurus/pull/6318) fix(website): various anchor link fixes ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6308](https://github.com/facebook/docusaurus/pull/6308) fix(website): wrap details in mdx-code-block ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6307](https://github.com/facebook/docusaurus/pull/6307) docs: document MD and JSX interoperability issues ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6299](https://github.com/facebook/docusaurus/pull/6299) docs: add icodex to showcase ([@wood3n](https://github.com/wood3n)) + - [#6297](https://github.com/facebook/docusaurus/pull/6297) docs: mention setup in monorepo ([@PatelN123](https://github.com/PatelN123)) + - [#6293](https://github.com/facebook/docusaurus/pull/6293) docs: remove GraphQL mesh from showcase ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6231](https://github.com/facebook/docusaurus/pull/6231) docs: update showcase images; remove GraphQL Code Generator site ([@PatelN123](https://github.com/PatelN123)) + - [#6285](https://github.com/facebook/docusaurus/pull/6285) refactor(website): further optimize showcase images ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6281](https://github.com/facebook/docusaurus/pull/6281) docs: Add kwatch to showcase ([@abahmed](https://github.com/abahmed)) + - [#6280](https://github.com/facebook/docusaurus/pull/6280) docs: elaborate on doc versioning ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6043](https://github.com/facebook/docusaurus/pull/6043) fix(website): resize showcase images, tighten CI check ([@armano2](https://github.com/armano2)) + - [#6274](https://github.com/facebook/docusaurus/pull/6274) docs: add dyte docs to showcase ([@vaibhavshn](https://github.com/vaibhavshn)) + - [#6278](https://github.com/facebook/docusaurus/pull/6278) docs: add Khyron Realm to showcase ([@alexgrigoras](https://github.com/alexgrigoras)) + - [#6271](https://github.com/facebook/docusaurus/pull/6271) docs: add FlatifyCSS to showcase ([@amir2mi](https://github.com/amir2mi)) + - [#6275](https://github.com/facebook/docusaurus/pull/6275) fix(website): fix config-tabs breaking after translation ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6269](https://github.com/facebook/docusaurus/pull/6269) docs: add Ionic to showcase ([@ltm](https://github.com/ltm)) + - [#6272](https://github.com/facebook/docusaurus/pull/6272) docs: make tsconfig work OOTB in typescript guide ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6265](https://github.com/facebook/docusaurus/pull/6265) docs: add Eric JiuRan's blog to showcase ([@1084350607](https://github.com/1084350607)) + - [#6242](https://github.com/facebook/docusaurus/pull/6242) docs(showcase): update oxidizer website url ([@vandreleal](https://github.com/vandreleal)) + - [#6226](https://github.com/facebook/docusaurus/pull/6226) docs: update showcase data for digital support notes ([@PatelN123](https://github.com/PatelN123)) + - [#6224](https://github.com/facebook/docusaurus/pull/6224) docs: add TalentBrick to showcase ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6223](https://github.com/facebook/docusaurus/pull/6223) docs: normalize CodeBlock highlighting ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6214](https://github.com/facebook/docusaurus/pull/6214) feat(website): improve prism themes ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6215](https://github.com/facebook/docusaurus/pull/6215) docs: use BrowserWindow for Markdown demos ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6193](https://github.com/facebook/docusaurus/pull/6193) docs: normalize plugin API documentation ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6209](https://github.com/facebook/docusaurus/pull/6209) docs: elaborate on static asset resolution ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6207](https://github.com/facebook/docusaurus/pull/6207) docs: add default value for BrowserWindow URL field ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6206](https://github.com/facebook/docusaurus/pull/6206) docs: fix highlighting of YAML front matter ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6191](https://github.com/facebook/docusaurus/pull/6191) docs: fix react live scope button color in dark mode ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6188](https://github.com/facebook/docusaurus/pull/6188) docs: add Layer0 to deployment guide ([@rishi-raj-jain](https://github.com/rishi-raj-jain)) + - [#6184](https://github.com/facebook/docusaurus/pull/6184) docs: remove mention of 'UA-' in gtag ([@johnnyreilly](https://github.com/johnnyreilly)) + - [#6181](https://github.com/facebook/docusaurus/pull/6181) docs: add GTFS-to-HTML to showcase ([@brendannee](https://github.com/brendannee)) + - [#6178](https://github.com/facebook/docusaurus/pull/6178) docs: add Digital Support Notes to showcase ([@PatelN123](https://github.com/PatelN123)) + - [#6170](https://github.com/facebook/docusaurus/pull/6170) docs: add LabVIEW coding experience to showcase ([@ruanqizhen](https://github.com/ruanqizhen)) + - [#6164](https://github.com/facebook/docusaurus/pull/6164) docs: fix import module name of theme/Admonition ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6158](https://github.com/facebook/docusaurus/pull/6158) docs: add Astronomer to showcase ([@jwitz](https://github.com/jwitz)) +- `create-docusaurus` + - [#5822](https://github.com/facebook/docusaurus/pull/5822) feat: update website & init template palette to pass WCAG test; include contrast check in ColorGenerator ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6187](https://github.com/facebook/docusaurus/pull/6187) docs: make installation guide more beginner-friendly ([@PatelN123](https://github.com/PatelN123)) +- `docusaurus-utils` + - [#6204](https://github.com/facebook/docusaurus/pull/6204) docs: recommend highlighting with comments than number range ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-theme-classic` + - [#6203](https://github.com/facebook/docusaurus/pull/6203) docs: audit grammar issues ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :house: Internal + +- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#6456](https://github.com/facebook/docusaurus/pull/6456) chore: add cSpell for spell checking ([@nschonni](https://github.com/nschonni)) +- Other + - [#6444](https://github.com/facebook/docusaurus/pull/6444) misc: update nvmrc to 14.17.0 to meet dependency requirements ([@jodyheavener](https://github.com/jodyheavener)) + - [#6441](https://github.com/facebook/docusaurus/pull/6441) misc: fix stylelint erroring when lint-staged passed ignored file ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6421](https://github.com/facebook/docusaurus/pull/6421) chore: fix yarn build:website:fast ([@slorber](https://github.com/slorber)) + - [#6381](https://github.com/facebook/docusaurus/pull/6381) chore(website): set cache-control for static assets ([@nschonni](https://github.com/nschonni)) + - [#6364](https://github.com/facebook/docusaurus/pull/6364) chore: remove Intl polyfills for Jest ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6325](https://github.com/facebook/docusaurus/pull/6325) chore: add Dependabot for dependency updates ([@nschonni](https://github.com/nschonni)) + - [#6328](https://github.com/facebook/docusaurus/pull/6328) chore(ci): upgrade actions/github-script to v5 ([@nschonni](https://github.com/nschonni)) + - [#6332](https://github.com/facebook/docusaurus/pull/6332) chore(deps): bump follow-redirects from 1.14.5 to 1.14.7 ([@dependabot[bot]](https://github.com/apps/dependabot)) + - [#6326](https://github.com/facebook/docusaurus/pull/6326) misc(ci): remove redundant "CI: true" env ([@nschonni](https://github.com/nschonni)) + - [#6304](https://github.com/facebook/docusaurus/pull/6304) chore: upgrade to Husky 7 ([@nschonni](https://github.com/nschonni)) + - [#6222](https://github.com/facebook/docusaurus/pull/6222) test: ensure consistent CSS ordering ([@slorber](https://github.com/slorber)) + - [#6159](https://github.com/facebook/docusaurus/pull/6159) docs: remove useless comment ([@slorber](https://github.com/slorber)) + - [#6148](https://github.com/facebook/docusaurus/pull/6148) chore(examples): update examples to 2.0.0-beta.14 ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-debug`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#6442](https://github.com/facebook/docusaurus/pull/6442) chore: enable stylelint standard config ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus` + - [#6440](https://github.com/facebook/docusaurus/pull/6440) chore: remove some unused dependencies from package.json ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#6436](https://github.com/facebook/docusaurus/pull/6436) refactor(theme-classic): render BlogPostItem as one JSX element ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6283](https://github.com/facebook/docusaurus/pull/6283) refactor(theme-classic): apply import/no-named-export eslint rule ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-pages` + - [#6413](https://github.com/facebook/docusaurus/pull/6413) fix(content-pages): declare hide_table_of_contents as boolean ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus` + - [#6399](https://github.com/facebook/docusaurus/pull/6399) refactor: clean up TODO comments ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-cssnano-preset`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-theme-translations`, `docusaurus` + - [#6387](https://github.com/facebook/docusaurus/pull/6387) test: improve test coverage ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-utils` + - [#6380](https://github.com/facebook/docusaurus/pull/6380) chore: enable a few fixable ESLint rules ([@nschonni](https://github.com/nschonni)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-docs`, `docusaurus-utils`, `docusaurus` + - [#6377](https://github.com/facebook/docusaurus/pull/6377) refactor: use findAsyncSequential in a few places ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` + - [#6375](https://github.com/facebook/docusaurus/pull/6375) chore: enable eslint-plugin-jest ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus` + - [#6373](https://github.com/facebook/docusaurus/pull/6373) chore: enable react/jsx-closing-bracket-location ([@nschonni](https://github.com/nschonni)) +- `docusaurus-theme-classic`, `stylelint-copyright` + - [#6374](https://github.com/facebook/docusaurus/pull/6374) feat(stylelint-copyright): autofix, stricter config ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-cssnano-preset`, `docusaurus-theme-classic` + - [#6372](https://github.com/facebook/docusaurus/pull/6372) chore: add baseline stylelint rules ([@nschonni](https://github.com/nschonni)) +- `create-docusaurus`, `docusaurus-plugin-debug`, `docusaurus-theme-classic` + - [#6369](https://github.com/facebook/docusaurus/pull/6369) chore: upgrade lint-staged and globs ([@nschonni](https://github.com/nschonni)) +- `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus` + - [#6341](https://github.com/facebook/docusaurus/pull/6341) chore: regenerate yarn.lock ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-pages`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus` + - [#6324](https://github.com/facebook/docusaurus/pull/6324) chore: minor typo cleanup ([@nschonni](https://github.com/nschonni)) +- `create-docusaurus`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` + - [#6286](https://github.com/facebook/docusaurus/pull/6286) misc: convert all internal scripts to ESM ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia` + - [#6289](https://github.com/facebook/docusaurus/pull/6289) refactor: move @theme/hooks to @docusaurus/theme-common ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia` + - [#6287](https://github.com/facebook/docusaurus/pull/6287) refactor: new @docusaurus/plugin-content-docs/client interface ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#6279](https://github.com/facebook/docusaurus/pull/6279) refactor(core): use native types from webpack-dev-server ([@RDIL](https://github.com/RDIL)) +- `docusaurus-plugin-content-docs` + - [#6277](https://github.com/facebook/docusaurus/pull/6277) refactor(content-docs): make readVersionsMetadata async ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-types`, `docusaurus` + - [#6237](https://github.com/facebook/docusaurus/pull/6237) refactor(core): convert serverEntry.js to TS ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#6230](https://github.com/facebook/docusaurus/pull/6230) refactor: enforce type import specifiers ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-plugin-content-blog`, `docusaurus-utils`, `docusaurus` + - [#6229](https://github.com/facebook/docusaurus/pull/6229) refactor(utils): reorganize functions; move authors file resolution to utils ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-translations` + - [#6225](https://github.com/facebook/docusaurus/pull/6225) refactor(theme-translations): improve typing for update script ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6174](https://github.com/facebook/docusaurus/pull/6174) misc(theme-translations): multiple improvements to the update CLI ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### Committers: 46 + +- AJ Rice ([@ajrice6713](https://github.com/ajrice6713)) +- Abdelrahman Ahmed ([@abahmed](https://github.com/abahmed)) +- Alexandru Grigoras ([@alexgrigoras](https://github.com/alexgrigoras)) +- Amir M. Mohamadi ([@amir2mi](https://github.com/amir2mi)) +- Anthony McCaigue ([@antmcc49](https://github.com/antmcc49)) +- Armano ([@armano2](https://github.com/armano2)) +- Brendan Nee ([@brendannee](https://github.com/brendannee)) +- Chen ([@HiChen404](https://github.com/HiChen404)) +- Davide Bianchi ([@davidebianchi](https://github.com/davidebianchi)) +- Devtato ([@cerkiewny](https://github.com/cerkiewny)) +- Edouard Bonlieu ([@edouardb](https://github.com/edouardb)) +- Feodor Fitsner ([@FeodorFitsner](https://github.com/FeodorFitsner)) +- Filipe Guerra ([@alias-mac](https://github.com/alias-mac)) +- Gabriel Csapo ([@gabrielcsapo](https://github.com/gabrielcsapo)) +- Jake Witz ([@jwitz](https://github.com/jwitz)) +- Jeffrey Aven ([@jeffreyaven](https://github.com/jeffreyaven)) +- Jody Heavener ([@jodyheavener](https://github.com/jodyheavener)) +- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) +- Joseph ([@josephriosIO](https://github.com/josephriosIO)) +- Josh Goldberg ([@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Kaustubh Kulkarni ([@kaustubhk24](https://github.com/kaustubhk24)) +- Lars Mikkelsen ([@ltm](https://github.com/ltm)) +- Mikey O'Toole ([@homotechsual](https://github.com/homotechsual)) +- Minh Pham ([@lmpham1](https://github.com/lmpham1)) +- Morooka Kotaro ([@MorookaKotaro](https://github.com/MorookaKotaro)) +- Nayan Patel ([@PatelN123](https://github.com/PatelN123)) +- Nick Schonning ([@nschonni](https://github.com/nschonni)) +- Pranab Das ([@pranabdas](https://github.com/pranabdas)) +- Reece Dunham ([@RDIL](https://github.com/RDIL)) +- Rishi Raj Jain ([@rishi-raj-jain](https://github.com/rishi-raj-jain)) +- Sanjay Soundarajan ([@megasanjay](https://github.com/megasanjay)) +- Shun Wakatsuki ([@shwaka](https://github.com/shwaka)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tapan Chudasama ([@tapanchudasama](https://github.com/tapanchudasama)) +- Vaibhav Shinde ([@vaibhavshn](https://github.com/vaibhavshn)) +- Vandré Leal ([@vandreleal](https://github.com/vandreleal)) +- Yaroslav Serhieiev ([@noomorph](https://github.com/noomorph)) +- [@mcallisto](https://github.com/mcallisto) +- [@ruanqizhen](https://github.com/ruanqizhen) +- [@wood3n](https://github.com/wood3n) +- kuizuo ([@kuizuo](https://github.com/kuizuo)) +- sgenoud ([@sgenoud](https://github.com/sgenoud)) +- trent ([@roydukkey](https://github.com/roydukkey)) +- Ömer Faruk APLAK ([@omeraplak](https://github.com/omeraplak)) +- 久染 | JiuRan ([@1084350607](https://github.com/1084350607)) + +## 2.0.0-beta.14 (2021-12-21) + +#### :rocket: New Feature + +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6132](https://github.com/facebook/docusaurus/pull/6132) feat(theme-classic): new configuration syntax for a simple footer ([@christopherklint97](https://github.com/christopherklint97)) + - [#6125](https://github.com/facebook/docusaurus/pull/6125) feat(theme-common): stable classname for code blocks ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#5848](https://github.com/facebook/docusaurus/pull/5848) feat(theme-classic): standalone Admonition component ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6082](https://github.com/facebook/docusaurus/pull/6082) feat(theme-classic): allow passing additional attributes to tab headings ([@Drylozu](https://github.com/Drylozu)) +- `docusaurus-plugin-content-blog` + - [#6126](https://github.com/facebook/docusaurus/pull/6126) feat(content-blog): support json feed ([@notzheng](https://github.com/notzheng)) +- `docusaurus` + - [#6107](https://github.com/facebook/docusaurus/pull/6107) feat(core): allow plugins to customize/override Webpack devServer config ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-migrate` + - [#6146](https://github.com/facebook/docusaurus/pull/6146) fix(migrate): do not modify non-MD files ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#6128](https://github.com/facebook/docusaurus/pull/6128) fix: do not use aria-hidden in heading anchor links ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs` + - [#6124](https://github.com/facebook/docusaurus/pull/6124) fix(content-docs): restore behavior when pagination front matter is null ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6085](https://github.com/facebook/docusaurus/pull/6085) fix(content-docs): getMainDocId should return doc with both versioned or unversioned id ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-utils-validation` + - [#6097](https://github.com/facebook/docusaurus/pull/6097) fix: declare missing dependencies ([@merceyz](https://github.com/merceyz)) +- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-pwa`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `lqip-loader` + - [#6094](https://github.com/facebook/docusaurus/pull/6094) fix: add missing dependencies on tslib ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-translations` + - [#6088](https://github.com/facebook/docusaurus/pull/6088) fix(theme-translations): publish theme-translation lib, including typedef ([@slorber](https://github.com/slorber)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#6053](https://github.com/facebook/docusaurus/pull/6053) feat(theme-classic): allow stylizing doc paginator arrows ([@noomorph](https://github.com/noomorph)) + - [#6121](https://github.com/facebook/docusaurus/pull/6121) fix(theme-classic): add outline to focused code blocks ([@christopherklint97](https://github.com/christopherklint97)) + - [#6118](https://github.com/facebook/docusaurus/pull/6118) refactor: remove some useless code ([@lex111](https://github.com/lex111)) +- `create-docusaurus`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#5994](https://github.com/facebook/docusaurus/pull/5994) refactor: unify log format with new logger utility ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus` + - [#6119](https://github.com/facebook/docusaurus/pull/6119) fix(create-docusaurus): make initial editUrl functional ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6095](https://github.com/facebook/docusaurus/pull/6095) fix(create-docusaurus): give a clearer message when installation failed ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :memo: Documentation + +- [#6142](https://github.com/facebook/docusaurus/pull/6142) docs: normalize usage of placeholders ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#5918](https://github.com/facebook/docusaurus/pull/5918) docs: refactor & refine lifecycle API docs ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#6138](https://github.com/facebook/docusaurus/pull/6138) docs: add Smart Docs to showcase ([@wowtvds](https://github.com/wowtvds)) +- [#6137](https://github.com/facebook/docusaurus/pull/6137) docs: add ToolJet to showcase ([@withshubh](https://github.com/withshubh)) +- [#6141](https://github.com/facebook/docusaurus/pull/6141) docs: add WoodpeckerCI to showcase ([@6543](https://github.com/6543)) +- [#6135](https://github.com/facebook/docusaurus/pull/6135) docs: mention admonition quirks with Prettier ([@yangshun](https://github.com/yangshun)) +- [#6131](https://github.com/facebook/docusaurus/pull/6131) docs: elaborate on "docs-only" and "blog-only" ([@himanshu007-creator](https://github.com/himanshu007-creator)) +- [#6134](https://github.com/facebook/docusaurus/pull/6134) docs: update link to init template README.md ([@cmpadden](https://github.com/cmpadden)) +- [#6130](https://github.com/facebook/docusaurus/pull/6130) docs: refactor docs sidebar doc ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#6129](https://github.com/facebook/docusaurus/pull/6129) docs: refactor styling/theming docs ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#6112](https://github.com/facebook/docusaurus/pull/6112) docs: mention that SEO through front matter is better than head tag ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#6120](https://github.com/facebook/docusaurus/pull/6120) refactor(website): make deploy preview open next version docs by default ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#6111](https://github.com/facebook/docusaurus/pull/6111) docs: add Molecule website to showcase ([@wewoor](https://github.com/wewoor)) +- [#6089](https://github.com/facebook/docusaurus/pull/6089) docs: add Enarx website to showcase ([@HarshCasper](https://github.com/HarshCasper)) +- [#6090](https://github.com/facebook/docusaurus/pull/6090) docs: add sapphire to showcase ([@favna](https://github.com/favna)) +- [#6091](https://github.com/facebook/docusaurus/pull/6091) docs(showcase): "much more pages" => "many more pages" ([@favna](https://github.com/favna)) + +#### :house: Internal + +- `docusaurus-theme-classic` + - [#6144](https://github.com/facebook/docusaurus/pull/6144) fix(theme-classic): fix translation when footer has no links ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs` + - [#6143](https://github.com/facebook/docusaurus/pull/6143) test: fix async tests resolved in random order ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6123](https://github.com/facebook/docusaurus/pull/6123) test: use snapshots for sidebar tests ([@Josh-Cena](https://github.com/Josh-Cena)) +- Other + - [#6122](https://github.com/facebook/docusaurus/pull/6122) fix(website): fix yarn build:website:fast ([@slorber](https://github.com/slorber)) + - [#6080](https://github.com/facebook/docusaurus/pull/6080) chore: add npm and pnpm to E2E tests ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-cssnano-preset`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#6092](https://github.com/facebook/docusaurus/pull/6092) misc: ignore some files during npm publish ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### Committers: 17 + +- 6543 ([@6543](https://github.com/6543)) +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Christopher Klint ([@christopherklint97](https://github.com/christopherklint97)) +- Harsh Mishra ([@HarshCasper](https://github.com/HarshCasper)) +- Himanshu ([@himanshu007-creator](https://github.com/himanshu007-creator)) +- Jeroen Claassens ([@favna](https://github.com/favna)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Kristoffer K. ([@merceyz](https://github.com/merceyz)) +- Shubhendra Singh Chauhan ([@withshubh](https://github.com/withshubh)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Wout Vandesompele ([@wowtvds](https://github.com/wowtvds)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) +- Yaroslav Serhieiev ([@noomorph](https://github.com/noomorph)) +- Ziv ([@wewoor](https://github.com/wewoor)) +- [@Drylozu](https://github.com/Drylozu) +- colton ([@cmpadden](https://github.com/cmpadden)) +- 不郑 ([@notzheng](https://github.com/notzheng)) + +## 2.0.0-beta.13 (2021-12-10) + +Good npm publish, same code as beta.11 + +## 2.0.0-beta.12 (2021-12-10) + +Bad npm publish, use beta.13 instead + +## 2.0.0-beta.11 (2021-12-10) + +#### :bug: Bug Fix + +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia` + - [#6078](https://github.com/facebook/docusaurus/pull/6078) fix: move docusaurus core back to hard dependencies ([@pranabdas](https://github.com/pranabdas)) + +#### Committers: 2 + +- Pranab Das ([@pranabdas](https://github.com/pranabdas)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) + +## 2.0.0-beta.10 (2021-12-09) + +#### :rocket: New Feature + +- `create-docusaurus`, `docusaurus-types`, `docusaurus` + - [#5930](https://github.com/facebook/docusaurus/pull/5930) feat: shorthands for themes/plugins/presets configuration ([@fsmaia](https://github.com/fsmaia)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus` + - [#5830](https://github.com/facebook/docusaurus/pull/5830) feat(content-docs): sidebar category linking to document or auto-generated index page ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-types`, `docusaurus` + - [#4095](https://github.com/facebook/docusaurus/pull/4095) feat(core): allow sourcing from multiple static directories ([@oriooctopus](https://github.com/oriooctopus)) +- `create-docusaurus` + - [#3458](https://github.com/facebook/docusaurus/pull/3458) feat(create-docusaurus): allow using local folder as template ([@afshinm](https://github.com/afshinm)) +- `docusaurus-plugin-content-blog` + - [#5787](https://github.com/facebook/docusaurus/pull/5787) feat(content-blog): allow sorting posts in ascending order ([@cerkiewny](https://github.com/cerkiewny)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus` + - [#3104](https://github.com/facebook/docusaurus/pull/3104) feat(core): Add React ErrorBoundary component + theme default boundaries ([@spyke01](https://github.com/spyke01)) + +#### :boom: Breaking Change + +- `docusaurus-plugin-content-blog` + - [#6061](https://github.com/facebook/docusaurus/pull/6061) fix(content-blog): make post ID unique ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate`, `docusaurus-plugin-content-docs` + - [#6065](https://github.com/facebook/docusaurus/pull/6065) refactor: remove deprecated docs homePageId option ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs` + - [#6056](https://github.com/facebook/docusaurus/pull/6056) refactor: remove unused metadata field for homepage ([@lex111](https://github.com/lex111)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus` + - [#5830](https://github.com/facebook/docusaurus/pull/5830) feat(content-docs): sidebar category linking to document or auto-generated index page ([@slorber](https://github.com/slorber)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-preset-classic` + - [#5832](https://github.com/facebook/docusaurus/pull/5832) refactor(ganalytics, gtag): move options out of themeConfig ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils` + - [#5871](https://github.com/facebook/docusaurus/pull/5871) misc: replace all "Metadatas" with "Metadata" ([@swalahamani](https://github.com/swalahamani)) + +#### :bug: Bug Fix + +- `docusaurus-theme-common` + - [#6070](https://github.com/facebook/docusaurus/pull/6070) fix(theme-common): useLocationChange fire un-necessarily twice ([@slorber](https://github.com/slorber)) + - [#6040](https://github.com/facebook/docusaurus/pull/6040) fix: browser storage (localStorage) is unreliable: api should fail-safe ([@slorber](https://github.com/slorber)) +- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#6047](https://github.com/facebook/docusaurus/pull/6047) fix: make Docusaurus PnP strict mode compatible ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus` + - [#6052](https://github.com/facebook/docusaurus/pull/6052) fix(core): fix error boundary import disrupting CSS order ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog` + - [#6061](https://github.com/facebook/docusaurus/pull/6061) fix(content-blog): make post ID unique ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#5983](https://github.com/facebook/docusaurus/pull/5983) fix(core): do not apply theme-init alias to user component ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5798](https://github.com/facebook/docusaurus/pull/5798) fix(cli): update notifier should be shown if current is less than latest ([@semoal](https://github.com/semoal)) + - [#5864](https://github.com/facebook/docusaurus/pull/5864) fix: respect base URL when serving content by webpack dev server ([@lex111](https://github.com/lex111)) +- `docusaurus-module-type-aliases` + - [#5945](https://github.com/facebook/docusaurus/pull/5945) fix(module-type-aliases): add svg declaration ([@MisterFISHUP](https://github.com/MisterFISHUP)) +- `docusaurus-theme-classic` + - [#5873](https://github.com/facebook/docusaurus/pull/5873) fix(theme-classic): fix announcementBar css ([@slorber](https://github.com/slorber)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#6003](https://github.com/facebook/docusaurus/pull/6003) fix(theme-classic): make nav dropdowns focusable ([@robinmetral](https://github.com/robinmetral)) + - [#6000](https://github.com/facebook/docusaurus/pull/6000) fix(theme-classic): make hash link in heading not selectable ([@JararvisQ](https://github.com/JararvisQ)) + - [#5944](https://github.com/facebook/docusaurus/pull/5944) fix: translate all remaining english sentence in French ([@StanKocken](https://github.com/StanKocken)) +- `docusaurus-theme-classic`, `docusaurus` + - [#6048](https://github.com/facebook/docusaurus/pull/6048) refactor: capitalize locales when creating i18n config ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-translations` + - [#5976](https://github.com/facebook/docusaurus/pull/5976) feat(theme-translations): add extra Korean translation, fix typo ([@revi](https://github.com/revi)) + - [#6060](https://github.com/facebook/docusaurus/pull/6060) chore(theme-translations): complete Chinese translations ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate`, `docusaurus-plugin-content-docs` + - [#6065](https://github.com/facebook/docusaurus/pull/6065) refactor: remove deprecated docs homePageId option ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs` + - [#6056](https://github.com/facebook/docusaurus/pull/6056) refactor: remove unused metadata field for homepage ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#6049](https://github.com/facebook/docusaurus/pull/6049) refactor: simplify Toggle component ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-types` + - [#5981](https://github.com/facebook/docusaurus/pull/5981) refactor: minor ESLint improvements ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-pwa` + - [#5995](https://github.com/facebook/docusaurus/pull/5995) chore(plugin-pwa): change core-js version in package.json to v3 ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils` + - [#5849](https://github.com/facebook/docusaurus/pull/5849) refactor: define own translations in other themes ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-types` + - [#5959](https://github.com/facebook/docusaurus/pull/5959) refactor(types): correct HtmlTags types ([@armano2](https://github.com/armano2)) +- `docusaurus` + - [#5829](https://github.com/facebook/docusaurus/pull/5829) refactor: optimize clone and checkout in deploy command ([@sivapalan](https://github.com/sivapalan)) + - [#5899](https://github.com/facebook/docusaurus/pull/5899) feat(core): give more hints when plugins have duplicate IDs ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-preset-classic` + - [#5832](https://github.com/facebook/docusaurus/pull/5832) refactor(ganalytics, gtag): move options out of themeConfig ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus` + - [#5840](https://github.com/facebook/docusaurus/pull/5840) feat: allow GIT_USER env var to be unset if SSH is used ([@wpyoga](https://github.com/wpyoga)) +- `create-docusaurus`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils` + - [#5871](https://github.com/facebook/docusaurus/pull/5871) misc: replace all "Metadatas" with "Metadata" ([@swalahamani](https://github.com/swalahamani)) + +#### :memo: Documentation + +- Other + - [#6063](https://github.com/facebook/docusaurus/pull/6063) docs: add moja global to showcase ([@sohamsshah](https://github.com/sohamsshah)) + - [#6069](https://github.com/facebook/docusaurus/pull/6069) docs: update CONTRIBUTING for website ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6062](https://github.com/facebook/docusaurus/pull/6062) refactor(website): improve wording in comments of showcase data ([@sohamsshah](https://github.com/sohamsshah)) + - [#6045](https://github.com/facebook/docusaurus/pull/6045) docs: add "discord resources" to showcase ([@dexbiobot](https://github.com/dexbiobot)) + - [#6026](https://github.com/facebook/docusaurus/pull/6026) docs(deployment): add cost-benefit analysis with different options ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5955](https://github.com/facebook/docusaurus/pull/5955) docs: add Pearl UI website to showcase ([@agrawal-rohit](https://github.com/agrawal-rohit)) + - [#5989](https://github.com/facebook/docusaurus/pull/5989) misc: update CONTRIBUTING to reflect status quo ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5845](https://github.com/facebook/docusaurus/pull/5845) docs(admin): update repo testing instructions to reflect v2 ([@wpyoga](https://github.com/wpyoga)) + - [#6019](https://github.com/facebook/docusaurus/pull/6019) docs: update Netlify url config option in deployment instructions ([@rsapkf](https://github.com/rsapkf)) + - [#6015](https://github.com/facebook/docusaurus/pull/6015) docs: add Tremor website to showcase page ([@skoech](https://github.com/skoech)) + - [#5997](https://github.com/facebook/docusaurus/pull/5997) refactor(website): various fixes and improvements on Showcase page ([@lex111](https://github.com/lex111)) + - [#6008](https://github.com/facebook/docusaurus/pull/6008) docs: improve algolia integration instructions ([@shafy](https://github.com/shafy)) + - [#6006](https://github.com/facebook/docusaurus/pull/6006) docs: improve explanation for url config in GH Pages ([@Martinsos](https://github.com/Martinsos)) + - [#6001](https://github.com/facebook/docusaurus/pull/6001) docs: add Dime.Scheduler SDK to showcase ([@hbulens](https://github.com/hbulens)) + - [#5984](https://github.com/facebook/docusaurus/pull/5984) docs: add PREFS website to showcase ([@Patitotective](https://github.com/Patitotective)) + - [#5967](https://github.com/facebook/docusaurus/pull/5967) docs(website): Add docsearch migration blog post ([@slorber](https://github.com/slorber)) + - [#5968](https://github.com/facebook/docusaurus/pull/5968) refactor(website): shadow on showcase toggle ([@dsmmcken](https://github.com/dsmmcken)) + - [#5979](https://github.com/facebook/docusaurus/pull/5979) docs: update links to default translations dir ([@lex111](https://github.com/lex111)) + - [#5969](https://github.com/facebook/docusaurus/pull/5969) refactor(website): polish on Showcase page ([@slorber](https://github.com/slorber)) + - [#5966](https://github.com/facebook/docusaurus/pull/5966) docs: add Darklang to showcase ([@pbiggar](https://github.com/pbiggar)) + - [#5970](https://github.com/facebook/docusaurus/pull/5970) docs: add Remirror to showcase ([@ronnyroeller](https://github.com/ronnyroeller)) + - [#5971](https://github.com/facebook/docusaurus/pull/5971) docs: add Webiny docs to showcase page ([@swapnilmmane](https://github.com/swapnilmmane)) + - [#5953](https://github.com/facebook/docusaurus/pull/5953) docs: fix BrowserOnly return statement ([@MorookaKotaro](https://github.com/MorookaKotaro)) + - [#5949](https://github.com/facebook/docusaurus/pull/5949) docs: update Signoz showcase details ([@pal-sig](https://github.com/pal-sig)) + - [#5948](https://github.com/facebook/docusaurus/pull/5948) fix(website): fix APITable anchor ID having extra hash ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5947](https://github.com/facebook/docusaurus/pull/5947) fix(website): fix APITable anchor link ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5925](https://github.com/facebook/docusaurus/pull/5925) docs: add Froggit site to showcase page ([@cchaudier](https://github.com/cchaudier)) + - [#5928](https://github.com/facebook/docusaurus/pull/5928) docs: Add Shotstack showcase user ([@jeffski](https://github.com/jeffski)) + - [#5934](https://github.com/facebook/docusaurus/pull/5934) docs: fix a typo in CHANGELOG ([@KonstHardy](https://github.com/KonstHardy)) + - [#5921](https://github.com/facebook/docusaurus/pull/5921) docs: add Signoz site to showcase site ([@pal-sig](https://github.com/pal-sig)) + - [#5891](https://github.com/facebook/docusaurus/pull/5891) docs: new APITable comp to render large tables ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5917](https://github.com/facebook/docusaurus/pull/5917) docs: make API sidebar partially autogenerated ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5903](https://github.com/facebook/docusaurus/pull/5903) docs: refer to deployed branch as deployment rather than target ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5902](https://github.com/facebook/docusaurus/pull/5902) fix(website): fix i18n routes for Canny board ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5900](https://github.com/facebook/docusaurus/pull/5900) docs: document global variables in MDX scope ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#4409](https://github.com/facebook/docusaurus/pull/4409) docs: add example for GitHub Pages deployment; rewrite deployment section ([@polarathene](https://github.com/polarathene)) + - [#5888](https://github.com/facebook/docusaurus/pull/5888) docs: update GitHub deployment instructions ([@rootwork](https://github.com/rootwork)) + - [#5895](https://github.com/facebook/docusaurus/pull/5895) docs: Add juffalow.com to Docusaurus showcase ([@juffalow](https://github.com/juffalow)) + - [#5881](https://github.com/facebook/docusaurus/pull/5881) docs: fix wrong code sample in docusaurus-core ([@matthijsgroen](https://github.com/matthijsgroen)) + - [#5875](https://github.com/facebook/docusaurus/pull/5875) docs: add patrikmasiar website showcase ([@patrikmasiar](https://github.com/patrikmasiar)) + - [#5876](https://github.com/facebook/docusaurus/pull/5876) docs: '5 minutes tutorial' -> '5-minute tutorial' ([@molly](https://github.com/molly)) + - [#5759](https://github.com/facebook/docusaurus/pull/5759) docs: create SEO documentation page ([@cerkiewny](https://github.com/cerkiewny)) + - [#5869](https://github.com/facebook/docusaurus/pull/5869) docs: remove duplicated appId property ([@juzhiyuan](https://github.com/juzhiyuan)) + - [#5868](https://github.com/facebook/docusaurus/pull/5868) docs: fix a typo in using-themes.md ([@fishmandev](https://github.com/fishmandev)) + - [#5862](https://github.com/facebook/docusaurus/pull/5862) misc: show only latest archive alpha/beta versions dropdown ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#5742](https://github.com/facebook/docusaurus/pull/5742) feat(website): redesign of showcase page ([@chimailo](https://github.com/chimailo)) + +#### :house: Internal + +- `create-docusaurus`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-common`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus` + - [#6071](https://github.com/facebook/docusaurus/pull/6071) refactor: add blank lines below all copyright headers ([@Josh-Cena](https://github.com/Josh-Cena)) +- Other + - [#6068](https://github.com/facebook/docusaurus/pull/6068) chore: add prefix to needs triage label; separate Windows test workflow ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6031](https://github.com/facebook/docusaurus/pull/6031) chore: upgrade netlify-cli ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6012](https://github.com/facebook/docusaurus/pull/6012) chore(website): enable strict compiler option ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#6002](https://github.com/facebook/docusaurus/pull/6002) chore(ci): add GitHub action for showcase testing ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5977](https://github.com/facebook/docusaurus/pull/5977) chore: generate dogfooding test for long pathname during CI ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5950](https://github.com/facebook/docusaurus/pull/5950) misc(codeowners): add @Josh-Cena to CODEOWNERS ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5919](https://github.com/facebook/docusaurus/pull/5919) misc(workflow): E2E tests should not be run with website changes ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5907](https://github.com/facebook/docusaurus/pull/5907) chore(workflow): merge jobs into one workflow & give each job a name ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5889](https://github.com/facebook/docusaurus/pull/5889) chore(website): enable eslint in website ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5870](https://github.com/facebook/docusaurus/pull/5870) chore(README): fix broken GitHub Actions Workflow Status icon ([@HemantSachdeva](https://github.com/HemantSachdeva)) +- `docusaurus-module-type-aliases`, `docusaurus-types`, `docusaurus` + - [#6064](https://github.com/facebook/docusaurus/pull/6064) refactor(core): fix types for client code ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus` + - [#6055](https://github.com/facebook/docusaurus/pull/6055) chore: clean up dev dependency declarations ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic` + - [#6010](https://github.com/facebook/docusaurus/pull/6010) chore: upgrade prettier; rename prettier scripts as format ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus`, `docusaurus` + - [#5958](https://github.com/facebook/docusaurus/pull/5958) chore: update @svgr/webpack to version 6 ([@ludofischer](https://github.com/ludofischer)) +- `docusaurus` + - [#5998](https://github.com/facebook/docusaurus/pull/5998) chore: upgrade webpack-dev-server to v4.5.0 ([@lex111](https://github.com/lex111)) + - [#5965](https://github.com/facebook/docusaurus/pull/5965) fix(core): apply staticDirectories to base webpack config ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus` + - [#5985](https://github.com/facebook/docusaurus/pull/5985) chore: cleanup dependency declaration in package.json ([@armano2](https://github.com/armano2)) +- `create-docusaurus`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` + - [#5963](https://github.com/facebook/docusaurus/pull/5963) chore: upgrade TypeScript & other ESLint related deps ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs` + - [#5962](https://github.com/facebook/docusaurus/pull/5962) refactor(content-docs): move isCategoriesShorthand to utils ([@armano2](https://github.com/armano2)) + - [#5906](https://github.com/facebook/docusaurus/pull/5906) fix(content-docs): do not echo git history to console ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5905](https://github.com/facebook/docusaurus/pull/5905) misc(plugin-docs): fix Windows test snapshot for git history retrieval ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5904](https://github.com/facebook/docusaurus/pull/5904) refactor(content-docs): use shelljs instead of execa ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-ideal-image` + - [#5940](https://github.com/facebook/docusaurus/pull/5940) refactor(plugin-ideal-image): migrate package to TS ([@armano2](https://github.com/armano2)) +- `docusaurus-plugin-pwa`, `docusaurus-theme-classic` + - [#5941](https://github.com/facebook/docusaurus/pull/5941) refactor(plugin-pwa): migrate package to TS ([@armano2](https://github.com/armano2)) +- `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia` + - [#5935](https://github.com/facebook/docusaurus/pull/5935) refactor(theme-search-algolia): migrate package to TS ([@armano2](https://github.com/armano2)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages` + - [#5946](https://github.com/facebook/docusaurus/pull/5946) refactor: move deps declarations into src ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus` + - [#5914](https://github.com/facebook/docusaurus/pull/5914) refactor: improve setup of type declaration files ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5922](https://github.com/facebook/docusaurus/pull/5922) refactor(theme-classic): move some logic of CodeBlock to theme-common ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-remark-plugin-npm2yarn` + - [#5931](https://github.com/facebook/docusaurus/pull/5931) refactor(remark-plugin-npm2yarn): migrate package to TS ([@duanwilliam](https://github.com/duanwilliam)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils` + - [#5806](https://github.com/facebook/docusaurus/pull/5806) refactor: use js-yaml to parse both JSON and YAML ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### Committers: 48 + +- Afshin Mehrabani ([@afshinm](https://github.com/afshinm)) +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Armano ([@armano2](https://github.com/armano2)) +- Brennan Kinney ([@polarathene](https://github.com/polarathene)) +- Can Olcer ([@shafy](https://github.com/shafy)) +- Christophe Chaudier ([@cchaudier](https://github.com/cchaudier)) +- Devtato ([@cerkiewny](https://github.com/cerkiewny)) +- Dmitriy Fishman ([@fishmandev](https://github.com/fishmandev)) +- Don ([@dsmmcken](https://github.com/dsmmcken)) +- FISH UP ([@MisterFISHUP](https://github.com/MisterFISHUP)) +- Fernando Maia ([@fsmaia](https://github.com/fsmaia)) +- Hemant Sachdeva ([@HemantSachdeva](https://github.com/HemantSachdeva)) +- Hendrik Bulens ([@hbulens](https://github.com/hbulens)) +- Ivan Boothe ([@rootwork](https://github.com/rootwork)) +- Jarar ([@JararvisQ](https://github.com/JararvisQ)) +- Jeff Shillitto ([@jeffski](https://github.com/jeffski)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Konstantin Popov ([@KonstHardy](https://github.com/KonstHardy)) +- Ludovico Fischer ([@ludofischer](https://github.com/ludofischer)) +- Martin Šošić ([@Martinsos](https://github.com/Martinsos)) +- Matej Jellus ([@juffalow](https://github.com/juffalow)) +- Matthijs Groen ([@matthijsgroen](https://github.com/matthijsgroen)) +- Molly White ([@molly](https://github.com/molly)) +- Morooka Kotaro ([@MorookaKotaro](https://github.com/MorookaKotaro)) +- Oliver Ullman ([@oriooctopus](https://github.com/oriooctopus)) +- Paden Clayton ([@spyke01](https://github.com/spyke01)) +- Patitotective ([@Patitotective](https://github.com/Patitotective)) +- Patrik Mäsiar ([@patrikmasiar](https://github.com/patrikmasiar)) +- Paul Biggar ([@pbiggar](https://github.com/pbiggar)) +- Rey ([@rsapkf](https://github.com/rsapkf)) +- Robin Métral ([@robinmetral](https://github.com/robinmetral)) +- Rohit Agrawal ([@agrawal-rohit](https://github.com/agrawal-rohit)) +- Ronny Roeller ([@ronnyroeller](https://github.com/ronnyroeller)) +- Sergio Moreno ([@semoal](https://github.com/semoal)) +- Sharon Koech ([@skoech](https://github.com/skoech)) +- Shoaib Sajid ([@dexbiobot](https://github.com/dexbiobot)) +- Soham Shah ([@sohamsshah](https://github.com/sohamsshah)) +- Stan Kocken ([@StanKocken](https://github.com/StanKocken)) +- Swalah Amani ([@swalahamani](https://github.com/swalahamani)) +- Swapnil M Mane ([@swapnilmmane](https://github.com/swapnilmmane)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Varun Sivapalan ([@sivapalan](https://github.com/sivapalan)) +- William Poetra Yoga ([@wpyoga](https://github.com/wpyoga)) +- Yongmin Hong ([@revi](https://github.com/revi)) +- [@duanwilliam](https://github.com/duanwilliam) +- [@pal-sig](https://github.com/pal-sig) +- chima ilo ([@chimailo](https://github.com/chimailo)) +- 琚致远 ([@juzhiyuan](https://github.com/juzhiyuan)) + +## 2.0.0-beta.9 (2021-11-02) + +#### :rocket: New Feature + +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5770](https://github.com/facebook/docusaurus/pull/5770) feat(theme-classic): allow specifying width/height in logo ([@cerkiewny](https://github.com/cerkiewny)) +- `docusaurus-types`, `docusaurus` + - [#5841](https://github.com/facebook/docusaurus/pull/5841) feat: allow user to specify deploymentBranch property in docusaurus.config.js ([@wpyoga](https://github.com/wpyoga)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia` + - [#5795](https://github.com/facebook/docusaurus/pull/5795) feat(search-algolia): algolia externalUrl regex to navigate with window.href ([@semoal](https://github.com/semoal)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-types`, `docusaurus` + - [#5814](https://github.com/facebook/docusaurus/pull/5814) feat: Support Node 17 ([@slorber](https://github.com/slorber)) + - [#5420](https://github.com/facebook/docusaurus/pull/5420) feat(core): upgrade to webpack-dev-server@4 ([@AviVahl](https://github.com/AviVahl)) +- `docusaurus-theme-classic` + - [#5791](https://github.com/facebook/docusaurus/pull/5791) feat(theme-classic): add Serbian Cyrillic translation ([@utajum](https://github.com/utajum)) + +#### :boom: Breaking Change + +- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#5812](https://github.com/facebook/docusaurus/pull/5812) chore: require Node 14 ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-plugin-content-blog` + - [#5835](https://github.com/facebook/docusaurus/pull/5835) fix(content-blog): Fix blog feeds not generated ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#5828](https://github.com/facebook/docusaurus/pull/5828) fix: include all branch tips for shallow clone in deploy command ([@sivapalan](https://github.com/sivapalan)) + - [#5824](https://github.com/facebook/docusaurus/pull/5824) fix: baseUrl passed to sortConfig ([@semoal](https://github.com/semoal)) + - [#5813](https://github.com/facebook/docusaurus/pull/5813) fix: handle SIGTERM in build command ([@slorber](https://github.com/slorber)) +- `docusaurus-module-type-aliases`, `docusaurus` + - [#5819](https://github.com/facebook/docusaurus/pull/5819) fix: use @docusaurus/react-loadable as package alias + include types ([@slorber](https://github.com/slorber)) + +#### :nail_care: Polish + +- `docusaurus-preset-classic` + - [#5831](https://github.com/facebook/docusaurus/pull/5831) feat(preset-classic): guard against unknown keys in options ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#5815](https://github.com/facebook/docusaurus/pull/5815) refactor: some improvements for webpack-dev-server ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` + - [#5788](https://github.com/facebook/docusaurus/pull/5788) refactor: fix a few type inconsistencies ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#5781](https://github.com/facebook/docusaurus/pull/5781) refactor: Vietnamese translations ([@datlechin](https://github.com/datlechin)) + +#### :memo: Documentation + +- Other + - [#5853](https://github.com/facebook/docusaurus/pull/5853) docs: Fix a typo in CONTRIBUTING.md ([@fishmandev](https://github.com/fishmandev)) + - [#5852](https://github.com/facebook/docusaurus/pull/5852) docs: Fix a typo in versioning.md ([@fishmandev](https://github.com/fishmandev)) + - [#5847](https://github.com/facebook/docusaurus/pull/5847) docs: add InfraQL product docs website to showcase ([@jeffreyaven](https://github.com/jeffreyaven)) + - [#5843](https://github.com/facebook/docusaurus/pull/5843) docs: fix i18n routes to feature requests ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5766](https://github.com/facebook/docusaurus/pull/5766) docs: elaborate on the usage of MDX plugins ([@cerkiewny](https://github.com/cerkiewny)) + - [#5826](https://github.com/facebook/docusaurus/pull/5826) docs: fix lint issue ([@slorber](https://github.com/slorber)) + - [#5801](https://github.com/facebook/docusaurus/pull/5801) docs: Update Drone Deployment docs ([@gabrielfalcao](https://github.com/gabrielfalcao)) + - [#5821](https://github.com/facebook/docusaurus/pull/5821) docs: include navbar item type in the API table ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5820](https://github.com/facebook/docusaurus/pull/5820) docs: add @Josh-Cena to the team ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5818](https://github.com/facebook/docusaurus/pull/5818) doc: fix typo in "create a doc" ([@dominikmeyersap](https://github.com/dominikmeyersap)) + - [#5797](https://github.com/facebook/docusaurus/pull/5797) docs: use "npx create-docusaurus" for init ([@slorber](https://github.com/slorber)) + - [#5771](https://github.com/facebook/docusaurus/pull/5771) docs: Minor update to grammar in plugins overview page ([@robbieaverill](https://github.com/robbieaverill)) + - [#5774](https://github.com/facebook/docusaurus/pull/5774) docs: update ssrTemplate ([@juzhiyuan](https://github.com/juzhiyuan)) + - [#5784](https://github.com/facebook/docusaurus/pull/5784) docs: fix link for apply to DocSearch program ([@lex111](https://github.com/lex111)) +- `create-docusaurus` + - [#5792](https://github.com/facebook/docusaurus/pull/5792) docs: fix typo ([@wingclover](https://github.com/wingclover)) + +#### :house: Internal + +- Other + - [#5842](https://github.com/facebook/docusaurus/pull/5842) misc: add "name" field for root package.json ([@wpyoga](https://github.com/wpyoga)) + - [#5836](https://github.com/facebook/docusaurus/pull/5836) chore: switch to GitHub issue forms ([@lex111](https://github.com/lex111)) + - [#5834](https://github.com/facebook/docusaurus/pull/5834) chore(issue templ): add "self service" section in templates ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5833](https://github.com/facebook/docusaurus/pull/5833) chore(workflow): remove v2 prefix from titles ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5697](https://github.com/facebook/docusaurus/pull/5697) chore(workflow): add cache to workflows using actions/setup-node ([@oscard0m](https://github.com/oscard0m)) + - [#5825](https://github.com/facebook/docusaurus/pull/5825) chore: fix Crowdin again ([@slorber](https://github.com/slorber)) + - [#5823](https://github.com/facebook/docusaurus/pull/5823) chore: replace doc sample .pdf file by .xlsx to solve Crowdin issue ([@slorber](https://github.com/slorber)) + - [#5763](https://github.com/facebook/docusaurus/pull/5763) chore: update examples for beta.8 ([@slorber](https://github.com/slorber)) +- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#5812](https://github.com/facebook/docusaurus/pull/5812) chore: require Node 14 ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus` + - [#5807](https://github.com/facebook/docusaurus/pull/5807) refactor: remove a few Lodash usages & ESLint enforcement ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` + - [#5808](https://github.com/facebook/docusaurus/pull/5808) refactor: clear a few ESLint warnings ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `lqip-loader` + - [#5779](https://github.com/facebook/docusaurus/pull/5779) refactor: migrate lqip-loader to TS, fix typing for Webpack Loaders ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### Committers: 18 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Avi Vahl ([@AviVahl](https://github.com/AviVahl)) +- Devtato ([@cerkiewny](https://github.com/cerkiewny)) +- Dmitriy Fishman ([@fishmandev](https://github.com/fishmandev)) +- Dominik Meyer ([@dominikmeyersap](https://github.com/dominikmeyersap)) +- Gabriel Falcão ([@gabrielfalcao](https://github.com/gabrielfalcao)) +- Jeffrey Aven ([@jeffreyaven](https://github.com/jeffreyaven)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Ngô Quốc Đạt ([@datlechin](https://github.com/datlechin)) +- Oscar Dominguez ([@oscard0m](https://github.com/oscard0m)) +- Robbie Averill ([@robbieaverill](https://github.com/robbieaverill)) +- Sergio Moreno ([@semoal](https://github.com/semoal)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Varun Sivapalan ([@sivapalan](https://github.com/sivapalan)) +- Vladimir Tasic ([@utajum](https://github.com/utajum)) +- William Poetra Yoga ([@wpyoga](https://github.com/wpyoga)) +- Ying Wang ([@wingclover](https://github.com/wingclover)) +- 琚致远 ([@juzhiyuan](https://github.com/juzhiyuan)) + +## 2.0.0-beta.8 (2021-10-21) + +#### :rocket: New Feature + +- `docusaurus-plugin-content-blog` + - [#5702](https://github.com/facebook/docusaurus/pull/5702) feat(content-blog): new readingTime plugin option ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#5740](https://github.com/facebook/docusaurus/pull/5740) feat(core): write-heading-ids options maintainCasing, overwrite ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs` + - [#5705](https://github.com/facebook/docusaurus/pull/5705) feat(content-docs): new front matter options to customize pagination ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :boom: Breaking Change + +- `docusaurus-theme-search-algolia` + - [#5751](https://github.com/facebook/docusaurus/pull/5751) fix: stable callbacks in useSearchQuery + refactor ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-plugin-ideal-image` + - [#5760](https://github.com/facebook/docusaurus/pull/5760) fix(ideal-image): fix IdealImage in dev not handling ES import images properly ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#5732](https://github.com/facebook/docusaurus/pull/5732) fix(theme-classic): allow tabs with number as value ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5721](https://github.com/facebook/docusaurus/pull/5721) fix: handle rubber band scrolling in hideable navbar ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-search-algolia` + - [#5751](https://github.com/facebook/docusaurus/pull/5751) fix: stable callbacks in useSearchQuery + refactor ([@slorber](https://github.com/slorber)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#5717](https://github.com/facebook/docusaurus/pull/5717) refactor: Polish de translation ([@philipp985](https://github.com/philipp985)) + - [#5725](https://github.com/facebook/docusaurus/pull/5725) refactor: add missing Turkish translations to theme-classic ([@canercanbaz](https://github.com/canercanbaz)) + - [#5723](https://github.com/facebook/docusaurus/pull/5723) refactor(v2): update Vietnamese translations ([@datlechin](https://github.com/datlechin)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic`, `docusaurus` + - [#5726](https://github.com/facebook/docusaurus/pull/5726) refactor(module-type-aliases): remove fallback aliases ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :memo: Documentation + +- Other + - [#5755](https://github.com/facebook/docusaurus/pull/5755) docs: rename docusaurus.config.js route + redirects cleanup ([@slorber](https://github.com/slorber)) + - [#5750](https://github.com/facebook/docusaurus/pull/5750) docs(v2): Fix typo in using-plugins.md ([@thanasis00](https://github.com/thanasis00)) + - [#5727](https://github.com/facebook/docusaurus/pull/5727) docs(v2): Add Fenghua Frontend Developer site to showcase page ([@zxuqian](https://github.com/zxuqian)) + - [#5746](https://github.com/facebook/docusaurus/pull/5746) docs: Add plugin-image-zoom ([@ataft](https://github.com/ataft)) + - [#5728](https://github.com/facebook/docusaurus/pull/5728) docs: add h4 into toc on certain pages ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5737](https://github.com/facebook/docusaurus/pull/5737) docs: Add Apex FP to showcase ([@ipavlic](https://github.com/ipavlic)) +- `docusaurus-plugin-content-blog` + - [#5753](https://github.com/facebook/docusaurus/pull/5753) fix(content-blog): temporarily swallow feed mdxToHtml errors + feed refactor ([@slorber](https://github.com/slorber)) + +#### :house: Internal + +- `docusaurus` + - [#5761](https://github.com/facebook/docusaurus/pull/5761) chore: upgrade html-webpack-plugin, remove terser 4 ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#5714](https://github.com/facebook/docusaurus/pull/5714) chore: Enable ESLint rules of hooks + fix new lint errors ([@slorber](https://github.com/slorber)) +- Other + - [#5722](https://github.com/facebook/docusaurus/pull/5722) chore: fix gen script to support TS template ([@lex111](https://github.com/lex111)) + - [#5730](https://github.com/facebook/docusaurus/pull/5730) chore: fix typos / casing in issue template ([@johnnyreilly](https://github.com/johnnyreilly)) + - [#5720](https://github.com/facebook/docusaurus/pull/5720) chore: regenerate beta.7 examples ([@lex111](https://github.com/lex111)) + - [#5719](https://github.com/facebook/docusaurus/pull/5719) chore: remove beta.5 docs ([@lex111](https://github.com/lex111)) + +#### :running_woman: Performance + +- `docusaurus` + - [#5748](https://github.com/facebook/docusaurus/pull/5748) refactor: perform shallow clone during deploy ([@nlfurniss](https://github.com/nlfurniss)) + +#### Committers: 13 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Andrew Taft ([@ataft](https://github.com/ataft)) +- Caner Canbaz ([@canercanbaz](https://github.com/canercanbaz)) +- Dimi Mikadze ([@DimiMikadze](https://github.com/DimiMikadze)) +- Ilija Pavlic ([@ipavlic](https://github.com/ipavlic)) +- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Nathaniel Furniss ([@nlfurniss](https://github.com/nlfurniss)) +- Ngô Quốc Đạt ([@datlechin](https://github.com/datlechin)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Thanasis Katsadas ([@thanasis00](https://github.com/thanasis00)) +- Xuqian ([@zxuqian](https://github.com/zxuqian)) +- [@philipp985](https://github.com/philipp985) + +## 2.0.0-beta.7 (2021-10-15) + +#### :rocket: New Feature + +- `docusaurus-module-type-aliases`, `docusaurus` + - [#5683](https://github.com/facebook/docusaurus/pull/5683) feat: make Translate children optional ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5674](https://github.com/facebook/docusaurus/pull/5674) polish(theme-classic): guard against potential definition mistakes in Tabs ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5618](https://github.com/facebook/docusaurus/pull/5618) feat: maintain page position for clicked grouped tabs ([@Shrugsy](https://github.com/Shrugsy)) +- `docusaurus-plugin-content-blog`, `docusaurus-utils` + - [#4330](https://github.com/facebook/docusaurus/pull/4330) feat(content-blog): add full blog post html into RSS/Atom feeds ([@moonrailgun](https://github.com/moonrailgun)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5642](https://github.com/facebook/docusaurus/pull/5642) feat(theme-classic, plugin-docs): sidebar item level-specific className + allow customization ([@Josh-Cena](https://github.com/Josh-Cena)) +- `create-docusaurus` + - [#5635](https://github.com/facebook/docusaurus/pull/5635) feat: npm init docusaurus, yarn create docusaurus ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types` + - [#5589](https://github.com/facebook/docusaurus/pull/5589) feat: properly type-check the Docusaurus config of new sites ([@bmiddha](https://github.com/bmiddha)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-validation` + - [#5578](https://github.com/facebook/docusaurus/pull/5578) feat(v2): allow specifying TOC max depth (themeConfig + frontMatter) ([@erickzhao](https://github.com/erickzhao)) +- `docusaurus` + - [#5498](https://github.com/facebook/docusaurus/pull/5498) feat: make Webpack url-loader limit configurable (env variable) ([@stnor](https://github.com/stnor)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` + - [#5545](https://github.com/facebook/docusaurus/pull/5545) feat: make tags route path configurable ([@lex111](https://github.com/lex111)) + +#### :boom: Breaking Change + +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5674](https://github.com/facebook/docusaurus/pull/5674) polish(theme-classic): guard against potential definition mistakes in Tabs ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5618](https://github.com/facebook/docusaurus/pull/5618) feat: maintain page position for clicked grouped tabs ([@Shrugsy](https://github.com/Shrugsy)) +- `docusaurus-init`, `docusaurus-preset-bootstrap`, `docusaurus-theme-bootstrap` + - [#5634](https://github.com/facebook/docusaurus/pull/5634) chore: remove unused Bootstrap theme ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-validation` + - [#5578](https://github.com/facebook/docusaurus/pull/5578) feat(v2): allow specifying TOC max depth (themeConfig + frontMatter) ([@erickzhao](https://github.com/erickzhao)) +- `docusaurus-theme-classic` + - [#5592](https://github.com/facebook/docusaurus/pull/5592) refactor: use CSS Modules for toggle styles ([@lex111](https://github.com/lex111)) + +#### :bug: Bug Fix + +- `docusaurus-theme-common` + - [#5694](https://github.com/facebook/docusaurus/pull/5694) fix: proper collapsing of long element ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#5684](https://github.com/facebook/docusaurus/pull/5684) fix: use realpath for site dir to resolve symlink ([@lex111](https://github.com/lex111)) + - [#5645](https://github.com/facebook/docusaurus/pull/5645) fix: place root route at the end ([@lex111](https://github.com/lex111)) + - [#5629](https://github.com/facebook/docusaurus/pull/5629) fix: text/link hydration bug ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5699](https://github.com/facebook/docusaurus/pull/5699) fix: apply announcement bar class if only needed ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#5667](https://github.com/facebook/docusaurus/pull/5667) fix: expand tag column on truncated post ([@lex111](https://github.com/lex111)) + - [#5668](https://github.com/facebook/docusaurus/pull/5668) fix: preserve line breaks when copy code in Firefox ([@lex111](https://github.com/lex111)) + - [#5647](https://github.com/facebook/docusaurus/pull/5647) feat(theme-classic): make first tab the default tab ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5652](https://github.com/facebook/docusaurus/pull/5652) fix: restore duplicate Tabs rendering to fix hydration issue ([@slorber](https://github.com/slorber)) + - [#5643](https://github.com/facebook/docusaurus/pull/5643) fix(theme-classic): reset default style for task lists ([@EkaterinaMozheiko](https://github.com/EkaterinaMozheiko)) + - [#5571](https://github.com/facebook/docusaurus/pull/5571) fix: highlight active item in recent post list ([@lex111](https://github.com/lex111)) + - [#5481](https://github.com/facebook/docusaurus/pull/5481) fix: use heading itself as anchor for better crawling ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-live-codeblock` + - [#5677](https://github.com/facebook/docusaurus/pull/5677) fix: Don't ignore options.transforms for buble ([@ntucker](https://github.com/ntucker)) + - [#5556](https://github.com/facebook/docusaurus/pull/5556) fix: pin react-live due to possible mismatch React ([@lex111](https://github.com/lex111)) +- `docusaurus-mdx-loader` + - [#5690](https://github.com/facebook/docusaurus/pull/5690) fix: preserve hash in asset link ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-ideal-image` + - [#5540](https://github.com/facebook/docusaurus/pull/5540) fix: do not use ideal image plugin in dev env ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs` + - [#5606](https://github.com/facebook/docusaurus/pull/5606) fix(docs): create tags route if only tags exists ([@lex111](https://github.com/lex111)) +- `docusaurus-init`, `docusaurus-module-type-aliases`, `docusaurus-types` + - [#5601](https://github.com/facebook/docusaurus/pull/5601) fix(module-type-aliases): move @type packages to dependencies ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-utils` + - [#5495](https://github.com/facebook/docusaurus/pull/5495) fix: ignore code block lines when creating excerpt ([@lex111](https://github.com/lex111)) +- `docusaurus-init` + - [#5490](https://github.com/facebook/docusaurus/pull/5490) fix: install deps for new project via Yarn on Windows properly ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils-validation` + - [#5479](https://github.com/facebook/docusaurus/pull/5479) fix: add docs tag validation to solve #5478 ([@sw-yx](https://github.com/sw-yx)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5709](https://github.com/facebook/docusaurus/pull/5709) refactor: cleanup scroll handlers ([@lex111](https://github.com/lex111)) + - [#5627](https://github.com/facebook/docusaurus/pull/5627) refactor: various TOC improvements ([@lex111](https://github.com/lex111)) + - [#5469](https://github.com/facebook/docusaurus/pull/5469) refactor: Adjust styling of back top top button ([@dsmmcken](https://github.com/dsmmcken)) +- `docusaurus-theme-classic` + - [#5708](https://github.com/facebook/docusaurus/pull/5708) refactor: hide hash link from crawlers ([@lex111](https://github.com/lex111)) + - [#5649](https://github.com/facebook/docusaurus/pull/5649) refactor: improve pt-BR translation for classic theme ([@printf-ana](https://github.com/printf-ana)) + - [#5646](https://github.com/facebook/docusaurus/pull/5646) refactor: complete missing and fix ES translations ([@caleeli](https://github.com/caleeli)) + - [#5640](https://github.com/facebook/docusaurus/pull/5640) style: update Persian language translations ([@MrTechHunter](https://github.com/MrTechHunter)) + - [#5630](https://github.com/facebook/docusaurus/pull/5630) refactor: standardize using media queries ([@lex111](https://github.com/lex111)) + - [#5487](https://github.com/facebook/docusaurus/pull/5487) refactor: use only one close SVG icon ([@lex111](https://github.com/lex111)) + - [#5592](https://github.com/facebook/docusaurus/pull/5592) refactor: use CSS Modules for toggle styles ([@lex111](https://github.com/lex111)) + - [#5485](https://github.com/facebook/docusaurus/pull/5485) polish: prevent pop navigation on back if navbar sidebar is open ([@slorber](https://github.com/slorber)) + - [#5472](https://github.com/facebook/docusaurus/pull/5472) polish(theme-classic): add Chinese translations ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#5636](https://github.com/facebook/docusaurus/pull/5636) refactor: make all Props defined as interface + readonly ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus` + - [#5560](https://github.com/facebook/docusaurus/pull/5560) polish: remove unused eslint-disable ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#5580](https://github.com/facebook/docusaurus/pull/5580) refactor(core): type improvements for `PendingNavigation` ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus` + - [#5496](https://github.com/facebook/docusaurus/pull/5496) refactor: remove deprecated createRequireFromPath ([@lex111](https://github.com/lex111)) + +#### :memo: Documentation + +- [#5681](https://github.com/facebook/docusaurus/pull/5681) docs(v2): Add CountryStateCityAPI site to showcase page ([@dr5hn](https://github.com/dr5hn)) +- [#5661](https://github.com/facebook/docusaurus/pull/5661) docs: updated cloudywithachanceofbigdata.com blog showcase ([@jeffreyaven](https://github.com/jeffreyaven)) +- [#5658](https://github.com/facebook/docusaurus/pull/5658) docs: Algolia plugin must be enabled before crawling the site ([@slorber](https://github.com/slorber)) +- [#5654](https://github.com/facebook/docusaurus/pull/5654) docs: Add Warrant Docs site to showcase page ([@akajla09](https://github.com/akajla09)) +- [#5655](https://github.com/facebook/docusaurus/pull/5655) docs: Added cloudywithachanceofbigdata.com showcase blog ([@jeffreyaven](https://github.com/jeffreyaven)) +- [#5648](https://github.com/facebook/docusaurus/pull/5648) docs: add ory documentation to showcase ([@vinckr](https://github.com/vinckr)) +- [#5644](https://github.com/facebook/docusaurus/pull/5644) docs: add djamaile blog to site showcase ([@djamaile](https://github.com/djamaile)) +- [#5641](https://github.com/facebook/docusaurus/pull/5641) docs: add Lux Algo to showcase ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#5638](https://github.com/facebook/docusaurus/pull/5638) docs: add nanos world docs to showcase ([@gtnardy](https://github.com/gtnardy)) +- [#5610](https://github.com/facebook/docusaurus/pull/5610) docs: Add IOTA wiki to showcase ([@Dr-Electron](https://github.com/Dr-Electron)) +- [#5489](https://github.com/facebook/docusaurus/pull/5489) docs: add additional search options, typesense and local search ([@jasonbosco](https://github.com/jasonbosco)) +- [#5590](https://github.com/facebook/docusaurus/pull/5590) docs(website): document npm2yarn plugin + use new Tabs API everywhere ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#5591](https://github.com/facebook/docusaurus/pull/5591) docs: Add whirl.codes to showcase ([@Whirl21](https://github.com/Whirl21)) +- [#5574](https://github.com/facebook/docusaurus/pull/5574) docs: add Pipeline UI to showcase ([@headline-design](https://github.com/headline-design)) +- [#5585](https://github.com/facebook/docusaurus/pull/5585) docs: fix more references to Discord channels ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#5572](https://github.com/facebook/docusaurus/pull/5572) docs: add Blogasaurus to showcase ([@BattleOfPlassey](https://github.com/BattleOfPlassey)) +- [#5575](https://github.com/facebook/docusaurus/pull/5575) docs: clarify MDX version used ([@lex111](https://github.com/lex111)) +- [#5581](https://github.com/facebook/docusaurus/pull/5581) docs(website): update all Discord links ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#5566](https://github.com/facebook/docusaurus/pull/5566) docs: fix code example ([@ChrisChinchilla](https://github.com/ChrisChinchilla)) +- [#5559](https://github.com/facebook/docusaurus/pull/5559) docs: minor grammatical correction ([@jkhaui](https://github.com/jkhaui)) +- [#5543](https://github.com/facebook/docusaurus/pull/5543) docs: add note about files being ignored when prefixed with an unders… ([@KyrietS](https://github.com/KyrietS)) +- [#5549](https://github.com/facebook/docusaurus/pull/5549) docs: Add Mint Metrics site to the Showcase ([@kingo55](https://github.com/kingo55)) +- [#5546](https://github.com/facebook/docusaurus/pull/5546) docs: add unleash to showcase ([@ivarconr](https://github.com/ivarconr)) +- [#5539](https://github.com/facebook/docusaurus/pull/5539) docs: improve escape pipe in Markdown tables ([@forresst](https://github.com/forresst)) +- [#5486](https://github.com/facebook/docusaurus/pull/5486) docs: mention Netlify ignore build setting ([@slorber](https://github.com/slorber)) +- [#5482](https://github.com/facebook/docusaurus/pull/5482) docs: update docusaurus-plugin-relative-paths description ([@ohkimur](https://github.com/ohkimur)) + +#### :house: Internal + +- `create-docusaurus`, `docusaurus-plugin-content-docs` + - [#5678](https://github.com/facebook/docusaurus/pull/5678) refactor(content-docs): refactor sidebars, Joi validation, generator rework, expose config types ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#5666](https://github.com/facebook/docusaurus/pull/5666) chore: upgrade Infima to alpha.34 ([@lex111](https://github.com/lex111)) + - [#5639](https://github.com/facebook/docusaurus/pull/5639) misc: update base translation + remove extra char ([@lex111](https://github.com/lex111)) +- Other + - [#5669](https://github.com/facebook/docusaurus/pull/5669) fix: allow ColorGenerator to parse colors with prefix `#` ([@Andrewnt219](https://github.com/Andrewnt219)) + - [#5632](https://github.com/facebook/docusaurus/pull/5632) chore: prepare Algolia migration ([@slorber](https://github.com/slorber)) + - [#5628](https://github.com/facebook/docusaurus/pull/5628) chore: fix warning after build ([@lex111](https://github.com/lex111)) + - [#5573](https://github.com/facebook/docusaurus/pull/5573) misc: fix ungrammatical sentence about 5-min tutorial ([@hughlilly](https://github.com/hughlilly)) + - [#5499](https://github.com/facebook/docusaurus/pull/5499) chore: set up CodeQL ([@zpao](https://github.com/zpao)) + - [#5474](https://github.com/facebook/docusaurus/pull/5474) chore: remove beta.4 docs (already archived) ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-preset-bootstrap`, `docusaurus-theme-bootstrap` + - [#5634](https://github.com/facebook/docusaurus/pull/5634) chore: remove unused Bootstrap theme ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#5611](https://github.com/facebook/docusaurus/pull/5611) chore: upgrade Prettier + regenerate lock file ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-pwa`, `docusaurus` + - [#5609](https://github.com/facebook/docusaurus/pull/5609) chore: upgrade Terser-related dependencies ([@lex111](https://github.com/lex111)) +- `docusaurus-cssnano-preset`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#5608](https://github.com/facebook/docusaurus/pull/5608) chore: upgrade dependencies ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#5605](https://github.com/facebook/docusaurus/pull/5605) refactor(core): enforce noImplicitAny ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-preset-classic` + - [#5603](https://github.com/facebook/docusaurus/pull/5603) fix(preset-classic): fix TS build issue ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-preset-classic` + - [#5561](https://github.com/facebook/docusaurus/pull/5561) refactor(plugin-google-gtag, plugin-google-analytics): migrate packages to TS ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic` + - [#5579](https://github.com/facebook/docusaurus/pull/5579) refactor(preset-classic): migrate preset-classic to TypeScript ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-init` + - [#5484](https://github.com/facebook/docusaurus/pull/5484) chore: regenerate beta.6 examples + fix regen script ([@slorber](https://github.com/slorber)) + +#### Committers: 36 + +- Aditya Kajla ([@akajla09](https://github.com/akajla09)) +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Ana Carolina ([@printf-ana](https://github.com/printf-ana)) +- Andrew Nguyen ([@Andrewnt219](https://github.com/Andrewnt219)) +- Bharat Middha ([@bmiddha](https://github.com/bmiddha)) +- Chris Chinchilla ([@ChrisChinchilla](https://github.com/ChrisChinchilla)) +- Daniel Costrasel ([@ohkimur](https://github.com/ohkimur)) +- Darshan Gada ([@dr5hn](https://github.com/dr5hn)) +- David Callizaya ([@caleeli](https://github.com/caleeli)) +- Don ([@dsmmcken](https://github.com/dsmmcken)) +- Ekaterina Mozheiko ([@EkaterinaMozheiko](https://github.com/EkaterinaMozheiko)) +- Erick Zhao ([@erickzhao](https://github.com/erickzhao)) +- Forresst ([@forresst](https://github.com/forresst)) +- Gabriel T. Nardy ([@gtnardy](https://github.com/gtnardy)) +- Hugh Lilly ([@hughlilly](https://github.com/hughlilly)) +- Ivar Conradi Østhus ([@ivarconr](https://github.com/ivarconr)) +- Jason Bosco ([@jasonbosco](https://github.com/jasonbosco)) +- Jeffrey Aven ([@jeffreyaven](https://github.com/jeffreyaven)) +- Jordan Lee ([@jkhaui](https://github.com/jkhaui)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Kyriet ([@KyrietS](https://github.com/KyrietS)) +- Mahdi Hamldar ([@MrTechHunter](https://github.com/MrTechHunter)) +- Nathaniel Tucker ([@ntucker](https://github.com/ntucker)) +- Palash Shrivastava ([@BattleOfPlassey](https://github.com/BattleOfPlassey)) +- Paul O’Shannessy ([@zpao](https://github.com/zpao)) +- Robert Kingston ([@kingo55](https://github.com/kingo55)) +- Stefan Norberg ([@stnor](https://github.com/stnor)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Vincent ([@vinckr](https://github.com/vinckr)) +- Whirl ([@Whirl21](https://github.com/Whirl21)) +- [@Dr-Electron](https://github.com/Dr-Electron) +- [@Shrugsy](https://github.com/Shrugsy) +- [@djamaile](https://github.com/djamaile) +- [@headline-design](https://github.com/headline-design) +- moonrailgun ([@moonrailgun](https://github.com/moonrailgun)) +- swyx ([@sw-yx](https://github.com/sw-yx)) + +## 2.0.0-beta.6 (2021-09-02) + +#### :rocket: New Feature + +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#5428](https://github.com/facebook/docusaurus/pull/5428) feat: adds blog archive route ([@gabrielcsapo](https://github.com/gabrielcsapo)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5462](https://github.com/facebook/docusaurus/pull/5462) feat: on back navigation, close mobile sidebar ([@slorber](https://github.com/slorber)) + - [#5445](https://github.com/facebook/docusaurus/pull/5445) feat: Add docs-related stable classnames ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#5460](https://github.com/facebook/docusaurus/pull/5460) feat: infima 33 + navbar-sidebar close button ([@slorber](https://github.com/slorber)) + - [#5442](https://github.com/facebook/docusaurus/pull/5442) feat(theme-classic): allow passing tab label and default value through TabItem ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#5454](https://github.com/facebook/docusaurus/pull/5454) feat: new docs options: versions.{badge,className} ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#5444](https://github.com/facebook/docusaurus/pull/5444) fix: fix some theme UI issues (blockquotes, navbar-sidebar font) with Infima alpha.32 ([@slorber](https://github.com/slorber)) + - [#5431](https://github.com/facebook/docusaurus/pull/5431) fix: some beta.5 bugfixes ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#5437](https://github.com/facebook/docusaurus/pull/5437) fix: fix a few TS errors ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :nail_care: Polish + +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#5459](https://github.com/facebook/docusaurus/pull/5459) refactor(theme-classic): completely migrate package to TypeScript ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#5453](https://github.com/facebook/docusaurus/pull/5453) refactor: use SVG for closable button in announcement bar ([@lex111](https://github.com/lex111)) + - [#5430](https://github.com/facebook/docusaurus/pull/5430) refactor: switch to Flexbox in announcement bar ([@lex111](https://github.com/lex111)) + - [#5434](https://github.com/facebook/docusaurus/pull/5434) refactor: update Arabic and Persian translations ([@3alisaki](https://github.com/3alisaki)) + - [#5410](https://github.com/facebook/docusaurus/pull/5410) refactor: add missing translations in fa.json ([@farshidinanloo](https://github.com/farshidinanloo)) + +#### :memo: Documentation + +- [#5471](https://github.com/facebook/docusaurus/pull/5471) docs: Add docusaurus-plugin-relative-paths ([@ohkimur](https://github.com/ohkimur)) +- [#5464](https://github.com/facebook/docusaurus/pull/5464) docs: add mapillary-js to showcase ([@oscarlorentzon](https://github.com/oscarlorentzon)) +- [#5433](https://github.com/facebook/docusaurus/pull/5433) docs: document doc tags + refinements ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#5435](https://github.com/facebook/docusaurus/pull/5435) docs: Add netboot.xyz to site showcase ([@antonym](https://github.com/antonym)) +- [#5436](https://github.com/facebook/docusaurus/pull/5436) docs: add Redocusaurus in community plugin list ([@rohit-gohri](https://github.com/rohit-gohri)) + +#### :house: Internal + +- [#5455](https://github.com/facebook/docusaurus/pull/5455) fix: website bad version name in docusaurus.config.js ([@slorber](https://github.com/slorber)) + +#### Committers: 10 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Ali Saki ([@3alisaki](https://github.com/3alisaki)) +- Antony Messerli ([@antonym](https://github.com/antonym)) +- Daniel Costrasel ([@ohkimur](https://github.com/ohkimur)) +- Gabriel Csapo ([@gabrielcsapo](https://github.com/gabrielcsapo)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Oscar Lorentzon ([@oscarlorentzon](https://github.com/oscarlorentzon)) +- Rohit Gohri ([@rohit-gohri](https://github.com/rohit-gohri)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- farshid ([@farshidinanloo](https://github.com/farshidinanloo)) + +## 2.0.0-beta.5 (2021-08-26) + +#### :rocket: New Feature + +- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-utils-validation` + - [#5396](https://github.com/facebook/docusaurus/pull/5396) feat(plugin-blog): multi-authors support + authors.yml global configuration ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#5371](https://github.com/facebook/docusaurus/pull/5371) feat: make blog config options and navbar versions dropdown label translatable ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5375](https://github.com/facebook/docusaurus/pull/5375) feat: add metatags support for seo / blogposts #5373 ([@johnnyreilly](https://github.com/johnnyreilly)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-validation`, `docusaurus-utils` + - [#3646](https://github.com/facebook/docusaurus/pull/3646) feat: doc tags (same as blog tags) ([@isaac-philip](https://github.com/isaac-philip)) +- `docusaurus-plugin-content-blog` + - [#5354](https://github.com/facebook/docusaurus/pull/5354) feat(plugin-blog): allow `'ALL'` as `postsPerPage` option value ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#5330](https://github.com/facebook/docusaurus/pull/5330) feat: Markdown page-specific head metadatas ([@slorber](https://github.com/slorber)) + - [#5322](https://github.com/facebook/docusaurus/pull/5322) feat: structured data for blog posts ([@johnnyreilly](https://github.com/johnnyreilly)) + - [#5314](https://github.com/facebook/docusaurus/pull/5314) feat(v2): add cs (Czech) translations for docusaurus-theme-classic ([@michalsanger](https://github.com/michalsanger)) +- `docusaurus-init` + - [#5233](https://github.com/facebook/docusaurus/pull/5233) feat: new init template classic-typescript ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#5309](https://github.com/facebook/docusaurus/pull/5309) feat: blog posts support /YYYY/MM/DD/blog-post/index.md pattern + blog frontmatter can reference relative images ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader`, `docusaurus` + - [#5299](https://github.com/facebook/docusaurus/pull/5299) feat: mdx loader fallback, allow importing mdx docs from anywhere ([@slorber](https://github.com/slorber)) + +#### :boom: Breaking Change + +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-validation`, `docusaurus-utils` + - [#3646](https://github.com/facebook/docusaurus/pull/3646) feat: doc tags (same as blog tags) ([@isaac-philip](https://github.com/isaac-philip)) +- `docusaurus-init`, `docusaurus-migrate`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus` + - [#5345](https://github.com/facebook/docusaurus/pull/5345) refactor: rename Git master branch to main ([@zpao](https://github.com/zpao)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-types`, `docusaurus` + - [#5349](https://github.com/facebook/docusaurus/pull/5349) refactor(core): replace useDocusaurusContext().isClient by useIsBrowser() ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#5264](https://github.com/facebook/docusaurus/pull/5264) fix: apply proper class for active doc item on mobiles + avoid duplicated classes ([@lex111](https://github.com/lex111)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#5425](https://github.com/facebook/docusaurus/pull/5425) fix: toc does not highlight clicked anchor + use scroll-margin-top ([@slorber](https://github.com/slorber)) + - [#5424](https://github.com/facebook/docusaurus/pull/5424) refactor: make dynamic authors layout via CSS only ([@lex111](https://github.com/lex111)) + - [#5422](https://github.com/facebook/docusaurus/pull/5422) fix: make tags wrapping properly ([@lex111](https://github.com/lex111)) + - [#5419](https://github.com/facebook/docusaurus/pull/5419) fix: various fixes back-to-top button ([@lex111](https://github.com/lex111)) + - [#5361](https://github.com/facebook/docusaurus/pull/5361) fix: refactor TOC highlighting + handle edge cases ([@slorber](https://github.com/slorber)) + - [#5357](https://github.com/facebook/docusaurus/pull/5357) fix: code blocks should scroll in RTL direction ([@slorber](https://github.com/slorber)) + - [#5346](https://github.com/facebook/docusaurus/pull/5346) fix: author/image adjustments in BlogPosting schema ([@lex111](https://github.com/lex111)) + - [#5240](https://github.com/facebook/docusaurus/pull/5240) fix: remove top margin only from directly first element ([@lex111](https://github.com/lex111)) + - [#5317](https://github.com/facebook/docusaurus/pull/5317) fix: make proper highlighting doc link if no sidebar ([@hamzahamidi](https://github.com/hamzahamidi)) + - [#5316](https://github.com/facebook/docusaurus/pull/5316) fix: avoid extra default active class on doc sidebar item ([@lex111](https://github.com/lex111)) + - [#5319](https://github.com/facebook/docusaurus/pull/5319) fix: unbreak highlighting regular navbar links ([@lex111](https://github.com/lex111)) + - [#5264](https://github.com/facebook/docusaurus/pull/5264) fix: apply proper class for active doc item on mobiles + avoid duplicated classes ([@lex111](https://github.com/lex111)) + - [#5275](https://github.com/facebook/docusaurus/pull/5275) fix: improve spanish translation ([@faloi](https://github.com/faloi)) + - [#5262](https://github.com/facebook/docusaurus/pull/5262) fix: show secondary menu if even there is no main one ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#5426](https://github.com/facebook/docusaurus/pull/5426) fix: Make update-notifier fail-safe if no permission to read configStore ([@slorber](https://github.com/slorber)) + - [#5398](https://github.com/facebook/docusaurus/pull/5398) fix: fix write-translations warning for theme-common translations ([@slorber](https://github.com/slorber)) + - [#5381](https://github.com/facebook/docusaurus/pull/5381) fix: canary releases should ignore notifier updates ([@slorber](https://github.com/slorber)) + - [#5339](https://github.com/facebook/docusaurus/pull/5339) fix: add admonitions support to mdx partials loaded through the fallback mdx loader ([@slorber](https://github.com/slorber)) + - [#5311](https://github.com/facebook/docusaurus/pull/5311) fix: docusaurus serve logs wrong port if 3000 is taken ([@wan-nyan-wan](https://github.com/wan-nyan-wan)) + - [#5308](https://github.com/facebook/docusaurus/pull/5308) fix: remove unexpected whitespaces in CSS bundle ([@lex111](https://github.com/lex111)) + - [#5268](https://github.com/facebook/docusaurus/pull/5268) fix: fix wrong regex that removes extra letters from swizzled component names ([@Josh-Cena](https://github.com/Josh-Cena)) +- Other + - [#5399](https://github.com/facebook/docusaurus/pull/5399) fix: fix site unlocalized 404 pages + aggressive Netlify /assets caching ([@slorber](https://github.com/slorber)) + - [#5249](https://github.com/facebook/docusaurus/pull/5249) fix: fix Crowdin mapping for pt-BR ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus` + - [#5383](https://github.com/facebook/docusaurus/pull/5383) fix: fix Locale Dropdown RTL icon + Webpack aliases ordering ([@slorber](https://github.com/slorber)) +- `docusaurus-init` + - [#5370](https://github.com/facebook/docusaurus/pull/5370) fix(init): fix links to feature images in classic-typescript ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-common` + - [#5364](https://github.com/facebook/docusaurus/pull/5364) fix: unbreak Details component ([@lex111](https://github.com/lex111)) + - [#5297](https://github.com/facebook/docusaurus/pull/5297) fix: fix constant value import ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-ideal-image` + - [#5334](https://github.com/facebook/docusaurus/pull/5334) fix: plugin ideal-image should generate filename with a hash even in development ([@Pierre-Gilles](https://github.com/Pierre-Gilles)) +- `docusaurus-theme-search-algolia` + - [#5290](https://github.com/facebook/docusaurus/pull/5290) fix: make successful build if missing favicon ([@lex111](https://github.com/lex111)) +- `docusaurus-utils` + - [#5270](https://github.com/facebook/docusaurus/pull/5270) fix: ability to link md files with relative paths when paths contain space ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-types` + - [#5261](https://github.com/facebook/docusaurus/pull/5261) fix: fix various TS errors ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :nail_care: Polish + +- `docusaurus-theme-common` + - [#5402](https://github.com/facebook/docusaurus/pull/5402) refactor: improve styles of Details component ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#5386](https://github.com/facebook/docusaurus/pull/5386) refactor: various tags improvements ([@lex111](https://github.com/lex111)) + - [#5377](https://github.com/facebook/docusaurus/pull/5377) refactor: make main heading font size changeable via CSS var ([@lex111](https://github.com/lex111)) + - [#5355](https://github.com/facebook/docusaurus/pull/5355) refactor: add blog microdata in markup instead of use JSON-LD ([@lex111](https://github.com/lex111)) + - [#5365](https://github.com/facebook/docusaurus/pull/5365) refactor(v2): improved Farsi default translations ([@massoudmaboudi](https://github.com/massoudmaboudi)) + - [#5280](https://github.com/facebook/docusaurus/pull/5280) refactor(v2): improved Farsi default translations ([@massoudmaboudi](https://github.com/massoudmaboudi)) +- Other + - [#5389](https://github.com/facebook/docusaurus/pull/5389) refactor: clean Canny integration + rename 'Feedback' to 'Feature Requests' + improve TS doc page ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5242](https://github.com/facebook/docusaurus/pull/5242) refactor: reduce ESLint warnings / better typing ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :memo: Documentation + +- [#5423](https://github.com/facebook/docusaurus/pull/5423) docs: clarify using custom attributes for navbar link ([@lex111](https://github.com/lex111)) +- [#5421](https://github.com/facebook/docusaurus/pull/5421) docs: add Indent to showcase ([@fouad](https://github.com/fouad)) +- [#5405](https://github.com/facebook/docusaurus/pull/5405) docs: add Gotenberg to showcase ([@gulien](https://github.com/gulien)) +- [#5406](https://github.com/facebook/docusaurus/pull/5406) docs: specify proper min Node.js version for Travis CI example ([@BattleOfPlassey](https://github.com/BattleOfPlassey)) +- [#5390](https://github.com/facebook/docusaurus/pull/5390) docs(v2): showcase BoxyHQ ([@deepakprabhakara](https://github.com/deepakprabhakara)) +- [#5376](https://github.com/facebook/docusaurus/pull/5376) docs(v2): Update Datagit site to showcase page ([@massoudmaboudi](https://github.com/massoudmaboudi)) +- [#5372](https://github.com/facebook/docusaurus/pull/5372) docs: remove docusaurus-preset-name from preset doc ([@slorber](https://github.com/slorber)) +- [#5366](https://github.com/facebook/docusaurus/pull/5366) docs: Add drayman to showcase ([@jansivans](https://github.com/jansivans)) +- [#5369](https://github.com/facebook/docusaurus/pull/5369) docs(v2): Add Nocalhost website to showcase page ([@neaped](https://github.com/neaped)) +- [#5351](https://github.com/facebook/docusaurus/pull/5351) docs(website): bump announcement bar + include Twitter link + refactor site colors ([@slorber](https://github.com/slorber)) +- [#5352](https://github.com/facebook/docusaurus/pull/5352) docs: update `docusaurus-plugin-sass` instructions ([@erickzhao](https://github.com/erickzhao)) +- [#5332](https://github.com/facebook/docusaurus/pull/5332) docs(v2): add mdx-mermaid to resources ([@sjwall](https://github.com/sjwall)) +- [#5331](https://github.com/facebook/docusaurus/pull/5331) docs: Changelog page should display TOC with releases ([@slorber](https://github.com/slorber)) +- [#5329](https://github.com/facebook/docusaurus/pull/5329) docs: add Haochen to showcase page ([@HaochenQ](https://github.com/HaochenQ)) +- [#5313](https://github.com/facebook/docusaurus/pull/5313) docs: try to make plugin/preset config less confusing ([@slorber](https://github.com/slorber)) +- [#5296](https://github.com/facebook/docusaurus/pull/5296) docs: update canary doc ([@slorber](https://github.com/slorber)) +- [#5219](https://github.com/facebook/docusaurus/pull/5219) docs: refactor API documentation ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#5271](https://github.com/facebook/docusaurus/pull/5271) Add Plausible Analytics docs to showcase page ([@metmarkosaric](https://github.com/metmarkosaric)) +- [#5283](https://github.com/facebook/docusaurus/pull/5283) docs: fix broken link to syncing tab choices section ([@lex111](https://github.com/lex111)) +- [#5259](https://github.com/facebook/docusaurus/pull/5259) docs(v2): update Remotion website picture in showcase ([@JonnyBurger](https://github.com/JonnyBurger)) +- [#5260](https://github.com/facebook/docusaurus/pull/5260) docs(v2): add Dart Code Metrics site to showcase page ([@incendial](https://github.com/incendial)) +- [#5253](https://github.com/facebook/docusaurus/pull/5253) docs: Fix typo `2-resources.md` ([@forresst](https://github.com/forresst)) +- [#5248](https://github.com/facebook/docusaurus/pull/5248) docs(v2): add docusaurus-prince-pdf to resources ([@sparanoid](https://github.com/sparanoid)) +- [#5239](https://github.com/facebook/docusaurus/pull/5239) docs(v2): Add unmand site to showcase page ([@dbseal](https://github.com/dbseal)) + +#### :house: Internal + +- Other + - [#5397](https://github.com/facebook/docusaurus/pull/5397) chore: rename docusaurus-2-website package + refactor scripts ([@slorber](https://github.com/slorber)) + - [#5342](https://github.com/facebook/docusaurus/pull/5342) chore: fix e2e yarn berry tests ([@slorber](https://github.com/slorber)) + - [#5328](https://github.com/facebook/docusaurus/pull/5328) refactor(website): convert website to TypeScript ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5336](https://github.com/facebook/docusaurus/pull/5336) chore: bump url-parse from 1.5.1 to 1.5.3 ([@dependabot[bot]](https://github.com/apps/dependabot)) + - [#5312](https://github.com/facebook/docusaurus/pull/5312) fix: fix changelog page mdx import for i18n ([@slorber](https://github.com/slorber)) + - [#5295](https://github.com/facebook/docusaurus/pull/5295) fix: fix canary release versions ([@slorber](https://github.com/slorber)) + - [#5285](https://github.com/facebook/docusaurus/pull/5285) fix: fix canary version names ([@slorber](https://github.com/slorber)) + - [#5269](https://github.com/facebook/docusaurus/pull/5269) misc: enable pt-BR + archive older versions ([@slorber](https://github.com/slorber)) + - [#5237](https://github.com/facebook/docusaurus/pull/5237) chore: enable pt-BR i18n locale on staging ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-migrate`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus` + - [#5345](https://github.com/facebook/docusaurus/pull/5345) refactor: rename Git master branch to main ([@zpao](https://github.com/zpao)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5341](https://github.com/facebook/docusaurus/pull/5341) polish: bind key listener to light/dark toggle + a11y lint fixes ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus` + - [#5347](https://github.com/facebook/docusaurus/pull/5347) chore(mdx-loader): migrate package to TypeScript ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus` + - [#5335](https://github.com/facebook/docusaurus/pull/5335) refactor: better typing + remove unnecessary eslint-disable ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-blog` + - [#5338](https://github.com/facebook/docusaurus/pull/5338) refactor(plugin-blog): style improvements in blogUtils ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic` + - [#5256](https://github.com/facebook/docusaurus/pull/5256) chore: upgrade Infima to alpha.30 ([@lex111](https://github.com/lex111)) +- `docusaurus-init` + - [#5315](https://github.com/facebook/docusaurus/pull/5315) refactor(init): share common files between templates ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5284](https://github.com/facebook/docusaurus/pull/5284) refactor: properly type docs version ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :running_woman: Performance + +- `docusaurus-module-type-aliases`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-types`, `docusaurus` + - [#5349](https://github.com/facebook/docusaurus/pull/5349) refactor(core): replace useDocusaurusContext().isClient by useIsBrowser() ([@slorber](https://github.com/slorber)) + +#### Committers: 27 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- David Seal ([@dbseal](https://github.com/dbseal)) +- Deepak Prabhakara ([@deepakprabhakara](https://github.com/deepakprabhakara)) +- Dmitry Zhifarsky ([@incendial](https://github.com/incendial)) +- Erick Zhao ([@erickzhao](https://github.com/erickzhao)) +- Federico Aloi ([@faloi](https://github.com/faloi)) +- Forresst ([@forresst](https://github.com/forresst)) +- Fouad Matin ([@fouad](https://github.com/fouad)) +- Garry ([@neaped](https://github.com/neaped)) +- Hamza Hamidi ([@hamzahamidi](https://github.com/hamzahamidi)) +- Isaac Philip ([@isaac-philip](https://github.com/isaac-philip)) +- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) +- Jonny Burger ([@JonnyBurger](https://github.com/JonnyBurger)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Julien Neuhart ([@gulien](https://github.com/gulien)) +- Marko Saric ([@metmarkosaric](https://github.com/metmarkosaric)) +- Massoud Maboudi ([@massoudmaboudi](https://github.com/massoudmaboudi)) +- Michal Sänger ([@michalsanger](https://github.com/michalsanger)) +- Palash Shrivastava ([@BattleOfPlassey](https://github.com/BattleOfPlassey)) +- Paul O’Shannessy ([@zpao](https://github.com/zpao)) +- Pierre-Gilles Leymarie ([@Pierre-Gilles](https://github.com/Pierre-Gilles)) +- Sam Wall ([@sjwall](https://github.com/sjwall)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tunghsiao Liu ([@sparanoid](https://github.com/sparanoid)) +- Yan Ivan Evdokimov ([@jansivans](https://github.com/jansivans)) +- [@HaochenQ](https://github.com/HaochenQ) +- wan-nyan-wan ([@wan-nyan-wan](https://github.com/wan-nyan-wan)) + +## 2.0.0-beta.4 (2021-07-28) + +#### :rocket: New Feature + +- `docusaurus-theme-classic` + - [#4912](https://github.com/facebook/docusaurus/pull/4912) feat(v2): add back to top button ([@lex111](https://github.com/lex111)) +- `docusaurus-init` + - [#5235](https://github.com/facebook/docusaurus/pull/5235) feat: docusaurus.new + improve StackBlitz playground integration ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5203](https://github.com/facebook/docusaurus/pull/5203) feat: docs plugin options sidebarCollapsible + sidebarCollapsed ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#5207](https://github.com/facebook/docusaurus/pull/5207) feat: multiple playground choices ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus` + - [#4273](https://github.com/facebook/docusaurus/pull/4273) feat(v2): redesign mobile UX: inline TOC + doc sidebar in main menu ([@lex111](https://github.com/lex111)) + +#### :boom: Breaking Change + +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5203](https://github.com/facebook/docusaurus/pull/5203) feat: docs plugin options sidebarCollapsible + sidebarCollapsed ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils`, `docusaurus` + - [#5173](https://github.com/facebook/docusaurus/pull/5173) feat(v2): generalize usage of \_ prefix convention to exclude content files/folders ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus` + - [#4273](https://github.com/facebook/docusaurus/pull/4273) feat(v2): redesign mobile UX: inline TOC + doc sidebar in main menu ([@lex111](https://github.com/lex111)) + +#### :bug: Bug Fix + +- `docusaurus-plugin-content-blog` + - [#5232](https://github.com/facebook/docusaurus/pull/5232) fix(v2): blog should parse frontMatter.date even when time is present ([@wenerme](https://github.com/wenerme)) +- `docusaurus-theme-classic` + - [#5230](https://github.com/facebook/docusaurus/pull/5230) fix(v2): remove top margin from first element inside doc article ([@lex111](https://github.com/lex111)) + - [#5229](https://github.com/facebook/docusaurus/pull/5229) fix(v2): keep mobile TOC after hydration ([@lex111](https://github.com/lex111)) + - [#5179](https://github.com/facebook/docusaurus/pull/5179) fix(v2): wrap dropdown item to missing li element + remove extra attributes ([@lex111](https://github.com/lex111)) + - [#5183](https://github.com/facebook/docusaurus/pull/5183) fix(v2): pass all props to CodeBlock component ([@lex111](https://github.com/lex111)) + - [#5176](https://github.com/facebook/docusaurus/pull/5176) fix(v2): Fix type for navlink label ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5172](https://github.com/facebook/docusaurus/pull/5172) fix(v2): hide mobile collapsible doc toc if no headings ([@slorber](https://github.com/slorber)) + - [#5161](https://github.com/facebook/docusaurus/pull/5161) fix(v2): disable default behavior when click on collapsible item ([@lex111](https://github.com/lex111)) + - [#5151](https://github.com/facebook/docusaurus/pull/5151) fix(v2): add missing french translations for mobile ([@forresst](https://github.com/forresst)) + - [#5104](https://github.com/facebook/docusaurus/pull/5104) fix(v2): fix SkipToContent programmatic focus when updating querystring ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-search-algolia` + - [#5214](https://github.com/facebook/docusaurus/pull/5214) fix: upgrade Docsearch to avoid layout shift ([@slorber](https://github.com/slorber)) + - [#5135](https://github.com/facebook/docusaurus/pull/5135) chore(v2): update @docsearch/react ([@shortcuts](https://github.com/shortcuts)) +- `docusaurus` + - [#5204](https://github.com/facebook/docusaurus/pull/5204) fix: cli upgrade helper fail when no `package.dependencies` ([@mweststrate](https://github.com/mweststrate)) + - [#5164](https://github.com/facebook/docusaurus/pull/5164) fix(v2): revert webpack.resolve.symlinks = false ([@slorber](https://github.com/slorber)) + - [#5126](https://github.com/facebook/docusaurus/pull/5126) fix(v2): remove webpackConfig.resolve.symlinks: true ([@slorber](https://github.com/slorber)) + - [#5110](https://github.com/facebook/docusaurus/pull/5110) fix(v2): Fix update-notifier not run at first and not notifying consistently ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils` + - [#5199](https://github.com/facebook/docusaurus/pull/5199) fix(v2): Fix MDX docs being considered as partials when siteDir match the \_ prefix convention ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-pwa` + - [#5185](https://github.com/facebook/docusaurus/pull/5185) fix(v2): add base URL to content attribute of head tags PWA ([@lex111](https://github.com/lex111)) + - [#5169](https://github.com/facebook/docusaurus/pull/5169) refactor(v2): automatically add base URL to PWA head tags ([@lex111](https://github.com/lex111)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils`, `docusaurus` + - [#5173](https://github.com/facebook/docusaurus/pull/5173) feat(v2): generalize usage of \_ prefix convention to exclude content files/folders ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-common` + - [#5159](https://github.com/facebook/docusaurus/pull/5159) fix(v2): Fix Collapsible hydration layout shift ([@slorber](https://github.com/slorber)) + - [#5146](https://github.com/facebook/docusaurus/pull/5146) fix(v2): improve work of useCollapsible hook with multiple clicks ([@lex111](https://github.com/lex111)) +- `docusaurus-types` + - [#5129](https://github.com/facebook/docusaurus/pull/5129) fix(v2): fix d.ts lint error ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5116](https://github.com/facebook/docusaurus/pull/5116) fix(v2): introduce useCollapsible to fix collapsible animation perf issues ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-client-redirects` + - [#5102](https://github.com/facebook/docusaurus/pull/5102) fix(v2): fix redirect plugin when trailingSlash=false for .html extension ([@slorber](https://github.com/slorber)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#5228](https://github.com/facebook/docusaurus/pull/5228) refactor(v2): fix small typo in Russian translation ([@antonvasilev52](https://github.com/antonvasilev52)) + - [#5222](https://github.com/facebook/docusaurus/pull/5222) chore(v2): update Infima to alpha 28 ([@lex111](https://github.com/lex111)) + - [#5224](https://github.com/facebook/docusaurus/pull/5224) refactor(v2): update Russian translation ([@lex111](https://github.com/lex111)) + - [#5217](https://github.com/facebook/docusaurus/pull/5217) refactor(v2): improved Farsi default translations ([@massoudmaboudi](https://github.com/massoudmaboudi)) + - [#5171](https://github.com/facebook/docusaurus/pull/5171) refactor(v2): increase content area if blog sidebar is off ([@lex111](https://github.com/lex111)) + - [#5154](https://github.com/facebook/docusaurus/pull/5154) refactor(v2): Hindi translation for semantic doc sidebar ([@pranabdas](https://github.com/pranabdas)) + - [#5145](https://github.com/facebook/docusaurus/pull/5145) refactor(v2): use Collapsible for mobile nav items ([@lex111](https://github.com/lex111)) + - [#5138](https://github.com/facebook/docusaurus/pull/5138) refactor(v2): Update Hebrew translations ([@nirtamir2](https://github.com/nirtamir2)) + - [#5140](https://github.com/facebook/docusaurus/pull/5140) refactor(v2): bn translation improvements for semantic doc sidebar ([@pranabdas](https://github.com/pranabdas)) + - [#5139](https://github.com/facebook/docusaurus/pull/5139) feat(v2): complete Chinese code translations ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5118](https://github.com/facebook/docusaurus/pull/5118) refactor(v2): pt-BR translations improve semantic doc sidebar and tags ([@marssaljr](https://github.com/marssaljr)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#5215](https://github.com/facebook/docusaurus/pull/5215) refactor: make code block shadows consistent with new admonitions ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic` + - [#5193](https://github.com/facebook/docusaurus/pull/5193) refactor: redesign admonitions/callouts/quotes ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5168](https://github.com/facebook/docusaurus/pull/5168) refactor(v2): mobile dropdown navbar: expand when subitem become active ([@slorber](https://github.com/slorber)) + +#### :memo: Documentation + +- [#5236](https://github.com/facebook/docusaurus/pull/5236) docs: add Verdaccio.org to showcase ([@semoal](https://github.com/semoal)) +- [#5218](https://github.com/facebook/docusaurus/pull/5218) docs(v2): remove vector.dev from showcase ([@lex111](https://github.com/lex111)) +- [#5212](https://github.com/facebook/docusaurus/pull/5212) docs: mention Link can be used for external links ([@slorber](https://github.com/slorber)) +- [#5210](https://github.com/facebook/docusaurus/pull/5210) docs(v2): Elaboration of raw-loader in markdown react component ([@pranabdas](https://github.com/pranabdas)) +- [#5191](https://github.com/facebook/docusaurus/pull/5191) docs: user should restart docusaurus after adding prism additionalLanguage ([@tohidnateghi](https://github.com/tohidnateghi)) +- [#5175](https://github.com/facebook/docusaurus/pull/5175) docs: update API docs on navbar behavior ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#5189](https://github.com/facebook/docusaurus/pull/5189) docs(v2): Add orbitjs site to showcase page ([@dgeb](https://github.com/dgeb)) +- [#5177](https://github.com/facebook/docusaurus/pull/5177) docs(v2): add easyjwt to users ([@dbrrt](https://github.com/dbrrt)) +- [#5187](https://github.com/facebook/docusaurus/pull/5187) docs(v2): Add quickwit to user.js and png. ([@fmassot](https://github.com/fmassot)) +- [#5184](https://github.com/facebook/docusaurus/pull/5184) docs(v2): Add react-complex-tree to users.js ([@lukasbach](https://github.com/lukasbach)) +- [#5178](https://github.com/facebook/docusaurus/pull/5178) docs(v2): Update tutorial link ([@slorber](https://github.com/slorber)) +- [#5158](https://github.com/facebook/docusaurus/pull/5158) docs(v2): Update deploy with Qovery docs for V2 ([@arnaudjnn](https://github.com/arnaudjnn)) +- [#5152](https://github.com/facebook/docusaurus/pull/5152) docs(v2): Indent code example to improve readability ([@rluvaton](https://github.com/rluvaton)) +- [#5133](https://github.com/facebook/docusaurus/pull/5133) docs(v2): GIF format is not suported ([@NazarStreletskyi](https://github.com/NazarStreletskyi)) +- [#5117](https://github.com/facebook/docusaurus/pull/5117) docs(v2): Add Prismatic docs page to showcase. ([@taylorreece](https://github.com/taylorreece)) +- [#5115](https://github.com/facebook/docusaurus/pull/5115) docs(v2): Add LiveKit to showcase ([@davidzhao](https://github.com/davidzhao)) +- [#5114](https://github.com/facebook/docusaurus/pull/5114) docs(v2): add Blink Shell Documentation to Showcase ([@pcho](https://github.com/pcho)) +- [#5112](https://github.com/facebook/docusaurus/pull/5112) docs(v2): clarify how to disable edit links entirely ([@lennartkoopmann](https://github.com/lennartkoopmann)) +- [#5113](https://github.com/facebook/docusaurus/pull/5113) docs(v2): Add CryptoDevHub to Showcase ([@pmuens](https://github.com/pmuens)) + +#### :house: Internal + +- `docusaurus-theme-classic` + - [#5234](https://github.com/facebook/docusaurus/pull/5234) chore: Upgrade infima 29 ([@slorber](https://github.com/slorber)) + - [#5130](https://github.com/facebook/docusaurus/pull/5130) test(v2): dogfooding: add huge sidebar for testing purposes ([@slorber](https://github.com/slorber)) +- Other + - [#5223](https://github.com/facebook/docusaurus/pull/5223) chore: fix iframe background color in dark mode ([@lex111](https://github.com/lex111)) + - [#5206](https://github.com/facebook/docusaurus/pull/5206) misc: add script to keep starters branch/repos up-to-date ([@slorber](https://github.com/slorber)) + - [#5167](https://github.com/facebook/docusaurus/pull/5167) fix(v2): fix website PWA icon hrefs ([@slorber](https://github.com/slorber)) + - [#5166](https://github.com/facebook/docusaurus/pull/5166) fix(v2): fix yarn clear command ([@slorber](https://github.com/slorber)) + - [#5137](https://github.com/facebook/docusaurus/pull/5137) chore: upgrade crowdin ([@slorber](https://github.com/slorber)) + - [#5111](https://github.com/facebook/docusaurus/pull/5111) misc: monitor site global data with build size bot ([@slorber](https://github.com/slorber)) + +#### :running_woman: Performance + +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5136](https://github.com/facebook/docusaurus/pull/5136) perf(v2): lazy sidebar categories / collapsibles, reduce html output / build times ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#5130](https://github.com/facebook/docusaurus/pull/5130) test(v2): dogfooding: add huge sidebar for testing purposes ([@slorber](https://github.com/slorber)) + +#### Committers: 28 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Arijit Kundu ([@covalentbond](https://github.com/covalentbond)) +- Arnaud Jeannin ([@arnaudjnn](https://github.com/arnaudjnn)) +- Christian Flach ([@cmfcmf](https://github.com/cmfcmf)) +- Clément Vannicatte ([@shortcuts](https://github.com/shortcuts)) +- Dan Gebhardt ([@dgeb](https://github.com/dgeb)) +- David Barrat ([@dbrrt](https://github.com/dbrrt)) +- David Zhao ([@davidzhao](https://github.com/davidzhao)) +- Forresst ([@forresst](https://github.com/forresst)) +- François Massot ([@fmassot](https://github.com/fmassot)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Lennart Koopmann ([@lennartkoopmann](https://github.com/lennartkoopmann)) +- Lukas Bach ([@lukasbach](https://github.com/lukasbach)) +- Marçal Junior ([@marssaljr](https://github.com/marssaljr)) +- Massoud Maboudi ([@massoudmaboudi](https://github.com/massoudmaboudi)) +- Michel Weststrate ([@mweststrate](https://github.com/mweststrate)) +- Nazar ([@NazarStreletskyi](https://github.com/NazarStreletskyi)) +- Philipp Muens ([@pmuens](https://github.com/pmuens)) +- Pranab Das ([@pranabdas](https://github.com/pranabdas)) +- Przemysław Chojecki ([@pcho](https://github.com/pcho)) +- Raz Luvaton ([@rluvaton](https://github.com/rluvaton)) +- Sergio Moreno ([@semoal](https://github.com/semoal)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Taylor Reece ([@taylorreece](https://github.com/taylorreece)) +- [@antonvasilev52](https://github.com/antonvasilev52) +- [@nirtamir2](https://github.com/nirtamir2) +- tohid nateghi ([@tohidnateghi](https://github.com/tohidnateghi)) +- 陈杨文 ([@wenerme](https://github.com/wenerme)) + +## 2.0.0-beta.3 (2021-06-30) + +#### :rocket: New Feature + +- `docusaurus-theme-classic` + - [#5092](https://github.com/facebook/docusaurus/pull/5092) feat(v2): add icon to external footer links ([@lex111](https://github.com/lex111)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#5080](https://github.com/facebook/docusaurus/pull/5080) fix(v2): classic theme - semantic correct anchors links ([@AuHau](https://github.com/AuHau)) + - [#5081](https://github.com/facebook/docusaurus/pull/5081) fix(v2): restore previous scroll position on back button click ([@lex111](https://github.com/lex111)) + - [#5063](https://github.com/facebook/docusaurus/pull/5063) fix(v2): restore responsive menu ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#5094](https://github.com/facebook/docusaurus/pull/5094) fix(v2): fix typos in swizzle command ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5095](https://github.com/facebook/docusaurus/pull/5095) fix(v2): fix swizzle readComponent ([@slorber](https://github.com/slorber)) + - [#5059](https://github.com/facebook/docusaurus/pull/5059) fix(v2): fix webpack SSG plugin error thrown due to new URL() / \_\_filename ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs` + - [#5097](https://github.com/facebook/docusaurus/pull/5097) fix(v2): fix useEffect infinite loop in blogOnly mode ([@slorber](https://github.com/slorber)) + - [#5074](https://github.com/facebook/docusaurus/pull/5074) fix(v2): allow negative sidebar positions ([@kdrag0n](https://github.com/kdrag0n)) +- `docusaurus-plugin-client-redirects` + - [#5093](https://github.com/facebook/docusaurus/pull/5093) fix(v2): redirect from should work with trailingSlash: true ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects`, `docusaurus-utils` + - [#5085](https://github.com/facebook/docusaurus/pull/5085) fix(v2): redirect plugin should emit redirect files with lower precedence than redirect target ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-sitemap`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus` + - [#5082](https://github.com/facebook/docusaurus/pull/5082) fix(v2): never remove trailing slash from site root like '/baseUrl/' ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-sitemap` + - [#5068](https://github.com/facebook/docusaurus/pull/5068) fix(v2): sitemap should respect the global trailingSlash config option. ([@taylorreece](https://github.com/taylorreece)) +- `docusaurus-types` + - [#5058](https://github.com/facebook/docusaurus/pull/5058) fix(v2): fix bad @docusaurus/types Plugin type generics ([@jsamr](https://github.com/jsamr)) + +#### :memo: Documentation + +- [#5064](https://github.com/facebook/docusaurus/pull/5064) docs(v2): Rewrite markdown images section ([@ramiy](https://github.com/ramiy)) +- [#5086](https://github.com/facebook/docusaurus/pull/5086) docs(v2): Add SQL Frames to the showcase ([@dirslashls](https://github.com/dirslashls)) +- [#5073](https://github.com/facebook/docusaurus/pull/5073) docs(v2): update installation docs ([@iamayushdas](https://github.com/iamayushdas)) +- [#5061](https://github.com/facebook/docusaurus/pull/5061) docs(v2:) Divide `markdown-features/code-blocks` to smaller sections ([@ramiy](https://github.com/ramiy)) +- [#5066](https://github.com/facebook/docusaurus/pull/5066) docs(v2): correct typo ([@bperlmutter](https://github.com/bperlmutter)) + +#### :house: Internal + +- `docusaurus-types` + - [#5067](https://github.com/facebook/docusaurus/pull/5067) chore: unstable yarn.lock ([@slorber](https://github.com/slorber)) +- Other + - [#5057](https://github.com/facebook/docusaurus/pull/5057) chore(v2): upgrade examples to beta.2 ([@slorber](https://github.com/slorber)) + +#### Committers: 11 + +- Adam Uhlíř ([@AuHau](https://github.com/AuHau)) +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Ayush das ([@iamayushdas](https://github.com/iamayushdas)) +- Danny Lin ([@kdrag0n](https://github.com/kdrag0n)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Jules Sam. Randolph ([@jsamr](https://github.com/jsamr)) +- Rami Yushuvaev ([@ramiy](https://github.com/ramiy)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Taylor Reece ([@taylorreece](https://github.com/taylorreece)) +- [@bperlmutter](https://github.com/bperlmutter) +- [@dirslashls](https://github.com/dirslashls) + +## 2.0.0-beta.2 (2021-06-24) + +#### :rocket: New Feature + +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#5052](https://github.com/facebook/docusaurus/pull/5052) feat(v2): docs version banner configuration option ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` + - [#5037](https://github.com/facebook/docusaurus/pull/5037) feat(v2): plugins injectHtmlTags + configureWebpack should receive content loaded ([@slorber](https://github.com/slorber)) + +#### :boom: Breaking Change + +- `docusaurus-plugin-content-docs` + - [#5053](https://github.com/facebook/docusaurus/pull/5053) refactor(v2): remove deprecated docs option excludeNextVersionDocs ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#5052](https://github.com/facebook/docusaurus/pull/5052) feat(v2): docs version banner configuration option ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-plugin-content-blog`, `docusaurus-types`, `docusaurus` + - [#5054](https://github.com/facebook/docusaurus/pull/5054) fix(v2): allow undefined favicon ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs` + - [#5048](https://github.com/facebook/docusaurus/pull/5048) fix(v2): read last update from inner git repositories ([@felipecrs](https://github.com/felipecrs)) +- `docusaurus-theme-classic` + - [#5050](https://github.com/facebook/docusaurus/pull/5050) fix(v2): add shadow to skip link on focus only ([@lex111](https://github.com/lex111)) + - [#5035](https://github.com/facebook/docusaurus/pull/5035) fix(v2): fix some docs container/sidebar layout issues ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#5047](https://github.com/facebook/docusaurus/pull/5047) fix(v2): Fix Webpack persistent caching (evict on swizzle/alias/config change) ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5040](https://github.com/facebook/docusaurus/pull/5040) fix(v2): Fix announcementBar layout shifts ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#5034](https://github.com/facebook/docusaurus/pull/5034) fix(v2): dev css modules classnames should include filename ([@slorber](https://github.com/slorber)) + - [#5016](https://github.com/facebook/docusaurus/pull/5016) fix(v2): add missing quote in build command output ([@manuelmeurer](https://github.com/manuelmeurer)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#5023](https://github.com/facebook/docusaurus/pull/5023) fix(v2): ignore hash changes in useChangeRoute hook ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils-validation` + - [#5032](https://github.com/facebook/docusaurus/pull/5032) fix(v2): less strict blog/docs uri frontmatter validation ([@slorber](https://github.com/slorber)) + +#### :nail_care: Polish + +- `docusaurus-plugin-content-docs` + - [#5053](https://github.com/facebook/docusaurus/pull/5053) refactor(v2): remove deprecated docs option excludeNextVersionDocs ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#4993](https://github.com/facebook/docusaurus/pull/4993) style(v2): reduce number of ESLint warnings ([@Josh-Cena](https://github.com/Josh-Cena)) +- Other + - [#5017](https://github.com/facebook/docusaurus/pull/5017) chore(v2): remove badge for v1 tests ([@loozhengyuan](https://github.com/loozhengyuan)) + +#### :memo: Documentation + +- Other + - [#5049](https://github.com/facebook/docusaurus/pull/5049) docs(v2): Fix Gatsby theme name for docs site - Docz ([@ramiy](https://github.com/ramiy)) + - [#5030](https://github.com/facebook/docusaurus/pull/5030) docs(v2): typo in deployment.mdx ([@eshantri](https://github.com/eshantri)) + - [#5022](https://github.com/facebook/docusaurus/pull/5022) docs(v2): Add React Native Render HTML site to showcase page ([@jsamr](https://github.com/jsamr)) + - [#5027](https://github.com/facebook/docusaurus/pull/5027) docs(v2): Add Buddy to deployment doc ([@tomekpapiernik](https://github.com/tomekpapiernik)) + - [#5021](https://github.com/facebook/docusaurus/pull/5021) docs(v2): fix incorrect anchor links in website ([@teikjun](https://github.com/teikjun)) + - [#5007](https://github.com/facebook/docusaurus/pull/5007) docs(v2): wrap mdx usage in mdx-code-block ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#5033](https://github.com/facebook/docusaurus/pull/5033) docs(v2): GH pages: recommend using trailingSlash ([@slorber](https://github.com/slorber)) + +#### :house: Internal + +- [#5005](https://github.com/facebook/docusaurus/pull/5005) chore: add archived versions system + archive alpha.73-75 ([@slorber](https://github.com/slorber)) + +#### Committers: 11 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Eshan Tripathi ([@eshantri](https://github.com/eshantri)) +- Felipe Santos ([@felipecrs](https://github.com/felipecrs)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Jules Sam. Randolph ([@jsamr](https://github.com/jsamr)) +- Manuel Meurer ([@manuelmeurer](https://github.com/manuelmeurer)) +- Rami Yushuvaev ([@ramiy](https://github.com/ramiy)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Teik Jun ([@teikjun](https://github.com/teikjun)) +- Tomasz Papiernik ([@tomekpapiernik](https://github.com/tomekpapiernik)) +- ZhengYuan Loo ([@loozhengyuan](https://github.com/loozhengyuan)) + +## 2.0.0-beta.1 (2021-06-18) + +#### :rocket: New Feature + +- `docusaurus-plugin-content-docs` + - [#4982](https://github.com/facebook/docusaurus/pull/4982) feat(v2): add docs pagination_label frontmatter ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#4949](https://github.com/facebook/docusaurus/pull/4949) feat(v2): add icon to external navbar links ([@lex111](https://github.com/lex111)) + - [#4939](https://github.com/facebook/docusaurus/pull/4939) feat(v2): theme default translations Bengali ([@Neilblaze](https://github.com/Neilblaze)) + - [#4811](https://github.com/facebook/docusaurus/pull/4811) feat(v2): Add hebrew translations ([@slorber](https://github.com/slorber)) + - [#4798](https://github.com/facebook/docusaurus/pull/4798) feat(v2): add theme Danish translation ([@PsychTechApS](https://github.com/PsychTechApS)) +- `docusaurus-init` + - [#4968](https://github.com/facebook/docusaurus/pull/4968) feat(v2): add code block theming in init template ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#4908](https://github.com/facebook/docusaurus/pull/4908) feat(v2): add trailingSlash config option ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` + - [#4796](https://github.com/facebook/docusaurus/pull/4796) feat(v2): exhaustive docs frontmatter schema ([@nam-hle](https://github.com/nam-hle)) +- `docusaurus-types`, `docusaurus` + - [#4618](https://github.com/facebook/docusaurus/pull/4618) feat(v2): allow config plugins as functions or [function,options] ([@besemuna](https://github.com/besemuna)) +- `docusaurus-plugin-content-blog`, `docusaurus-utils-validation` + - [#4759](https://github.com/facebook/docusaurus/pull/4759) feat(v2): exhaustive BlogPostFrontMatter schema validation ([@nam-hle](https://github.com/nam-hle)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#5001](https://github.com/facebook/docusaurus/pull/5001) chore(v2): update Infima to alpha 26 ([@lex111](https://github.com/lex111)) + - [#4986](https://github.com/facebook/docusaurus/pull/4986) fix(v2): fix UX for docsVersionDropdown on mobile for single version ([@slorber](https://github.com/slorber)) + - [#4980](https://github.com/facebook/docusaurus/pull/4980) fix(v2): make proper data type for prependBaseUrlToHref field ([@lex111](https://github.com/lex111)) + - [#4943](https://github.com/facebook/docusaurus/pull/4943) fix(v2): improve accessibility of code blocks ([@lex111](https://github.com/lex111)) + - [#4917](https://github.com/facebook/docusaurus/pull/4917) fix(v2): tidy up Markdown page layout ([@lex111](https://github.com/lex111)) + - [#4906](https://github.com/facebook/docusaurus/pull/4906) fix(v2): fix minor a11y issues ([@lex111](https://github.com/lex111)) + - [#4900](https://github.com/facebook/docusaurus/pull/4900) fix(v2): adjust margin after content title ([@lex111](https://github.com/lex111)) + - [#4855](https://github.com/facebook/docusaurus/pull/4855) chore(v2): update infima to alpha 24 ([@lex111](https://github.com/lex111)) + - [#4819](https://github.com/facebook/docusaurus/pull/4819) fix(v2): Amend Hebrew translations ([@liorheber](https://github.com/liorheber)) + - [#4815](https://github.com/facebook/docusaurus/pull/4815) fix(v2): Fix Hebrew translations ([@nirtamir2](https://github.com/nirtamir2)) + - [#4792](https://github.com/facebook/docusaurus/pull/4792) fix(v2): fix minor a11y issue with headings ([@lex111](https://github.com/lex111)) + - [#4793](https://github.com/facebook/docusaurus/pull/4793) fix(v2): unbreak enhanced width of doc item wrapper ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-utils-common` + - [#5000](https://github.com/facebook/docusaurus/pull/5000) fix(v2): fix theme array deduplication bug ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus` + - [#4988](https://github.com/facebook/docusaurus/pull/4988) fix(v2): redirect plugin should use siteConfig.trailingSlash ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog` + - [#4983](https://github.com/facebook/docusaurus/pull/4983) fix(v2): always use UTC when dealing with blog dates ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#4962](https://github.com/facebook/docusaurus/pull/4962) fix(v2): respect base url in RSS feeds ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#4985](https://github.com/facebook/docusaurus/pull/4985) fix(v2): navbar doc item fallback: search doc in lastVersion ([@slorber](https://github.com/slorber)) +- `docusaurus-remark-plugin-npm2yarn` + - [#4964](https://github.com/facebook/docusaurus/pull/4964) fix(v2): avoid duplicated imports in npm2yarn plugin ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs` + - [#4970](https://github.com/facebook/docusaurus/pull/4970) fix(v2): sidebar_label should be used to compute next/previous button labels ([@slorber](https://github.com/slorber)) + - [#4861](https://github.com/facebook/docusaurus/pull/4861) fix(v2): allow relative sidebar path resolution in docs:version command ([@lex111](https://github.com/lex111)) + - [#4859](https://github.com/facebook/docusaurus/pull/4859) fix(v2): use frontmatter title at first for paginated links ([@lex111](https://github.com/lex111)) + - [#4775](https://github.com/facebook/docusaurus/pull/4775) fix(v2): improve dx sidebar config, ability to have no sidebars file ([@nam-hle](https://github.com/nam-hle)) +- `docusaurus-plugin-sitemap`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#4950](https://github.com/facebook/docusaurus/pull/4950) fix(v2): sitemap plugin should handle siteConfig.trailingSlash automatically ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#4924](https://github.com/facebook/docusaurus/pull/4924) fix(v2): respect baseUrl in serving command ([@lex111](https://github.com/lex111)) + - [#4935](https://github.com/facebook/docusaurus/pull/4935) fix(v2): render children in BrowserOnly after client is ready ([@lex111](https://github.com/lex111)) + - [#4894](https://github.com/facebook/docusaurus/pull/4894) fix(v2): escape HTML entities in user tags attributes ([@lex111](https://github.com/lex111)) + - [#4789](https://github.com/facebook/docusaurus/pull/4789) fix(v2): transpile libs with too recent syntax with babel ([@slorber](https://github.com/slorber)) + - [#4784](https://github.com/facebook/docusaurus/pull/4784) fix(v2): update notifier should never suggest to downgrade ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-utils` + - [#4882](https://github.com/facebook/docusaurus/pull/4882) fix(v2): fix contentTitle issues when markdown h1 title contains code blocks ([@slorber](https://github.com/slorber)) +- `docusaurus-utils` + - [#4862](https://github.com/facebook/docusaurus/pull/4862) fix(v2): remove Markdown heading id from excerpt ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#4871](https://github.com/facebook/docusaurus/pull/4871) fix(v2): unbreak adding of custom HTML metadatas ([@lex111](https://github.com/lex111)) + - [#4797](https://github.com/facebook/docusaurus/pull/4797) fix(v2): do not focus on skip link if page refreshed ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#4856](https://github.com/facebook/docusaurus/pull/4856) fix(v2): adjust padding when custom search box location ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock` + - [#4830](https://github.com/facebook/docusaurus/pull/4830) fix(v2): pin prism-react-renderer version to 1.1.1 ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-ideal-image`, `lqip-loader` + - [#4806](https://github.com/facebook/docusaurus/pull/4806) chore(v2): update sharp to 0.28.2 ([@lex111](https://github.com/lex111)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#4995](https://github.com/facebook/docusaurus/pull/4995) refactor(v2): reduce top padding in doc content container ([@lex111](https://github.com/lex111)) + - [#4918](https://github.com/facebook/docusaurus/pull/4918) refactor(v2): readjust footer of blog item ([@lex111](https://github.com/lex111)) + - [#4959](https://github.com/facebook/docusaurus/pull/4959) refactor(v2): minor cleanups ([@lex111](https://github.com/lex111)) + - [#4945](https://github.com/facebook/docusaurus/pull/4945) refactor(v2): remove extra padding from doc item container ([@lex111](https://github.com/lex111)) + - [#4940](https://github.com/facebook/docusaurus/pull/4940) refactor(v2): improve semantic doc sidebar markup ([@lex111](https://github.com/lex111)) + - [#4961](https://github.com/facebook/docusaurus/pull/4961) refactor(v2): improve semantic blog sidebar markup ([@lex111](https://github.com/lex111)) + - [#4903](https://github.com/facebook/docusaurus/pull/4903) refactor(v2): make doc item layout more semantic ([@lex111](https://github.com/lex111)) + - [#4877](https://github.com/facebook/docusaurus/pull/4877) refactor(v2): reduce vertical space in doc content container ([@lex111](https://github.com/lex111)) + - [#4914](https://github.com/facebook/docusaurus/pull/4914) refactor(v2): use SVG for external link icon ([@lex111](https://github.com/lex111)) + - [#4916](https://github.com/facebook/docusaurus/pull/4916) refactor(v2): replace strong with b in UI components ([@lex111](https://github.com/lex111)) + - [#4926](https://github.com/facebook/docusaurus/pull/4926) refactor(v2): hide decorative SVGs from screen readers ([@lex111](https://github.com/lex111)) + - [#4865](https://github.com/facebook/docusaurus/pull/4865) refactor(v2): make little better doc update block UI ([@lex111](https://github.com/lex111)) + - [#4795](https://github.com/facebook/docusaurus/pull/4795) refactor(v2): remove transition on body element ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` + - [#4989](https://github.com/facebook/docusaurus/pull/4989) refactor(v2): blog/docs: add more context in error messages ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#4979](https://github.com/facebook/docusaurus/pull/4979) refactor(v2): cleanup console output ([@lex111](https://github.com/lex111)) +- `docusaurus-utils-validation`, `docusaurus` + - [#4977](https://github.com/facebook/docusaurus/pull/4977) polish(v2): url-subpath config validation warning ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs` + - [#4969](https://github.com/facebook/docusaurus/pull/4969) refactor(v2): include path in error about non-existent ids ([@lex111](https://github.com/lex111)) + - [#4863](https://github.com/facebook/docusaurus/pull/4863) refactor(v2): remove sidebar_label filed from doc metadata file ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus` + - [#4907](https://github.com/facebook/docusaurus/pull/4907) refactor(v2): remove type attribute from link and script tags ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-search-algolia` + - [#4919](https://github.com/facebook/docusaurus/pull/4919) refactor(v2): improve markup and styling on search page ([@lex111](https://github.com/lex111)) + - [#4867](https://github.com/facebook/docusaurus/pull/4867) chore(v2): update @docsearch/react ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog` + - [#4905](https://github.com/facebook/docusaurus/pull/4905) refactor(v2): do not generate RSS files for empty feed ([@lex111](https://github.com/lex111)) + - [#4860](https://github.com/facebook/docusaurus/pull/4860) refactor(v2): use aliased path for blog list sidebar file ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#4870](https://github.com/facebook/docusaurus/pull/4870) refactor(v2): add exception handling if external command is fails ([@lex111](https://github.com/lex111)) + - [#4875](https://github.com/facebook/docusaurus/pull/4875) refactor(v2): make even better SSR error notify and add tip ([@lex111](https://github.com/lex111)) + - [#4866](https://github.com/facebook/docusaurus/pull/4866) refactor(v2): output URL to console only if it has changed ([@lex111](https://github.com/lex111)) +- `docusaurus-utils` + - [#4814](https://github.com/facebook/docusaurus/pull/4814) refactor(v2): purify normalizeUrl ([@nam-hle](https://github.com/nam-hle)) + +#### :memo: Documentation + +- Other + - [#4987](https://github.com/facebook/docusaurus/pull/4987) docs(v2): document canary releases ([@slorber](https://github.com/slorber)) + - [#4981](https://github.com/facebook/docusaurus/pull/4981) docs(v2): minor tweaks ([@lex111](https://github.com/lex111)) + - [#4976](https://github.com/facebook/docusaurus/pull/4976) docs(v2): mention to install the algolia package in search doc ([@slorber](https://github.com/slorber)) + - [#4953](https://github.com/facebook/docusaurus/pull/4953) docs(v2): add Flagsmith to showcase ([@dabeeeenster](https://github.com/dabeeeenster)) + - [#4942](https://github.com/facebook/docusaurus/pull/4942) docs(v2): add info about `DefaultValue` prop in `Tabs` ([@ArtFlag](https://github.com/ArtFlag)) + - [#4898](https://github.com/facebook/docusaurus/pull/4898) docs(v2): add ClarityChallenge to showcase ([@jonbarker68](https://github.com/jonbarker68)) + - [#4896](https://github.com/facebook/docusaurus/pull/4896) docs(v2): fix incorrect link to plugin-ideal-image ([@phwt](https://github.com/phwt)) + - [#4893](https://github.com/facebook/docusaurus/pull/4893) docs(v2): presets: fix typo in bootstrap preset ([@silva-nick](https://github.com/silva-nick)) + - [#4887](https://github.com/facebook/docusaurus/pull/4887) docs(v2): Add Aide Jeune website to Docusaurus site showcase ([@l0u1sg](https://github.com/l0u1sg)) + - [#4821](https://github.com/facebook/docusaurus/pull/4821) docs(v2): New doc page for math equations ([@pranabdas](https://github.com/pranabdas)) + - [#4885](https://github.com/facebook/docusaurus/pull/4885) docs(v2): v2 migration guide: mention Algolia config update ([@slorber](https://github.com/slorber)) + - [#4876](https://github.com/facebook/docusaurus/pull/4876) docs(v2): update steps in the github-actions section ([@wise-introvert](https://github.com/wise-introvert)) + - [#4880](https://github.com/facebook/docusaurus/pull/4880) docs(v2): grammar typo in migration-overview.md ([@jmazin](https://github.com/jmazin)) + - [#4879](https://github.com/facebook/docusaurus/pull/4879) docs(v2): Added FireCMS to the showcase ([@fgatti675](https://github.com/fgatti675)) + - [#4849](https://github.com/facebook/docusaurus/pull/4849) docs(v2): fix Java syntax highlight in website ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#4818](https://github.com/facebook/docusaurus/pull/4818) docs(v2): add mr-pdf to resources ([@antonygibbs](https://github.com/antonygibbs)) + - [#4835](https://github.com/facebook/docusaurus/pull/4835) docs(v2): fix grammar typo on Creating pages ([@Christopher-Hsieh](https://github.com/Christopher-Hsieh)) + - [#4837](https://github.com/facebook/docusaurus/pull/4837) docs(v2): fix missing closing bracket ([@pmqueiroz](https://github.com/pmqueiroz)) + - [#4820](https://github.com/facebook/docusaurus/pull/4820) docs(v2): Fix typo in doc: sidebar.md ([@pranabdas](https://github.com/pranabdas)) + - [#4813](https://github.com/facebook/docusaurus/pull/4813) docs(v2): fix css snipped with missing color ([@slorber](https://github.com/slorber)) + - [#4803](https://github.com/facebook/docusaurus/pull/4803) docs(v2): Add i18n tag and fix typo ([@HunteRoi](https://github.com/HunteRoi)) + - [#4786](https://github.com/facebook/docusaurus/pull/4786) docs(v2): Add tinaeldevresse.eu to Docusaurus' gallery ([@HunteRoi](https://github.com/HunteRoi)) + - [#4780](https://github.com/facebook/docusaurus/pull/4780) docs(v2): remove docs for alpha 71 + 72 ([@slorber](https://github.com/slorber)) + - [#4779](https://github.com/facebook/docusaurus/pull/4779) docs(v2): beta blog post edits ([@slorber](https://github.com/slorber)) +- `docusaurus-init` + - [#4973](https://github.com/facebook/docusaurus/pull/4973) docs(v2): replace `diff` codeblocks with line highlight ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#4756](https://github.com/facebook/docusaurus/pull/4756) docs(v2): Docusaurus 2 beta blog post ([@slorber](https://github.com/slorber)) + +#### :house: Internal + +- Other + - [#4994](https://github.com/facebook/docusaurus/pull/4994) misc: more issue template improvements ([@slorber](https://github.com/slorber)) + - [#4951](https://github.com/facebook/docusaurus/pull/4951) misc: disable google-gtag plugin in Netlify deploys ([@lex111](https://github.com/lex111)) + - [#4901](https://github.com/facebook/docusaurus/pull/4901) misc: optimize showcase images ([@lex111](https://github.com/lex111)) + - [#4897](https://github.com/facebook/docusaurus/pull/4897) chore: fail CI if yarn.lock is modified on install ([@slorber](https://github.com/slorber)) + - [#4858](https://github.com/facebook/docusaurus/pull/4858) chore(v2): add external link to community sidebar ([@lex111](https://github.com/lex111)) + - [#4889](https://github.com/facebook/docusaurus/pull/4889) misc: issue template config typo ([@slorber](https://github.com/slorber)) + - [#4886](https://github.com/facebook/docusaurus/pull/4886) misc: add github issue template config ([@slorber](https://github.com/slorber)) + - [#4878](https://github.com/facebook/docusaurus/pull/4878) misc: improve bug report issue template ([@lex111](https://github.com/lex111)) + - [#4791](https://github.com/facebook/docusaurus/pull/4791) chore: fix canary version name ([@slorber](https://github.com/slorber)) + - [#4777](https://github.com/facebook/docusaurus/pull/4777) chore: regenerate examples on 2.0.0-beta.0 ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-migrate`, `docusaurus` + - [#4944](https://github.com/facebook/docusaurus/pull/4944) chore: lockfile cleanup ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x`, `docusaurus-init-1.x` + - [#4902](https://github.com/facebook/docusaurus/pull/4902) chore: remove docusaurus v1 from master branch (moved to docusaurus-v1 branch) ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-ideal-image` + - [#4915](https://github.com/facebook/docusaurus/pull/4915) chore(v2): bump react-waypoint from 9.0.2 to 10.1.0 ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock` + - [#4834](https://github.com/facebook/docusaurus/pull/4834) chore(v2): unlock prism-react-renderer version ([@lex111](https://github.com/lex111)) +- `docusaurus-cssnano-preset`, `docusaurus` + - [#4833](https://github.com/facebook/docusaurus/pull/4833) chore(v2): bump cssnano packages ([@lex111](https://github.com/lex111)) +- `docusaurus-cssnano-preset`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-debug`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#4816](https://github.com/facebook/docusaurus/pull/4816) chore(v2): upgrade dependencies ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#4790](https://github.com/facebook/docusaurus/pull/4790) chore(v2): TypeScript, use isolatedModules ([@slorber](https://github.com/slorber)) + +#### Committers: 31 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Arthur ([@ArtFlag](https://github.com/ArtFlag)) +- Ben Rometsch ([@dabeeeenster](https://github.com/dabeeeenster)) +- Christopher Hsieh ([@Christopher-Hsieh](https://github.com/Christopher-Hsieh)) +- Fardeen Panjwani ([@wise-introvert](https://github.com/wise-introvert)) +- Joel ([@Joelpo](https://github.com/Joelpo)) +- Jon Barker ([@jonbarker68](https://github.com/jonbarker68)) +- Jonathan Mazin ([@jmazin](https://github.com/jmazin)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Lior Heber ([@liorheber](https://github.com/liorheber)) +- Louis Gallet ([@l0u1sg](https://github.com/l0u1sg)) +- Louis Grenard ([@louistiti](https://github.com/louistiti)) +- Lucas Correia ([@tsirlucas](https://github.com/tsirlucas)) +- Nam Hoang Le ([@nam-hle](https://github.com/nam-hle)) +- Pablo Vidal ([@limkinZero](https://github.com/limkinZero)) +- Pedro Queiroz ([@pmqueiroz](https://github.com/pmqueiroz)) +- Pranab Das ([@pranabdas](https://github.com/pranabdas)) +- Pratyay Banerjee ([@Neilblaze](https://github.com/Neilblaze)) +- PsychTech ([@PsychTechApS](https://github.com/PsychTechApS)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tinaël Devresse ([@HunteRoi](https://github.com/HunteRoi)) +- [@Massibian](https://github.com/Massibian) +- [@antonygibbs](https://github.com/antonygibbs) +- [@besemuna](https://github.com/besemuna) +- [@e271828-](https://github.com/e271828-) +- [@fgatti675](https://github.com/fgatti675) +- [@nirtamir2](https://github.com/nirtamir2) +- [@silva-nick](https://github.com/silva-nick) +- mg ([@tiny-dancer](https://github.com/tiny-dancer)) +- phwt.smwt ([@phwt](https://github.com/phwt)) + +## 2.0.0-beta.0 (2021-05-12) + +Read the [2.0.0 beta blog post](https://docusaurus.io/blog/2021/05/12/announcing-docusaurus-two-beta)! + +**Note**: this first beta release does not contain any new major feature. We are removing the alpha label, as we are confident Docusaurus 2 is stable enough. + +#### :rocket: New Feature + +- `docusaurus-theme-classic` + - [#4762](https://github.com/facebook/docusaurus/pull/4762) feat(v2): add es translations for docusaurus-theme-classic ([@rodmoreno](https://github.com/rodmoreno)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#4750](https://github.com/facebook/docusaurus/pull/4750) fix(v2): improve french translation for theme-classic ([@forresst](https://github.com/forresst)) +- `docusaurus-mdx-loader`, `docusaurus-utils` + - [#4736](https://github.com/facebook/docusaurus/pull/4736) fix(v2): fix encoding of markdown image/file inline file-loaders ([@slorber](https://github.com/slorber)) +- `docusaurus-utils` + - [#4735](https://github.com/facebook/docusaurus/pull/4735) fix(v2): markdown title parser should ignore all forms of MDX import statements ([@nam-hle](https://github.com/nam-hle)) + - [#4729](https://github.com/facebook/docusaurus/pull/4729) fix(v2): optimize markdown parser regex (Closes [#4726](https://github.com/facebook/docusaurus/issues/4726)) ([@nam-hle](https://github.com/nam-hle)) + +#### :memo: Documentation + +- [#4770](https://github.com/facebook/docusaurus/pull/4770) docs(v2): Improve intro doc ([@slorber](https://github.com/slorber)) +- [#4773](https://github.com/facebook/docusaurus/pull/4773) docs(v2): fix i18n doc: bad i18n page plugin path in code sample ([@KostyaTretyak](https://github.com/KostyaTretyak)) +- [#4758](https://github.com/facebook/docusaurus/pull/4758) docs(v2): add browsers support documentation ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#4757](https://github.com/facebook/docusaurus/pull/4757) docs(v2): Add Netdata to showcase ([@joelhans](https://github.com/joelhans)) +- [#4754](https://github.com/facebook/docusaurus/pull/4754) docs(v2): fix Jest showcase screenshot ([@slorber](https://github.com/slorber)) +- [#4747](https://github.com/facebook/docusaurus/pull/4747) docs(v2): Update showcase page ([@slorber](https://github.com/slorber)) +- [#4734](https://github.com/facebook/docusaurus/pull/4734) docs(v2): Added MediaMachine.io to showcase ([@gianu](https://github.com/gianu)) +- [#4731](https://github.com/facebook/docusaurus/pull/4731) docs(v2): add CodeYourFuture to showcase ([@ChrisOwen101](https://github.com/ChrisOwen101)) +- [#4703](https://github.com/facebook/docusaurus/pull/4703) docs(v2): specify google-analytics and gtag plugins ([@yiliansource](https://github.com/yiliansource)) +- [#4727](https://github.com/facebook/docusaurus/pull/4727) docs(v2): fix doc lint ([@slorber](https://github.com/slorber)) +- [#4725](https://github.com/facebook/docusaurus/pull/4725) docs(v2): emphasize subset of markdown supported languages ([@Josh-Cena](https://github.com/Josh-Cena)) +- [#4711](https://github.com/facebook/docusaurus/pull/4711) docs(v2): showcase personal site evantay ([@DigiPie](https://github.com/DigiPie)) + +#### :house: Internal + +- [#4746](https://github.com/facebook/docusaurus/pull/4746) chore(v2): attempt to fix crowdin dl again ([@slorber](https://github.com/slorber)) +- [#4743](https://github.com/facebook/docusaurus/pull/4743) chore(v2): fix prod deployment due to bad image path ([@slorber](https://github.com/slorber)) +- [#4740](https://github.com/facebook/docusaurus/pull/4740) chore(v2): delay i18n-staging deployment to avoid Crowdin 409 errors ([@slorber](https://github.com/slorber)) +- [#4739](https://github.com/facebook/docusaurus/pull/4739) chore(v2): Fix Crowdin 409 issues in CI ([@slorber](https://github.com/slorber)) + +#### Committers: 11 + +- Chris Owen ([@ChrisOwen101](https://github.com/ChrisOwen101)) +- Evan ([@DigiPie](https://github.com/DigiPie)) +- Forresst ([@forresst](https://github.com/forresst)) +- Ian Hornik ([@yiliansource](https://github.com/yiliansource)) +- Joel Hans ([@joelhans](https://github.com/joelhans)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Nam Hoang Le ([@nam-hle](https://github.com/nam-hle)) +- Rodrigo Moreno ([@rodmoreno](https://github.com/rodmoreno)) +- Sergio Rafael Gianazza ([@gianu](https://github.com/gianu)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Костя Третяк ([@KostyaTretyak](https://github.com/KostyaTretyak)) + +## 2.0.0-alpha.75 (2021-04-30) + +#### :boom: Breaking Change + +- `docusaurus-cssnano-preset`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus`, `lqip-loader` + - [#4089](https://github.com/facebook/docusaurus/pull/4089) feat(v2): Webpack 5, PostCSS 8 ([@RDIL](https://github.com/RDIL)) + +#### :memo: Documentation + +- [#4704](https://github.com/facebook/docusaurus/pull/4704) docs(v2): showcase meli ([@gempain](https://github.com/gempain)) +- [#4699](https://github.com/facebook/docusaurus/pull/4699) docs(v2): Add Kosko to showcase ([@tommy351](https://github.com/tommy351)) + +#### Committers: 4 + +- Geoffroy Empain ([@gempain](https://github.com/gempain)) +- Reece Dunham ([@RDIL](https://github.com/RDIL)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tommy Chen ([@tommy351](https://github.com/tommy351)) + +## 2.0.0-alpha.74 (2021-04-27) + +#### :rocket: New Feature + +- Other + - [#4515](https://github.com/facebook/docusaurus/pull/4515) feat(v2): add tag filters to showcase page ([@lisa761](https://github.com/lisa761)) +- `docusaurus-plugin-content-docs` + - [#4658](https://github.com/facebook/docusaurus/pull/4658) feat(v2): allow user to customize/enhance the default sidebar items generator ([@slorber](https://github.com/slorber)) + - [#4655](https://github.com/facebook/docusaurus/pull/4655) feat(v2): docs, make numberPrefixParser configurable, better defaults, minor breaking-changes ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils`, `docusaurus` + - [#4688](https://github.com/facebook/docusaurus/pull/4688) fix(v2): fix title logic (meta vs heading) + ignore fixed anchor id syntax ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#4689](https://github.com/facebook/docusaurus/pull/4689) chore(v2): update infima to alpha 23 ([@slorber](https://github.com/slorber)) + - [#4667](https://github.com/facebook/docusaurus/pull/4667) fix(v2): Unbreak blog post title by handling title fallback in `LayoutHead` ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-plugin-content-docs` + - [#4687](https://github.com/facebook/docusaurus/pull/4687) fix(v2): accept empty/null custom_edit_url docs frontmatter for retrocompat ([@slorber](https://github.com/slorber)) + - [#4651](https://github.com/facebook/docusaurus/pull/4651) fix(v2): sidebar autogen from subfolder should read category metadata correctly ([@slorber](https://github.com/slorber)) + - [#4629](https://github.com/facebook/docusaurus/pull/4629) fix(v2): fix validation rejecting admonitions false ([@kazk](https://github.com/kazk)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils-validation` + - [#4654](https://github.com/facebook/docusaurus/pull/4654) fix(v2): fix too strict markdown frontmatter validation ([@johnnyreilly](https://github.com/johnnyreilly)) +- `docusaurus-utils` + - [#4646](https://github.com/facebook/docusaurus/pull/4646) fix(v2): ignore imports when h1 heading parsing ([@lex111](https://github.com/lex111)) + - [#4641](https://github.com/facebook/docusaurus/pull/4641) fix(v2): parse headings directly after h1 properly ([@lex111](https://github.com/lex111)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#4682](https://github.com/facebook/docusaurus/pull/4682) refactor(v2): align external icon on right ([@lex111](https://github.com/lex111)) + +#### :memo: Documentation + +- [#4496](https://github.com/facebook/docusaurus/pull/4496) docs(v2): Add Qovery to deployment doc ([@arnaudjnn](https://github.com/arnaudjnn)) +- [#4680](https://github.com/facebook/docusaurus/pull/4680) docs(v2): Fix urls in deployment.md ([@luism3861](https://github.com/luism3861)) +- [#4668](https://github.com/facebook/docusaurus/pull/4668) docs(v2): Add Hostman to deployment doc ([@alena-ko](https://github.com/alena-ko)) +- [#4676](https://github.com/facebook/docusaurus/pull/4676) docs(v2): Add Daily Digest - COVID-19 IN FRANCE to showcase ([@MisterFISHUP](https://github.com/MisterFISHUP)) +- [#4643](https://github.com/facebook/docusaurus/pull/4643) docs(v2): Fix typo in installation.md ([@react-learner](https://github.com/react-learner)) +- [#4649](https://github.com/facebook/docusaurus/pull/4649) docs(v2): Add new showcase user ([@JeremyDolle](https://github.com/JeremyDolle)) + +#### :house: Internal + +- Other + - [#4670](https://github.com/facebook/docusaurus/pull/4670) chore: add some redirects to v1.docusaurus.io ([@slorber](https://github.com/slorber)) +- `docusaurus-init` + - [#4631](https://github.com/facebook/docusaurus/pull/4631) chore(v2): update examples to use alpha73 ([@slorber](https://github.com/slorber)) + +#### Committers: 12 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Arnaud Jeannin ([@arnaudjnn](https://github.com/arnaudjnn)) +- DOLLE ([@JeremyDolle](https://github.com/JeremyDolle)) +- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) +- Lisa Chandra ([@lisa761](https://github.com/lisa761)) +- Luis Medina Huerta ([@luism3861](https://github.com/luism3861)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tommy ([@react-learner](https://github.com/react-learner)) +- [@MisterFISHUP](https://github.com/MisterFISHUP) +- [@alena-ko](https://github.com/alena-ko) +- kazk ([@kazk](https://github.com/kazk)) + +## 2.0.0-alpha.73 (2021-04-16) + +#### :rocket: New Feature + +- `docusaurus-theme-classic` + - [#4624](https://github.com/facebook/docusaurus/pull/4624) feat(v2): Add Filipino default translations to theme ([@gumacahin](https://github.com/gumacahin)) + - [#4596](https://github.com/facebook/docusaurus/pull/4596) feat(v2): theme default translations hindi ([@lisa761](https://github.com/lisa761)) + - [#4536](https://github.com/facebook/docusaurus/pull/4536) feat(v2): add pt-PT translations for docusaurus-theme-classic ([@tiago-rr](https://github.com/tiago-rr)) + - [#4525](https://github.com/facebook/docusaurus/pull/4525) feat(v2): add Brazilian Portuguese translation for docusaurus-theme-classic ([@thiagog3](https://github.com/thiagog3)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#4511](https://github.com/facebook/docusaurus/pull/4511) feat(v2): add unique page/wrapper className to each theme pages ([@ShinteiMai](https://github.com/ShinteiMai)) +- `docusaurus-init`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#4582](https://github.com/facebook/docusaurus/pull/4582) feat(v2): auto-generated sidebars, frontmatter-less sites ([@slorber](https://github.com/slorber)) +- `docusaurus-types`, `docusaurus` + - [#4545](https://github.com/facebook/docusaurus/pull/4545) feat(v2): docusaurus deploy: ability to configure port in git url ([@talesporto](https://github.com/talesporto)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils` + - [#4590](https://github.com/facebook/docusaurus/pull/4590) feat(v2): various markdown string parsing improvements/fixes ([@slorber](https://github.com/slorber)) + - [#4485](https://github.com/facebook/docusaurus/pull/4485) feat(v2): frontmatter-less: read first heading as title and use it in front-matter ([@armano2](https://github.com/armano2)) +- `docusaurus-utils` + - [#4581](https://github.com/facebook/docusaurus/pull/4581) feat(v2): default theme translations: locale "pt" should load "pt-BR" translations ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs` + - [#4495](https://github.com/facebook/docusaurus/pull/4495) feat(v2): include frontmatter in loadedContent doc metadatas ([@kaytwo](https://github.com/kaytwo)) + - [#4500](https://github.com/facebook/docusaurus/pull/4500) feat(v2): provide doc sidebar_label through sidebars.js ([@besemuna](https://github.com/besemuna)) +- `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#4449](https://github.com/facebook/docusaurus/pull/4449) feat(v2): infer default i18n locale config from locale code ([@slorber](https://github.com/slorber)) + +#### :boom: Breaking Change + +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#4619](https://github.com/facebook/docusaurus/pull/4619) refactor(v2): rename class main-docs-wrapper to docs-wrapper ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#4582](https://github.com/facebook/docusaurus/pull/4582) feat(v2): auto-generated sidebars, frontmatter-less sites ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#4627](https://github.com/facebook/docusaurus/pull/4627) chore(v2): update Infima to alpha.22 ([@slorber](https://github.com/slorber)) + - [#4621](https://github.com/facebook/docusaurus/pull/4621) fix(v2): center align content if no sidebar exists ([@lex111](https://github.com/lex111)) + - [#4620](https://github.com/facebook/docusaurus/pull/4620) fix(v2): restore toggle responsive sidebar button ([@lex111](https://github.com/lex111)) + - [#4598](https://github.com/facebook/docusaurus/pull/4598) fix(v2): render escaped HTML entities inside code properly ([@lex111](https://github.com/lex111)) + - [#4554](https://github.com/facebook/docusaurus/pull/4554) fix: DocNavbarItem error message ([@serut](https://github.com/serut)) + - [#4468](https://github.com/facebook/docusaurus/pull/4468) fix(v2): select correct tab when items are incorrectly ordered ([@armano2](https://github.com/armano2)) + - [#4461](https://github.com/facebook/docusaurus/pull/4461) fix(v2): Fix i18n staging deployment due to json typo ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#4541](https://github.com/facebook/docusaurus/pull/4541) fix(v2): fix code block title parsing, support multiple metastring attributes ([@duanwilliam](https://github.com/duanwilliam)) + - [#4600](https://github.com/facebook/docusaurus/pull/4600) fix(v2): use page title from config if not set ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#4501](https://github.com/facebook/docusaurus/pull/4501) fix(v2): fail-safe usage of browser storage (localStorage/sessionStorage) when access is denied ([@jknoxville](https://github.com/jknoxville)) +- `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` + - [#4593](https://github.com/facebook/docusaurus/pull/4593) fix(v2): i18n perf issue: getTranslationFile() should not load content again ([@slorber](https://github.com/slorber)) +- Other + - [#4574](https://github.com/facebook/docusaurus/pull/4574) fix(v2): examples should use Node 14 by default on CodeSandbox + regen with alpha72 ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#4547](https://github.com/facebook/docusaurus/pull/4547) feat(v2) : use symbols to denote swizzle safety ([@besemuna](https://github.com/besemuna)) + - [#4575](https://github.com/facebook/docusaurus/pull/4575) fix(v2): fix i18n isLastLocale bug preventing docusaurus from building some locales ([@slorber](https://github.com/slorber)) + - [#4506](https://github.com/facebook/docusaurus/pull/4506) fix(v2): remove no longer used postcss-present-env from dependencies ([@armano2](https://github.com/armano2)) + - [#4444](https://github.com/facebook/docusaurus/pull/4444) fix(v2): Fix writeHeadingIds on Windows due to non-posix paths ([@slorber](https://github.com/slorber)) +- `docusaurus-utils` + - [#4507](https://github.com/facebook/docusaurus/pull/4507) fix(v2): do not warn about duplicated title for pages ([@armano2](https://github.com/armano2)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus` + - [#4466](https://github.com/facebook/docusaurus/pull/4466) fix(v2): i18n fixes ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus` + - [#4459](https://github.com/facebook/docusaurus/pull/4459) fix(v2): Export Joi from validation-utils package ([@slorber](https://github.com/slorber)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#4626](https://github.com/facebook/docusaurus/pull/4626) refactor(v2): toggleResponsiveSidebar => more stable callback ([@slorber](https://github.com/slorber)) + - [#4617](https://github.com/facebook/docusaurus/pull/4617) refactor(v2): simplify and optimize sidebar ([@slorber](https://github.com/slorber)) + - [#4608](https://github.com/facebook/docusaurus/pull/4608) refactor(v2): replace react-toggle with own implementation ([@lex111](https://github.com/lex111)) + - [#4601](https://github.com/facebook/docusaurus/pull/4601) refactor(v2): increase heading anchor offset ([@lex111](https://github.com/lex111)) + - [#4467](https://github.com/facebook/docusaurus/pull/4467) refactor(v2): add missing types to theme-classic useTheme ([@armano2](https://github.com/armano2)) + - [#4448](https://github.com/facebook/docusaurus/pull/4448) polish(v2): Add german translations ([@miku86](https://github.com/miku86)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#4619](https://github.com/facebook/docusaurus/pull/4619) refactor(v2): rename class main-docs-wrapper to docs-wrapper ([@slorber](https://github.com/slorber)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus` + - [#4451](https://github.com/facebook/docusaurus/pull/4451) refactor(v2): correct client types and type aliases ([@armano2](https://github.com/armano2)) +- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#4450](https://github.com/facebook/docusaurus/pull/4450) chore(v2): Fix more linter warnings ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` + - [#4442](https://github.com/facebook/docusaurus/pull/4442) chore(v2): Fix linter warnings ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#4375](https://github.com/facebook/docusaurus/pull/4375) refactor(v2): TS config update: reduce the size of npm modules ([@RDIL](https://github.com/RDIL)) + +#### :memo: Documentation + +- Other + - [#4616](https://github.com/facebook/docusaurus/pull/4616) docs(v2): add showcase: kubevela ([@sunny0826](https://github.com/sunny0826)) + - [#4612](https://github.com/facebook/docusaurus/pull/4612) docs(v2): Added IntelAGENT website to showcase. ([@akepecs](https://github.com/akepecs)) + - [#4609](https://github.com/facebook/docusaurus/pull/4609) docs(v2): add clarity to tip in versioned using-themes page ([@dickwyn](https://github.com/dickwyn)) + - [#4606](https://github.com/facebook/docusaurus/pull/4606) docs(v2): heading typo ([@arturcarvalho](https://github.com/arturcarvalho)) + - [#4604](https://github.com/facebook/docusaurus/pull/4604) docs(v2): add clarity to tip in using-themes page ([@dickwyn](https://github.com/dickwyn)) + - [#4602](https://github.com/facebook/docusaurus/pull/4602) docs(v2): Add "PptxGenJS" to showcase ([@gitbrent](https://github.com/gitbrent)) + - [#4599](https://github.com/facebook/docusaurus/pull/4599) docs(v2): i18n site: enable ko + zh-CN locales ([@slorber](https://github.com/slorber)) + - [#4595](https://github.com/facebook/docusaurus/pull/4595) docs(v2): fix typo theme-configuration.md ([@forresst](https://github.com/forresst)) + - [#4594](https://github.com/facebook/docusaurus/pull/4594) docs(v2): Include docusaurus-protobuffet to community plugins ([@AnthonyBobsin](https://github.com/AnthonyBobsin)) + - [#4558](https://github.com/facebook/docusaurus/pull/4558) docs(v2): fixed broken link in i18n-tutorial.md ([@covalentbond](https://github.com/covalentbond)) + - [#4573](https://github.com/facebook/docusaurus/pull/4573) docs: update README badges ([@slorber](https://github.com/slorber)) + - [#4559](https://github.com/facebook/docusaurus/pull/4559) docs(v2): fixed the directory of index.js ([@covalentbond](https://github.com/covalentbond)) + - [#4568](https://github.com/facebook/docusaurus/pull/4568) docs(v2): add social-embed to showcase ([@tony](https://github.com/tony)) + - [#4570](https://github.com/facebook/docusaurus/pull/4570) docs(v2): Add Redis Labs Developer Site to docusaurus showcase page ([@ajeetraina](https://github.com/ajeetraina)) + - [#4543](https://github.com/facebook/docusaurus/pull/4543) docs(v2): fix run-on sentence ([@duanwilliam](https://github.com/duanwilliam)) + - [#4539](https://github.com/facebook/docusaurus/pull/4539) docs(v2): fix typo deployment.mdx ([@forresst](https://github.com/forresst)) + - [#4538](https://github.com/facebook/docusaurus/pull/4538) Add Tuist to the list of projects that use Docusaurus ([@pepibumur](https://github.com/pepibumur)) + - [#4531](https://github.com/facebook/docusaurus/pull/4531) docs(v2): remove duplicate line on v1 docs ([@loozhengyuan](https://github.com/loozhengyuan)) + - [#4524](https://github.com/facebook/docusaurus/pull/4524) docs(v2): config for self-hosted docsearch crawler ([@loozhengyuan](https://github.com/loozhengyuan)) + - [#4526](https://github.com/facebook/docusaurus/pull/4526) docs(v2): fix markdown headings level 4 ([@forresst](https://github.com/forresst)) + - [#4505](https://github.com/facebook/docusaurus/pull/4505) docs(v2): add more links to v1: announcementBar, versionDropdown, homepage ([@slorber](https://github.com/slorber)) + - [#4497](https://github.com/facebook/docusaurus/pull/4497) docs: fix link to issue template ([@forresst](https://github.com/forresst)) + - [#4481](https://github.com/facebook/docusaurus/pull/4481) docs(v2): fix grammar and improve wording ([@aehrea](https://github.com/aehrea)) + - [#4472](https://github.com/facebook/docusaurus/pull/4472) docs(v2): fixed broken link in sidebar documentation ([@covalentbond](https://github.com/covalentbond)) + - [#4470](https://github.com/facebook/docusaurus/pull/4470) docs(v2): Add missing i18n docs: API lifecycles + Crowdin migration guide ([@slorber](https://github.com/slorber)) + - [#4460](https://github.com/facebook/docusaurus/pull/4460) docs(v2): use explicit heading IDs ([@lex111](https://github.com/lex111)) + - [#4446](https://github.com/facebook/docusaurus/pull/4446) docs(v2): Add blog.johnnyreilly.com to showcase ([@johnnyreilly](https://github.com/johnnyreilly)) + - [#4430](https://github.com/facebook/docusaurus/pull/4430) docs(v2): add Deploy with QuandCDN ([@steveworley](https://github.com/steveworley)) + - [#4441](https://github.com/facebook/docusaurus/pull/4441) docs(v2): add stylable site to users showcase list ([@tomrav](https://github.com/tomrav)) +- `docusaurus-init` + - [#4561](https://github.com/facebook/docusaurus/pull/4561) docs(v2): add a missing slug from the initial template ([@Foxeye-Rinx](https://github.com/Foxeye-Rinx)) + - [#4560](https://github.com/facebook/docusaurus/pull/4560) docs(v2): fixed typos ([@covalentbond](https://github.com/covalentbond)) + - [#4546](https://github.com/facebook/docusaurus/pull/4546) docs(v2): add a missing "export" from the initial template ([@Foxeye-Rinx](https://github.com/Foxeye-Rinx)) + - [#4320](https://github.com/facebook/docusaurus/pull/4320) feat(v2): Improve the initial templates #4302 ([@besemuna](https://github.com/besemuna)) +- `docusaurus-migrate`, `docusaurus` + - [#4479](https://github.com/facebook/docusaurus/pull/4479) docs(v2): fixed typos ([@covalentbond](https://github.com/covalentbond)) + +#### :house: Internal + +- `docusaurus-theme-classic` + - [#4627](https://github.com/facebook/docusaurus/pull/4627) chore(v2): update Infima to alpha.22 ([@slorber](https://github.com/slorber)) + - [#4463](https://github.com/facebook/docusaurus/pull/4463) chore: fb json header commit typo ([@slorber](https://github.com/slorber)) +- Other + - [#4613](https://github.com/facebook/docusaurus/pull/4613) chore(v2): fix yarn2 end2end test by using lerna publish --exact ([@slorber](https://github.com/slorber)) + - [#4611](https://github.com/facebook/docusaurus/pull/4611) chore(v2): CI: do not build all locales when monitoring build time perf ([@slorber](https://github.com/slorber)) + - [#4486](https://github.com/facebook/docusaurus/pull/4486) ci: enable yarn install cache ([@armano2](https://github.com/armano2)) + - [#4508](https://github.com/facebook/docusaurus/pull/4508) ci: change default actions timeout from 6h to 30m ([@armano2](https://github.com/armano2)) + - [#4488](https://github.com/facebook/docusaurus/pull/4488) chore(v2): fix typo in classic init template ([@clarus](https://github.com/clarus)) + - [#4471](https://github.com/facebook/docusaurus/pull/4471) chore: fix GH actions lint problem matchers issue in PR ([@slorber](https://github.com/slorber)) + - [#4458](https://github.com/facebook/docusaurus/pull/4458) chore(v2): enable staging locales: ko ja ([@slorber](https://github.com/slorber)) + - [#4457](https://github.com/facebook/docusaurus/pull/4457) chore(v2): remove docs for alpha v70 ([@lex111](https://github.com/lex111)) + - [#4452](https://github.com/facebook/docusaurus/pull/4452) chore(v2): update typescript-eslint to v4.18.0 ([@armano2](https://github.com/armano2)) +- `docusaurus` + - [#4516](https://github.com/facebook/docusaurus/pull/4516) ci(v2): fail CI if build takes too much time ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#4490](https://github.com/facebook/docusaurus/pull/4490) chore: rename v2.docusaurus.io urls after domain switch + redirect + cleanups ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x` + - [#4475](https://github.com/facebook/docusaurus/pull/4475) chore: prepare v1-v2 domain switch ([@slorber](https://github.com/slorber)) + - [#4447](https://github.com/facebook/docusaurus/pull/4447) chore: simplify CI setup ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x`, `docusaurus-init` + - [#4453](https://github.com/facebook/docusaurus/pull/4453) chore(v2): migrate babel-eslint to @babel/eslint-parser ([@armano2](https://github.com/armano2)) +- `docusaurus-utils-validation` + - [#4464](https://github.com/facebook/docusaurus/pull/4464) chore(v2): Joi cyclic dep warning ([@slorber](https://github.com/slorber)) +- `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` + - [#4462](https://github.com/facebook/docusaurus/pull/4462) chore: json files should be linted ([@slorber](https://github.com/slorber)) + +#### :running_woman: Performance + +- `docusaurus-theme-classic` + - [#4626](https://github.com/facebook/docusaurus/pull/4626) refactor(v2): toggleResponsiveSidebar => more stable callback ([@slorber](https://github.com/slorber)) + - [#4603](https://github.com/facebook/docusaurus/pull/4603) perf(v2): avoid rerender of sidebar items while scrolling ([@lex111](https://github.com/lex111)) + - [#4473](https://github.com/facebook/docusaurus/pull/4473) perf(v2): reduce amount of component updates while scrolling ([@armano2](https://github.com/armano2)) + +#### Committers: 37 + +- Ajeet Singh Raina, Docker Captain, RedisLabs ([@ajeetraina](https://github.com/ajeetraina)) +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Anthony Bobsin ([@AnthonyBobsin](https://github.com/AnthonyBobsin)) +- Arijit Kundu ([@covalentbond](https://github.com/covalentbond)) +- Armano ([@armano2](https://github.com/armano2)) +- Artur Carvalho ([@arturcarvalho](https://github.com/arturcarvalho)) +- Brent Ely ([@gitbrent](https://github.com/gitbrent)) +- Chris Kanich ([@kaytwo](https://github.com/kaytwo)) +- Dennis Thompson ([@atomicpages](https://github.com/atomicpages)) +- Dick Wyn Yong ([@dickwyn](https://github.com/dickwyn)) +- Forresst ([@forresst](https://github.com/forresst)) +- Guillaume Claret ([@clarus](https://github.com/clarus)) +- John Knox ([@jknoxville](https://github.com/jknoxville)) +- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) +- Lisa Chandra ([@lisa761](https://github.com/lisa761)) +- Lucas Alves ([@lucalves](https://github.com/lucalves)) +- Marco Enrico ([@gumacahin](https://github.com/gumacahin)) +- Pedro Piñera Buendía ([@pepibumur](https://github.com/pepibumur)) +- Reece Dunham ([@RDIL](https://github.com/RDIL)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Steve ([@steveworley](https://github.com/steveworley)) +- Steven Hansel ([@ShinteiMai](https://github.com/ShinteiMai)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tales Porto ([@talesporto](https://github.com/talesporto)) +- Thiago Sciotta ([@thiagog3](https://github.com/thiagog3)) +- Tiago Ribeiro ([@tiago-rr](https://github.com/tiago-rr)) +- Tom Raviv ([@tomrav](https://github.com/tomrav)) +- Tony Narlock ([@tony](https://github.com/tony)) +- ZhengYuan Loo ([@loozhengyuan](https://github.com/loozhengyuan)) +- [@Foxeye-Rinx](https://github.com/Foxeye-Rinx) +- [@aehrea](https://github.com/aehrea) +- [@akepecs](https://github.com/akepecs) +- [@besemuna](https://github.com/besemuna) +- [@duanwilliam](https://github.com/duanwilliam) +- [@miku86](https://github.com/miku86) +- [@serut](https://github.com/serut) +- guoxudong ([@sunny0826](https://github.com/sunny0826)) + +## 2.0.0-alpha.72 (2021-03-16) + +#### :boom: Breaking Change + +Starting with this release for a proper work of i18n functionality, you need to either use Node v14+ or in case of using earlier version of Node.js install [`full-icu` package](https://www.npmjs.com/package/full-icu) and set `NODE_ICU_DATA` environment variable in your npm scripts, for example: + +```json +"scripts": { + "start": "cross-env NODE_ICU_DATA=node_modules/full-icu docusaurus start" +} +``` + +#### :rocket: New Feature + +- `docusaurus-init` + - [#4302](https://github.com/facebook/docusaurus/pull/4302) feat(v2): Improve the initial templates ([@ShinteiMai](https://github.com/ShinteiMai)) +- `docusaurus-theme-classic` + - [#4390](https://github.com/facebook/docusaurus/pull/4390) feat(v2): Add korean default translations ([@koko8829](https://github.com/koko8829)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#4429](https://github.com/facebook/docusaurus/pull/4429) chore(v2): upgrade Infima to v0.2.0-alpha.21 ([@lex111](https://github.com/lex111)) + - [#4428](https://github.com/facebook/docusaurus/pull/4428) fix(v2): allow using pre tag in Markdown directly ([@lex111](https://github.com/lex111)) + - [#4381](https://github.com/facebook/docusaurus/pull/4381) fix(v2): specify proper TS path in classic theme ([@lex111](https://github.com/lex111)) + - [#4383](https://github.com/facebook/docusaurus/pull/4383) fix(v2): set theme color mode for SSR ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-pwa` + - [#4424](https://github.com/facebook/docusaurus/pull/4424) fix(v2): add missing peer dep on @babel/core ([@SimenB](https://github.com/SimenB)) + - [#4377](https://github.com/facebook/docusaurus/pull/4377) fix(v2): PWA issues + improve docs ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#4407](https://github.com/facebook/docusaurus/pull/4407) fix(v2): broken link checker should not report false positives when using encoded chars ([@Harvtronix](https://github.com/Harvtronix)) +- Other + - [#4410](https://github.com/facebook/docusaurus/pull/4410) fix(v1): Fix v1 site deployment with Crowdin again... ([@slorber](https://github.com/slorber)) + - [#4396](https://github.com/facebook/docusaurus/pull/4396) fix(v1): Temp fix v1 site deployment: fail-safe on Crowdin upload translations error ([@slorber](https://github.com/slorber)) + - [#4395](https://github.com/facebook/docusaurus/pull/4395) fix(v1): fix v1 site deploy issues ([@slorber](https://github.com/slorber)) + +#### :nail_care: Polish + +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus` + - [#4418](https://github.com/facebook/docusaurus/pull/4418) refactor(v2): correct plugin types ([@armano2](https://github.com/armano2)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` + - [#4405](https://github.com/facebook/docusaurus/pull/4405) refactor(v2): i18n cleanups / refactors ([@longlho](https://github.com/longlho)) +- `docusaurus-module-type-aliases` + - [#4387](https://github.com/facebook/docusaurus/pull/4387) refactor(v2): add ExecutionEnvironment, BrowserOnly, isInternalUrl to type aliases ([@armano2](https://github.com/armano2)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils` + - [#4402](https://github.com/facebook/docusaurus/pull/4402) refactor(v2): merge linkify function used in blog and docs and align properties ([@armano2](https://github.com/armano2)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-utils-validation`, `docusaurus` + - [#4382](https://github.com/facebook/docusaurus/pull/4382) refactor(v2): correct some of type errors reported by eslint ([@armano2](https://github.com/armano2)) +- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#4385](https://github.com/facebook/docusaurus/pull/4385) refactor(v2): add missing theme-classic types ([@armano2](https://github.com/armano2)) + +#### :memo: Documentation + +- [#4416](https://github.com/facebook/docusaurus/pull/4416) docs(v2): add Realtime Web Applications Workshop to showcase ([@lowenhere](https://github.com/lowenhere)) +- [#4408](https://github.com/facebook/docusaurus/pull/4408) docs(v2): add gladysassistant.com to showcase ([@Pierre-Gilles](https://github.com/Pierre-Gilles)) +- [#4386](https://github.com/facebook/docusaurus/pull/4386) docs(v2): Showcase the pnpm docs ([@zkochan](https://github.com/zkochan)) +- [#4367](https://github.com/facebook/docusaurus/pull/4367) docs(v2): releasing i18n blog post ([@slorber](https://github.com/slorber)) + +#### :house: Internal + +- `docusaurus-1.x` + - [#4401](https://github.com/facebook/docusaurus/pull/4401) chore(v1): fix CircleCI v1 site deploy ([@slorber](https://github.com/slorber)) +- Other + - [#4399](https://github.com/facebook/docusaurus/pull/4399) chore(v2): upgrade example projects ([@slorber](https://github.com/slorber)) + - [#4398](https://github.com/facebook/docusaurus/pull/4398) chore(v1): trigger v1 site deploy through CI ([@slorber](https://github.com/slorber)) +- `docusaurus-utils` + - [#4384](https://github.com/facebook/docusaurus/pull/4384) chore(v2): avoid bad publish of intl-locales-supported ([@lex111](https://github.com/lex111)) + +#### Committers: 14 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Armano ([@armano2](https://github.com/armano2)) +- Harvtronix ([@Harvtronix](https://github.com/Harvtronix)) +- Joon-Ha Lee ([@koko8829](https://github.com/koko8829)) +- Leandro Oriente ([@leandrooriente](https://github.com/leandrooriente)) +- Long Ho ([@longlho](https://github.com/longlho)) +- Lowen ([@lowenhere](https://github.com/lowenhere)) +- Pierre-Gilles Leymarie ([@Pierre-Gilles](https://github.com/Pierre-Gilles)) +- Quan ([@quanengineering](https://github.com/quanengineering)) +- Simen Bekkhus ([@SimenB](https://github.com/SimenB)) +- Steven Hansel ([@ShinteiMai](https://github.com/ShinteiMai)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Zoltan Kochan ([@zkochan](https://github.com/zkochan)) +- [@Rhodanthe1116](https://github.com/Rhodanthe1116) + +## 2.0.0-alpha.71 (2021-03-09) + +#### :rocket: New Feature + +- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-utils`, `docusaurus` + - [#4222](https://github.com/facebook/docusaurus/pull/4222) feat(v2): add ability to set custom heading id ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-live-codeblock` + - [#4328](https://github.com/facebook/docusaurus/pull/4328) feat(v2): Add playgroundPosition config for live codeblock ([@tokarchyn](https://github.com/tokarchyn)) +- `docusaurus-theme-classic` + - [#4209](https://github.com/facebook/docusaurus/pull/4209) feat(v2): auto focus to tab if it is outside viewport ([@lex111](https://github.com/lex111)) + - [#4329](https://github.com/facebook/docusaurus/pull/4329) feat(v2): add arabic translation ([@3alisaki](https://github.com/3alisaki)) + - [#4325](https://github.com/facebook/docusaurus/pull/4325) feat(v2): [theme-classic] add Polish translation ([@Simek](https://github.com/Simek)) + - [#4312](https://github.com/facebook/docusaurus/pull/4312) feat(v2): Add Turkish translations for theme labels ([@caglarturali](https://github.com/caglarturali)) + - [#4271](https://github.com/facebook/docusaurus/pull/4271) feat(v2): add Farsi default translations ([@slorber](https://github.com/slorber)) + - [#4261](https://github.com/facebook/docusaurus/pull/4261) feat(v2): add icon to generic sidebar link ([@lex111](https://github.com/lex111)) + - [#4109](https://github.com/facebook/docusaurus/pull/4109) feat(v2): default canonical urls ([@slorber](https://github.com/slorber)) +- `docusaurus-types`, `docusaurus` + - [#4308](https://github.com/facebook/docusaurus/pull/4308) feat(v2): add --config option to CLI ([@longlho](https://github.com/longlho)) + - [#4185](https://github.com/facebook/docusaurus/pull/4185) feat(v2): allow extend PostCSS config ([@lex111](https://github.com/lex111)) + - [#4021](https://github.com/facebook/docusaurus/pull/4021) feat(v2): Allow plugins to consume webpack stats ([@RDIL](https://github.com/RDIL)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#4303](https://github.com/facebook/docusaurus/pull/4303) feat(v2): add japanese translations ([@ykzts](https://github.com/ykzts)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus` + - [#4295](https://github.com/facebook/docusaurus/pull/4295) feat(v2): Add Interpolate / interpolate APIs + complete theme translations ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader` + - [#4278](https://github.com/facebook/docusaurus/pull/4278) feat(v2): ability to "escape" JSX in MDX files as code blocks ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` + - [#4232](https://github.com/facebook/docusaurus/pull/4232) feat(v2): editUrl functions should receive md doc permalink ([@slorber](https://github.com/slorber)) + - [#4121](https://github.com/facebook/docusaurus/pull/4121) feat(v2): editUrl function for advanced use-cases ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#4218](https://github.com/facebook/docusaurus/pull/4218) feat(v2): support/use React v17 by default ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#4215](https://github.com/facebook/docusaurus/pull/4215) feat(v2): Add i18n default code translation bundles ([@slorber](https://github.com/slorber)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#4140](https://github.com/facebook/docusaurus/pull/4140) feat(v2): add support for RTL direction ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#4199](https://github.com/facebook/docusaurus/pull/4199) feat(v2): allow to change location of search bar ([@lex111](https://github.com/lex111)) + - [#3993](https://github.com/facebook/docusaurus/pull/3993) feat(v2): themed logo in footer ([@natac13](https://github.com/natac13)) +- `docusaurus` + - [#4198](https://github.com/facebook/docusaurus/pull/4198) feat(v2): add fonts loaders + webpack resolve.roots ([@slorber](https://github.com/slorber)) + - [#3998](https://github.com/facebook/docusaurus/pull/3998) feat(v2): Cache hashed assets to dedicated folders ([@kumaraditya303](https://github.com/kumaraditya303)) + - [#3979](https://github.com/facebook/docusaurus/pull/3979) feat(v2): better error message for invalid plugin config ([@9oelM](https://github.com/9oelM)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus` + - [#4168](https://github.com/facebook/docusaurus/pull/4168) feat(v2): Extract/translate hardcoded labels from classic theme ([@slorber](https://github.com/slorber)) +- `docusaurus-init` + - [#4098](https://github.com/facebook/docusaurus/pull/4098) feat(v2): improve templates, use JSDoc type annotation, improve `docusaurus.config.js` autocompletion ([@LittleboyHarry](https://github.com/LittleboyHarry)) +- `docusaurus-init`, `docusaurus-migrate` + - [#3986](https://github.com/facebook/docusaurus/pull/3986) feat(v2): skip dependency install on docusaurus init ([@kumaraditya303](https://github.com/kumaraditya303)) +- `docusaurus-plugin-content-docs` + - [#3949](https://github.com/facebook/docusaurus/pull/3949) feat(v2): new docs edit options: editCurrentVersion + editLocalizedDocs ([@slorber](https://github.com/slorber)) + +#### :boom: Breaking Change + +- `docusaurus-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#4223](https://github.com/facebook/docusaurus/pull/4223) chore(v2): upgrade dependencies + require Node 12 ([@lex111](https://github.com/lex111)) + +#### :bug: Bug Fix + +- `docusaurus` + - [#4366](https://github.com/facebook/docusaurus/pull/4366) fix(v2): align installed core-js version with babel config ([@armano2](https://github.com/armano2)) + - [#4345](https://github.com/facebook/docusaurus/pull/4345) fix(v2): always extract translations from site/src ([@slorber](https://github.com/slorber)) + - [#4342](https://github.com/facebook/docusaurus/pull/4342) chore(v2): bump clean-css to 5.1.1 ([@lex111](https://github.com/lex111)) + - [#4212](https://github.com/facebook/docusaurus/pull/4212) fix(v2): typo in resolve.roots ([@slorber](https://github.com/slorber)) + - [#4155](https://github.com/facebook/docusaurus/pull/4155) fix(v2): BaseUrl issue banner insertion should be prevented if JS can load ([@slorber](https://github.com/slorber)) + - [#4137](https://github.com/facebook/docusaurus/pull/4137) fix(v2): escape apostrophes in route paths ([@lex111](https://github.com/lex111)) + - [#4136](https://github.com/facebook/docusaurus/pull/4136) fix(v2): fix navigation from homepage ([@lex111](https://github.com/lex111)) + - [#4125](https://github.com/facebook/docusaurus/pull/4125) fix(v2): baseUrl help banner should not be indexed by Google / SEO ([@slorber](https://github.com/slorber)) + - [#4080](https://github.com/facebook/docusaurus/pull/4080) fix(v2): chokidar reloading debounced ([@semoal](https://github.com/semoal)) + - [#3965](https://github.com/facebook/docusaurus/pull/3965) fix(v2): fix svg loader for CSS files ([@apurvaojas](https://github.com/apurvaojas)) + - [#3943](https://github.com/facebook/docusaurus/pull/3943) fix(v2): disables all inlining in CleanCSS ([@lex111](https://github.com/lex111)) + - [#3941](https://github.com/facebook/docusaurus/pull/3941) fix(v2): fix i18n build logging. ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#4349](https://github.com/facebook/docusaurus/pull/4349) fix(v2): fix update code translations script + update some translations ([@slorber](https://github.com/slorber)) + - [#4311](https://github.com/facebook/docusaurus/pull/4311) fix(v2): fit footer in viewport when content area is too small ([@lex111](https://github.com/lex111)) + - [#4340](https://github.com/facebook/docusaurus/pull/4340) fix(v2): prevent useless blog pages to be in search results ([@slorber](https://github.com/slorber)) + - [#4274](https://github.com/facebook/docusaurus/pull/4274) fix(v2): theme classic should have lib-next prettified ([@slorber](https://github.com/slorber)) + - [#4267](https://github.com/facebook/docusaurus/pull/4267) fix(v2): Allow null as valid for title of item in footer links. ([@ben-qnimble](https://github.com/ben-qnimble)) + - [#4254](https://github.com/facebook/docusaurus/pull/4254) fix(v2): fix LTR PostCSS bug on Netlify and monorepo symlinks ([@slorber](https://github.com/slorber)) + - [#4247](https://github.com/facebook/docusaurus/pull/4247) fix(v2): make doc container full width when hidden sidebar ([@lex111](https://github.com/lex111)) + - [#4241](https://github.com/facebook/docusaurus/pull/4241) fix(v2): avoid horizontal scrolling when long lines of code ([@lex111](https://github.com/lex111)) + - [#4200](https://github.com/facebook/docusaurus/pull/4200) fix(v2): various minor bugs with location hash ([@lex111](https://github.com/lex111)) + - [#4195](https://github.com/facebook/docusaurus/pull/4195) fix(v2): restore hamburger menu ([@lex111](https://github.com/lex111)) + - [#4189](https://github.com/facebook/docusaurus/pull/4189) fix(v2): prevent click on item menu with children on mobiles ([@lex111](https://github.com/lex111)) + - [#4176](https://github.com/facebook/docusaurus/pull/4176) fix(v2): make locale dropdown accessible from keyboard ([@lex111](https://github.com/lex111)) + - [#4163](https://github.com/facebook/docusaurus/pull/4163) fix(v2): fix warning and improve styling inline TOC ([@lex111](https://github.com/lex111)) + - [#4162](https://github.com/facebook/docusaurus/pull/4162) fix(v2): make more accessible skip link ([@lex111](https://github.com/lex111)) + - [#4160](https://github.com/facebook/docusaurus/pull/4160) fix(v2): fix hreflang headers ([@slorber](https://github.com/slorber)) + - [#4147](https://github.com/facebook/docusaurus/pull/4147) fix(v2): avoid misuse section tag in blog posts ([@lex111](https://github.com/lex111)) + - [#4146](https://github.com/facebook/docusaurus/pull/4146) fix(v2): use current color for language icon ([@lex111](https://github.com/lex111)) + - [#4118](https://github.com/facebook/docusaurus/pull/4118) fix(v2): navbar dropdown subitems should be translated properly ([@slorber](https://github.com/slorber)) + - [#4011](https://github.com/facebook/docusaurus/pull/4011) fix(v2): fix accessibility issue with IconArrow ([@natac13](https://github.com/natac13)) + - [#3968](https://github.com/facebook/docusaurus/pull/3968) fix(v2): fix blog only contextual search ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#4315](https://github.com/facebook/docusaurus/pull/4315) fix(v2): make code blocks more standalone ([@lex111](https://github.com/lex111)) + - [#4277](https://github.com/facebook/docusaurus/pull/4277) fix(v2): Code blocks should be LTR by default ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-live-codeblock` + - [#4318](https://github.com/facebook/docusaurus/pull/4318) fix(v2): evaluate code in live editor on client only ([@lex111](https://github.com/lex111)) + - [#3954](https://github.com/facebook/docusaurus/pull/3954) fix(v2): allow async/await in live code editor ([@9oelM](https://github.com/9oelM)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#4339](https://github.com/facebook/docusaurus/pull/4339) fix(v2): search page results localization ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#4304](https://github.com/facebook/docusaurus/pull/4304) fix(v2): fix bad theme pluralization rules for some labels ([@slorber](https://github.com/slorber)) +- `docusaurus-cssnano-preset` + - [#4240](https://github.com/facebook/docusaurus/pull/4240) fix(v2): remove PostCSS plugin for combine duplicated selectors ([@lex111](https://github.com/lex111)) +- Other + - [#4234](https://github.com/facebook/docusaurus/pull/4234) fix(v2): fix website versions page ([@slorber](https://github.com/slorber)) + - [#4233](https://github.com/facebook/docusaurus/pull/4233) fix(v2): website editUrl should target upstream docs ([@slorber](https://github.com/slorber)) + - [#4067](https://github.com/facebook/docusaurus/pull/4067) fix(v2): Fix blog post url/date ([@slorber](https://github.com/slorber)) + - [#3952](https://github.com/facebook/docusaurus/pull/3952) docs(v2): Fix invalid json ([@oze4](https://github.com/oze4)) +- `docusaurus-theme-search-algolia` + - [#4188](https://github.com/facebook/docusaurus/pull/4188) fix(v2): prepend docsearch modal to body element ([@lex111](https://github.com/lex111)) + - [#4154](https://github.com/facebook/docusaurus/pull/4154) fix(v2): add base url to opensearch.xml ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-ideal-image` + - [#4166](https://github.com/facebook/docusaurus/pull/4166) fix(v2): ideal image assets should be served under ./assets ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#4092](https://github.com/facebook/docusaurus/pull/4092) fix(v2): fix/enhance minor i18n issues reported ([@slorber](https://github.com/slorber)) + - [#3940](https://github.com/facebook/docusaurus/pull/3940) fix(v2): i18n should not crash theme without footer ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-sitemap` + - [#4004](https://github.com/facebook/docusaurus/pull/4004) fix(v2): Fix double trailingSlash in sitemap.xml ([@ntbosscher](https://github.com/ntbosscher)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils` + - [#3970](https://github.com/facebook/docusaurus/pull/3970) fix(v2): fix multi-instance mdx loaders not sandboxed correctly ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects` + - [#3903](https://github.com/facebook/docusaurus/pull/3903) fix(v2): fix redirect toUrl (windows + trailing slash) ([@saydo17](https://github.com/saydo17)) +- `docusaurus-utils` + - [#3944](https://github.com/facebook/docusaurus/pull/3944) fix(v2): ignore style imports in excerpt ([@lex111](https://github.com/lex111)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#4371](https://github.com/facebook/docusaurus/pull/4371) refactor(v2): update Russian translation in classic theme ([@lex111](https://github.com/lex111)) + - [#4359](https://github.com/facebook/docusaurus/pull/4359) polish(v2): [theme-classic] slightly improve Japanese translation ([@MisterFISHUP](https://github.com/MisterFISHUP)) + - [#4350](https://github.com/facebook/docusaurus/pull/4350) polish(v2): Updated theme label translations for Turkish ([@caglarturali](https://github.com/caglarturali)) + - [#4351](https://github.com/facebook/docusaurus/pull/4351) polish(v2): add japanese translation for #4304 ([@ykzts](https://github.com/ykzts)) + - [#4309](https://github.com/facebook/docusaurus/pull/4309) polish(v2): improved Farsi translation ([@massoudmaboudi](https://github.com/massoudmaboudi)) + - [#4279](https://github.com/facebook/docusaurus/pull/4279) polish(v2): theme default translations for language de / german ([@philipp985](https://github.com/philipp985)) + - [#4275](https://github.com/facebook/docusaurus/pull/4275) polish(v2): Add more tags translations ([@slorber](https://github.com/slorber)) + - [#4246](https://github.com/facebook/docusaurus/pull/4246) refactor(v2): add Russian translation for classic theme ([@lex111](https://github.com/lex111)) + - [#4242](https://github.com/facebook/docusaurus/pull/4242) refactor(v2): use Link component for external links ([@lex111](https://github.com/lex111)) + - [#4244](https://github.com/facebook/docusaurus/pull/4244) refactor(v2): clean-ups and fixes ([@lex111](https://github.com/lex111)) + - [#4193](https://github.com/facebook/docusaurus/pull/4193) refactor(v2): update tabs to follow WAI-ARIA spec ([@lex111](https://github.com/lex111)) + - [#4194](https://github.com/facebook/docusaurus/pull/4194) refactor(v2): use transform instead of top position for hideable navbar ([@lex111](https://github.com/lex111)) + - [#4167](https://github.com/facebook/docusaurus/pull/4167) refactor(v2): minor styling improvements ([@lex111](https://github.com/lex111)) + - [#4169](https://github.com/facebook/docusaurus/pull/4169) refactor(v2): remove delay after skip link pressed ([@lex111](https://github.com/lex111)) + - [#4086](https://github.com/facebook/docusaurus/pull/4086) style(v2): add className to tab container ([@ArtFlag](https://github.com/ArtFlag)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#4352](https://github.com/facebook/docusaurus/pull/4352) refactor(v2): format last updated date using Intl ([@lex111](https://github.com/lex111)) + - [#4243](https://github.com/facebook/docusaurus/pull/4243) refactor(v2): introduce Seo component for internal using ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic`, `docusaurus-utils` + - [#4344](https://github.com/facebook/docusaurus/pull/4344) refactor(v2): format post date using Intl ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#4257](https://github.com/facebook/docusaurus/pull/4257) refactor(v2): improve notifier message ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#4219](https://github.com/facebook/docusaurus/pull/4219) refactor(v2): add more translatable strings ([@lex111](https://github.com/lex111)) +- Other + - [#4074](https://github.com/facebook/docusaurus/pull/4074) polish(v2): improve codesandbox template package.json ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-debug` + - [#3953](https://github.com/facebook/docusaurus/pull/3953) refactor(v2): fix debug plugin name ([@RDIL](https://github.com/RDIL)) +- `docusaurus-plugin-debug`, `docusaurus-theme-classic` + - [#3946](https://github.com/facebook/docusaurus/pull/3946) refactor(v2): minor a11y tweaks ([@lex111](https://github.com/lex111)) + +#### :memo: Documentation + +- Other + - [#4369](https://github.com/facebook/docusaurus/pull/4369) docs(v2): various improvements ([@lex111](https://github.com/lex111)) + - [#4362](https://github.com/facebook/docusaurus/pull/4362) docs(v2): Add stryker-mutator.io to showcase ([@nicojs](https://github.com/nicojs)) + - [#4354](https://github.com/facebook/docusaurus/pull/4354) docs(v2): add trpgengine showcase ([@moonrailgun](https://github.com/moonrailgun)) + - [#4346](https://github.com/facebook/docusaurus/pull/4346) docs(v1): update phrasing for website dir relative to docs dir ([@aukokyong](https://github.com/aukokyong)) + - [#4338](https://github.com/facebook/docusaurus/pull/4338) docs(v2): update showcase instruction regarding tags + fix site tags ([@slorber](https://github.com/slorber)) + - [#4331](https://github.com/facebook/docusaurus/pull/4331) docs(v2): add ocpeasy to users ([@dbrrt](https://github.com/dbrrt)) + - [#4307](https://github.com/facebook/docusaurus/pull/4307) docs(v2): Add RactivePlayer to showcase ([@ysulyma](https://github.com/ysulyma)) + - [#4297](https://github.com/facebook/docusaurus/pull/4297) docs(v2): Fix examples by importing React ([@roydukkey](https://github.com/roydukkey)) + - [#4296](https://github.com/facebook/docusaurus/pull/4296) docs(v2): move migrated sites from v1 to v2 showcase ([@lisa761](https://github.com/lisa761)) + - [#4293](https://github.com/facebook/docusaurus/pull/4293) docs(v2): Added React Native ARIA to showcase ([@theankurkedia](https://github.com/theankurkedia)) + - [#4284](https://github.com/facebook/docusaurus/pull/4284) docs(v2): Add AttoBot website to showcase page ([@wolf20482](https://github.com/wolf20482)) + - [#4285](https://github.com/facebook/docusaurus/pull/4285) docs(v2): escape more jsx in mdx files for Crowdin ([@slorber](https://github.com/slorber)) + - [#4283](https://github.com/facebook/docusaurus/pull/4283) docs(v2): Add Postgres.ai to showcase ([@NikolayS](https://github.com/NikolayS)) + - [#4282](https://github.com/facebook/docusaurus/pull/4282) docs: update Netlify deploy status badge ([@slorber](https://github.com/slorber)) + - [#4259](https://github.com/facebook/docusaurus/pull/4259) docs(v2): improve cli docs ([@massoudmaboudi](https://github.com/massoudmaboudi)) + - [#4266](https://github.com/facebook/docusaurus/pull/4266) docs(v2): update agilets banner ([@bennodev19](https://github.com/bennodev19)) + - [#4263](https://github.com/facebook/docusaurus/pull/4263) docs(v2): remove npx and use github action to configure ssh key ([@MatanBobi](https://github.com/MatanBobi)) + - [#4262](https://github.com/facebook/docusaurus/pull/4262) docs(v2): Added kotest to showcase ([@sksamuel](https://github.com/sksamuel)) + - [#4256](https://github.com/facebook/docusaurus/pull/4256) docs(v2): Add docusaurus2-graphql-doc-generator to community resources ([@edno](https://github.com/edno)) + - [#4252](https://github.com/facebook/docusaurus/pull/4252) docs(v2): Added mailgo to showcase ([@manzinello](https://github.com/manzinello)) + - [#4251](https://github.com/facebook/docusaurus/pull/4251) docs(v2): Add Axioms to showcase ([@limkinZero](https://github.com/limkinZero)) + - [#4237](https://github.com/facebook/docusaurus/pull/4237) docs(v2): Replace mbt-bundle by sicope-model ([@tienvx](https://github.com/tienvx)) + - [#4236](https://github.com/facebook/docusaurus/pull/4236) docs(v2): v2 migration should mention RSS feed url change ([@slorber](https://github.com/slorber)) + - [#4230](https://github.com/facebook/docusaurus/pull/4230) docs(v2): fix npm/yarn command example for swizzling TypeScript theme components ([@YashTotale](https://github.com/YashTotale)) + - [#4229](https://github.com/facebook/docusaurus/pull/4229) docs(v2): Fix link to slash introduction svg ([@SamChou19815](https://github.com/SamChou19815)) + - [#4226](https://github.com/facebook/docusaurus/pull/4226) docs(v2): Removing wrong parenthesis on image variable ([@juancarlosjr97](https://github.com/juancarlosjr97)) + - [#4225](https://github.com/facebook/docusaurus/pull/4225) docs(v2): added Apache APISIX ([@juzhiyuan](https://github.com/juzhiyuan)) + - [#4224](https://github.com/facebook/docusaurus/pull/4224) docs(v2): Add MikroORM site to showcase page ([@B4nan](https://github.com/B4nan)) + - [#4220](https://github.com/facebook/docusaurus/pull/4220) Add WebdriverIO docs page as showcase ([@christian-bromann](https://github.com/christian-bromann)) + - [#4210](https://github.com/facebook/docusaurus/pull/4210) misc: add requirements for sites being added to showcase ([@lex111](https://github.com/lex111)) + - [#4207](https://github.com/facebook/docusaurus/pull/4207) docs(v2): Added Console Table Documentation Site to showcase ([@ayonious](https://github.com/ayonious)) + - [#4204](https://github.com/facebook/docusaurus/pull/4204) docs(v1): fixing a broken link in blog posts ([@ayonious](https://github.com/ayonious)) + - [#4178](https://github.com/facebook/docusaurus/pull/4178) docs(v2): localize 404 page with Netlify + docs ([@slorber](https://github.com/slorber)) + - [#4177](https://github.com/facebook/docusaurus/pull/4177) docs(v2): Add docusaurus-plugin-remote-content to resources list ([@RDIL](https://github.com/RDIL)) + - [#4172](https://github.com/facebook/docusaurus/pull/4172) docs(v2): Add react-hooks.org to showcase ([@imbhargav5](https://github.com/imbhargav5)) + - [#4173](https://github.com/facebook/docusaurus/pull/4173) docs(v2): typo fixing double colon ([@ayonious](https://github.com/ayonious)) + - [#4164](https://github.com/facebook/docusaurus/pull/4164) docs(v2): add a note for images not rendered on dev server ([@yuval-hazaz](https://github.com/yuval-hazaz)) + - [#4161](https://github.com/facebook/docusaurus/pull/4161) docs(v2): Add docusaurus-theme-github-codeblock ([@christian-bromann](https://github.com/christian-bromann)) + - [#4158](https://github.com/facebook/docusaurus/pull/4158) docs(v2): improve bad static assets doc + remove some useless useBaseUrl usage ([@slorber](https://github.com/slorber)) + - [#4144](https://github.com/facebook/docusaurus/pull/4144) docs(v2): community docs typo fix ([@ayonious](https://github.com/ayonious)) + - [#4143](https://github.com/facebook/docusaurus/pull/4143) docs(v2): guide docs typo fix ([@ayonious](https://github.com/ayonious)) + - [#4141](https://github.com/facebook/docusaurus/pull/4141) docs(v2): plugins docs typo fix ([@ayonious](https://github.com/ayonious)) + - [#4139](https://github.com/facebook/docusaurus/pull/4139) docs(v2): Add Rematch site to showcase page ([@semoal](https://github.com/semoal)) + - [#4128](https://github.com/facebook/docusaurus/pull/4128) docs(v2): remove duplicate link from docs about Docusaurus1 ([@ayonious](https://github.com/ayonious)) + - [#4129](https://github.com/facebook/docusaurus/pull/4129) docs(v2): typo fix in Migration Docs ([@ayonious](https://github.com/ayonious)) + - [#4127](https://github.com/facebook/docusaurus/pull/4127) docs(v2): remove unnecessary brace from installation doc ([@ayonious](https://github.com/ayonious)) + - [#4130](https://github.com/facebook/docusaurus/pull/4130) docs(v2): typo in i18n docs ([@ayonious](https://github.com/ayonious)) + - [#4112](https://github.com/facebook/docusaurus/pull/4112) docs(v2): Do not encourage using the permalink prop ([@slorber](https://github.com/slorber)) + - [#4106](https://github.com/facebook/docusaurus/pull/4106) docs(v2): update broken link on resources page ([@eric-hc](https://github.com/eric-hc)) + - [#4084](https://github.com/facebook/docusaurus/pull/4084) docs(v2): Use the TOCInline component in config doc ([@slorber](https://github.com/slorber)) + - [#4020](https://github.com/facebook/docusaurus/pull/4020) docs(v2): 2020 recap blog post ([@slorber](https://github.com/slorber)) + - [#4009](https://github.com/facebook/docusaurus/pull/4009) docs(v2): add hideableSidebar option to config demo ([@natac13](https://github.com/natac13)) + - [#4062](https://github.com/facebook/docusaurus/pull/4062) docs(v2): Add codesandbox integration ([@sammychinedu2ky](https://github.com/sammychinedu2ky)) + - [#4058](https://github.com/facebook/docusaurus/pull/4058) docs(v2): Include new.docusaurus.io CodeSandbox in issue templates + README ([@slorber](https://github.com/slorber)) + - [#4053](https://github.com/facebook/docusaurus/pull/4053) docs(v2): Add Eightshift Docs site to showcase page ([@iruzevic](https://github.com/iruzevic)) + - [#4048](https://github.com/facebook/docusaurus/pull/4048) docs(v1): Docker: remind the user to use the --host flag ([@tomsfernandez](https://github.com/tomsfernandez)) + - [#4047](https://github.com/facebook/docusaurus/pull/4047) docs(v1): version page should recommend v2 ([@slorber](https://github.com/slorber)) + - [#4046](https://github.com/facebook/docusaurus/pull/4046) docs(v2): add sciwp to showcase ([@edulazaro](https://github.com/edulazaro)) + - [#4036](https://github.com/facebook/docusaurus/pull/4036) docs(v2): Add Nodify to showcase ([@miroiu](https://github.com/miroiu)) + - [#4038](https://github.com/facebook/docusaurus/pull/4038) docs(v1): suggest to use Docusaurus 2 even for non-FB websites ([@slorber](https://github.com/slorber)) + - [#4026](https://github.com/facebook/docusaurus/pull/4026) docs(v2): Add FlexIt to showcase ([@ataft](https://github.com/ataft)) + - [#4022](https://github.com/facebook/docusaurus/pull/4022) docs: fix typo from 'dissapear' to 'disappear' ([@vamsi3](https://github.com/vamsi3)) + - [#4002](https://github.com/facebook/docusaurus/pull/4002) docs(v2): Add how to run your own DocSearch ([@TheodoreChu](https://github.com/TheodoreChu)) + - [#3997](https://github.com/facebook/docusaurus/pull/3997) docs(v2): Add Datagit site to showcase page ([@massoudmaboudi](https://github.com/massoudmaboudi)) + - [#3990](https://github.com/facebook/docusaurus/pull/3990) docs(v2): Add wiki-powerto site showcase ([@linyuxuanlin](https://github.com/linyuxuanlin)) + - [#3991](https://github.com/facebook/docusaurus/pull/3991) docs(v2): add overwriting css variables for dark mode ([@natac13](https://github.com/natac13)) + - [#3987](https://github.com/facebook/docusaurus/pull/3987) docs(v2): Add AgileTs site to showcase page ([@bennodev19](https://github.com/bennodev19)) + - [#3978](https://github.com/facebook/docusaurus/pull/3978) docs(v2): Add documentation for docs multi-instance support ([@slorber](https://github.com/slorber)) + - [#3977](https://github.com/facebook/docusaurus/pull/3977) docs(v2): nudge users to add site to showcase ([@slorber](https://github.com/slorber)) + - [#3975](https://github.com/facebook/docusaurus/pull/3975) docs(v2): Reorganize/split the guides doc / markdown sections ([@slorber](https://github.com/slorber)) + - [#3976](https://github.com/facebook/docusaurus/pull/3976) docs(v2): Add AI-Speaker site to showcase page ([@asystentka-jolka](https://github.com/asystentka-jolka)) + - [#3974](https://github.com/facebook/docusaurus/pull/3974) docs(v2): doc typo on sidebar admonition ([@slorber](https://github.com/slorber)) + - [#3962](https://github.com/facebook/docusaurus/pull/3962) docs(v2): Add migration info doc regarding docs folder location ([@slorber](https://github.com/slorber)) + - [#3950](https://github.com/facebook/docusaurus/pull/3950) docs(v2): update GitHub entreprise deployment doc ([@samhrncir](https://github.com/samhrncir)) + - [#3945](https://github.com/facebook/docusaurus/pull/3945) docs(v2): Added information about setting `/` in routeBasePath ([@Siemienik](https://github.com/Siemienik)) +- `docusaurus-theme-classic` + - [#4356](https://github.com/facebook/docusaurus/pull/4356) polish(v2): [theme-classic] add Chinese translations (zh-Hant & zh-Hans) ([@MisterFISHUP](https://github.com/MisterFISHUP)) +- `docusaurus` + - [#4126](https://github.com/facebook/docusaurus/pull/4126) docs(v2): do not recommend using useBaseUrl() hook in most cases ([@slorber](https://github.com/slorber)) + - [#4049](https://github.com/facebook/docusaurus/pull/4049) docs(v1): version page should recommend v2 (bis) ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-theme-classic`, `docusaurus` + - [#4014](https://github.com/facebook/docusaurus/pull/4014) docs(v2): i18n doc + polish ([@slorber](https://github.com/slorber)) +- `docusaurus-cssnano-preset`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-bootstrap`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` + - [#4034](https://github.com/facebook/docusaurus/pull/4034) docs(v2): Add READMEs to v2 packages ([@RDIL](https://github.com/RDIL)) +- `docusaurus-init` + - [#3881](https://github.com/facebook/docusaurus/pull/3881) docs(v2): update FB OSS logo ([@Simek](https://github.com/Simek)) + +#### :house: Internal + +- Other + - [#4372](https://github.com/facebook/docusaurus/pull/4372) chore(v1): release docusaurus v1.14.7 ([@slorber](https://github.com/slorber)) + - [#4368](https://github.com/facebook/docusaurus/pull/4368) chore(deps): bump elliptic from 6.5.3 to 6.5.4 ([@dependabot[bot]](https://github.com/apps/dependabot)) + - [#4365](https://github.com/facebook/docusaurus/pull/4365) chore: unstable yarnlock ([@slorber](https://github.com/slorber)) + - [#4337](https://github.com/facebook/docusaurus/pull/4337) misc: restore build size bot ([@slorber](https://github.com/slorber)) + - [#4289](https://github.com/facebook/docusaurus/pull/4289) chore(v2): remove docs for alpha v69 ([@lex111](https://github.com/lex111)) + - [#4253](https://github.com/facebook/docusaurus/pull/4253) chore(v2): remove docs for alpha v68 ([@lex111](https://github.com/lex111)) + - [#4248](https://github.com/facebook/docusaurus/pull/4248) chore(v2): Fix build size bot ([@slorber](https://github.com/slorber)) + - [#4214](https://github.com/facebook/docusaurus/pull/4214) chore(v2): setup for i18n staging deployment ([@slorber](https://github.com/slorber)) + - [#4159](https://github.com/facebook/docusaurus/pull/4159) chore(v2): fix build size bot again ([@slorber](https://github.com/slorber)) + - [#4156](https://github.com/facebook/docusaurus/pull/4156) chore(v2): fix build size bot monitoring of js/css assets ([@slorber](https://github.com/slorber)) + - [#4100](https://github.com/facebook/docusaurus/pull/4100) chore(v2): remove docs for alpha v66 ([@lex111](https://github.com/lex111)) + - [#4077](https://github.com/facebook/docusaurus/pull/4077) chore(v2): fix unstable master yarn.lock ([@slorber](https://github.com/slorber)) + - [#4063](https://github.com/facebook/docusaurus/pull/4063) chore(v2): Regen codesandbox templates + add template: "docusaurus" ([@slorber](https://github.com/slorber)) + - [#4056](https://github.com/facebook/docusaurus/pull/4056) chore(v2): update codesandbox redirect ([@slorber](https://github.com/slorber)) + - [#4041](https://github.com/facebook/docusaurus/pull/4041) chore(v1): revert v1 netlify.toml ([@slorber](https://github.com/slorber)) + - [#4040](https://github.com/facebook/docusaurus/pull/4040) chore(v1): upgrade v1 Crowdin cli + CI config ([@slorber](https://github.com/slorber)) + - [#4030](https://github.com/facebook/docusaurus/pull/4030) chore(v2): install Crowdin cli through npm package ([@slorber](https://github.com/slorber)) + - [#4003](https://github.com/facebook/docusaurus/pull/4003) chore: add DevContainer config for GitHub codespaces ([@kumaraditya303](https://github.com/kumaraditya303)) + - [#4001](https://github.com/facebook/docusaurus/pull/4001) chore(v2): Upgrade crowdin ([@slorber](https://github.com/slorber)) + - [#3995](https://github.com/facebook/docusaurus/pull/3995) chore(v2): remove docs for alpha v65 ([@lex111](https://github.com/lex111)) + - [#3960](https://github.com/facebook/docusaurus/pull/3960) fix(v2): remove duplicate section on Versions page ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#4370](https://github.com/facebook/docusaurus/pull/4370) chore(v2): update infima ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#4361](https://github.com/facebook/docusaurus/pull/4361) refactor(v2): remove duplicated lodash dependencies and import only what needed ([@armano2](https://github.com/armano2)) +- `docusaurus-1.x`, `docusaurus` + - [#4270](https://github.com/facebook/docusaurus/pull/4270) chore(v2): upgrade react-dev-utils ([@yangshun](https://github.com/yangshun)) +- `docusaurus-init`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-types`, `docusaurus` + - [#4264](https://github.com/facebook/docusaurus/pull/4264) chore(v2): bump/align deps in monorepo: commander, semver, fs-extra ([@Simek](https://github.com/Simek)) +- `docusaurus` + - [#4265](https://github.com/facebook/docusaurus/pull/4265) chore(v2): PostCSS peer dep fix ([@RDIL](https://github.com/RDIL)) + - [#4091](https://github.com/facebook/docusaurus/pull/4091) refactor(v2): Switch from inquirer to prompts ([@RDIL](https://github.com/RDIL)) + - [#4066](https://github.com/facebook/docusaurus/pull/4066) chore(v2): Update a few dependencies ([@RDIL](https://github.com/RDIL)) +- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#4148](https://github.com/facebook/docusaurus/pull/4148) chore(v2): upgrade dependencies ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-pwa` + - [#4120](https://github.com/facebook/docusaurus/pull/4120) chore(v2): Update workbox to v6 ([@RDIL](https://github.com/RDIL)) +- `docusaurus-utils`, `docusaurus` + - [#4081](https://github.com/facebook/docusaurus/pull/4081) chore(v2): Update webpack-related dependencies, pre-work to migrate to Webpack 5 ([@RDIL](https://github.com/RDIL)) +- `docusaurus-init`, `docusaurus` + - [#4012](https://github.com/facebook/docusaurus/pull/4012) chore(v2): docusaurus-init: switch from inquirer to prompts ([@RDIL](https://github.com/RDIL)) +- `docusaurus-plugin-sitemap` + - [#4005](https://github.com/facebook/docusaurus/pull/4005) chore(v2): prettier fixes ([@slorber](https://github.com/slorber)) +- `docusaurus-migrate` + - [#3988](https://github.com/facebook/docusaurus/pull/3988) chore(v2): fix date-sensitive test fixture ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` + - [#3959](https://github.com/facebook/docusaurus/pull/3959) chore(v2): fix windows Jest tests ([@slorber](https://github.com/slorber)) + +#### :running_woman: Performance + +- `docusaurus-cssnano-preset`, `docusaurus-plugin-content-blog`, `docusaurus` + - [#4355](https://github.com/facebook/docusaurus/pull/4355) perf(v2): improve blog mdx-loader and postcss loader ([@lex111](https://github.com/lex111)) + +#### Committers: 70 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Ali Saki ([@3alisaki](https://github.com/3alisaki)) +- Andrew Taft ([@ataft](https://github.com/ataft)) +- Ankur Kedia ([@theankurkedia](https://github.com/theankurkedia)) +- Apurva Ojas ([@apurvaojas](https://github.com/apurvaojas)) +- Armano ([@armano2](https://github.com/armano2)) +- Arthur ([@ArtFlag](https://github.com/ArtFlag)) +- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) +- Ben ([@ben-qnimble](https://github.com/ben-qnimble)) +- BennoDev ([@bennodev19](https://github.com/bennodev19)) +- Bhargav Ponnapalli ([@imbhargav5](https://github.com/imbhargav5)) +- Christian Bromann ([@christian-bromann](https://github.com/christian-bromann)) +- David Barrat ([@dbrrt](https://github.com/dbrrt)) +- Eduardo Lázaro ([@edulazaro](https://github.com/edulazaro)) +- Eric Carboni ([@eric-hc](https://github.com/eric-hc)) +- Grégory Heitz ([@edno](https://github.com/edno)) +- Ivan Ružević ([@iruzevic](https://github.com/iruzevic)) +- Jessica Lin ([@jlin27](https://github.com/jlin27)) +- Joel M ([@9oelM](https://github.com/9oelM)) +- Joel Marcey ([@JoelMarcey](https://github.com/JoelMarcey)) +- Jola ([@asystentka-jolka](https://github.com/asystentka-jolka)) +- Juan Carlos Blanco Delgado ([@juancarlosjr97](https://github.com/juancarlosjr97)) +- Kevin Viglucci ([@viglucci](https://github.com/viglucci)) +- Kumar Aditya ([@kumaraditya303](https://github.com/kumaraditya303)) +- Lisa Chandra ([@lisa761](https://github.com/lisa761)) +- LittleboyHarry ([@LittleboyHarry](https://github.com/LittleboyHarry)) +- Long Ho ([@longlho](https://github.com/longlho)) +- Martin Adámek ([@B4nan](https://github.com/B4nan)) +- Massoud Maboudi ([@massoudmaboudi](https://github.com/massoudmaboudi)) +- Matan Borenkraout ([@MatanBobi](https://github.com/MatanBobi)) +- Matt Oestreich ([@oze4](https://github.com/oze4)) +- Matteo Manzinello ([@manzinello](https://github.com/manzinello)) +- Miroiu Emanuel ([@miroiu](https://github.com/miroiu)) +- Mohd Shad Mirza ([@iamshadmirza](https://github.com/iamshadmirza)) +- Nahiyan Kamal ([@ayonious](https://github.com/ayonious)) +- Nathan Bosscher ([@ntbosscher](https://github.com/ntbosscher)) +- Nico Jansen ([@nicojs](https://github.com/nicojs)) +- Nikolay Samokhvalov ([@NikolayS](https://github.com/NikolayS)) +- Pablo Vidal ([@limkinZero](https://github.com/limkinZero)) +- Power Lin ([@linyuxuanlin](https://github.com/linyuxuanlin)) +- Reece Dunham ([@RDIL](https://github.com/RDIL)) +- Saihajpreet Singh ([@saihaj](https://github.com/saihaj)) +- Sam Hrncir ([@samhrncir](https://github.com/samhrncir)) +- Sam Sam ([@sksamuel](https://github.com/sksamuel)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Sean Campbell ([@natac13](https://github.com/natac13)) +- Sergio Moreno ([@semoal](https://github.com/semoal)) +- Siemienik Pawel ([@Siemienik](https://github.com/Siemienik)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Theodore Chu ([@TheodoreChu](https://github.com/TheodoreChu)) +- Tien Vo Xuan ([@tienvx](https://github.com/tienvx)) +- Tomas Fernandez ([@tomsfernandez](https://github.com/tomsfernandez)) +- Vamsi Krishna Reddy Satti ([@vamsi3](https://github.com/vamsi3)) +- Welly ([@wellyshen](https://github.com/wellyshen)) +- Yamagishi Kazutoshi ([@ykzts](https://github.com/ykzts)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) +- Yash Totale ([@YashTotale](https://github.com/YashTotale)) +- Yuri Sulyma ([@ysulyma](https://github.com/ysulyma)) +- Yuval Hazaz ([@yuval-hazaz](https://github.com/yuval-hazaz)) +- [@MisterFISHUP](https://github.com/MisterFISHUP) +- [@aukokyong](https://github.com/aukokyong) +- [@philipp985](https://github.com/philipp985) +- [@roydukkey](https://github.com/roydukkey) +- [@sammychinedu2ky](https://github.com/sammychinedu2ky) +- [@saydo17](https://github.com/saydo17) +- [@tokarchyn](https://github.com/tokarchyn) +- [@wolf20482](https://github.com/wolf20482) +- moonrailgun ([@moonrailgun](https://github.com/moonrailgun)) +- Çağlar Turalı ([@caglarturali](https://github.com/caglarturali)) +- 琚致远 ([@juzhiyuan](https://github.com/juzhiyuan)) + +## 2.0.0-alpha.70 (2020-12-17) + +#### :rocket: New Feature + +- `docusaurus` + - [#3932](https://github.com/facebook/docusaurus/pull/3932) feat(v2): Add Root theme element ([@slorber](https://github.com/slorber)) +- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#3916](https://github.com/facebook/docusaurus/pull/3916) feat(v2): Add localeDropdown navbar item type + i18n localeConfigs field ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-types` + - [#3904](https://github.com/facebook/docusaurus/pull/3904) feat(v2): inline table-of-contents + refactor TOC ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs` + - [#3888](https://github.com/facebook/docusaurus/pull/3888) feat(v2): add custom props for consumption by swizzled sidebar ([@oriooctopus](https://github.com/oriooctopus)) +- `docusaurus-plugin-content-blog` + - [#3842](https://github.com/facebook/docusaurus/pull/3842) feat(v2): enable feeds by default in blog plugin ([@cindygu4](https://github.com/cindygu4)) +- Other + - [#3827](https://github.com/facebook/docusaurus/pull/3827) feat(v2): add automated canary releases ([@slorber](https://github.com/slorber)) + - [#3761](https://github.com/facebook/docusaurus/pull/3761) feat(v2): Added Lighthouse CI to PR checks ([@sarthakkundra](https://github.com/sarthakkundra)) +- `docusaurus-1.x`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#3325](https://github.com/facebook/docusaurus/pull/3325) feat(v2): core v2 i18n support + Docusaurus site Crowdin integration ([@slorber](https://github.com/slorber)) + +#### :boom: Breaking Change + +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-types` + - [#3904](https://github.com/facebook/docusaurus/pull/3904) feat(v2): inline table-of-contents + refactor TOC ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog` + - [#3842](https://github.com/facebook/docusaurus/pull/3842) feat(v2): enable feeds by default in blog plugin ([@cindygu4](https://github.com/cindygu4)) + +#### :bug: Bug Fix + +- `docusaurus` + - [#3922](https://github.com/facebook/docusaurus/pull/3922) fix(v2): fix navbar items issue on Windows? ([@slorber](https://github.com/slorber)) + - [#3920](https://github.com/facebook/docusaurus/pull/3920) fix(v2): i18n translation extractor should handle JSX formatting edge cases better ([@slorber](https://github.com/slorber)) + - [#3896](https://github.com/facebook/docusaurus/pull/3896) fix(v2): do not treat at-rules during CSS minification ([@lex111](https://github.com/lex111)) + - [#3869](https://github.com/facebook/docusaurus/pull/3869) fix(v2): load plugin commands async to fix broken plugin CLI commands `docs:version` ([@aeneasr](https://github.com/aeneasr)) +- `docusaurus-theme-classic` + - [#3921](https://github.com/facebook/docusaurus/pull/3921) fix(v2): remove useless console log ([@slorber](https://github.com/slorber)) + - [#3895](https://github.com/facebook/docusaurus/pull/3895) fix(v2): use proper element for pagination nav label ([@lex111](https://github.com/lex111)) + - [#3882](https://github.com/facebook/docusaurus/pull/3882) fix(v2): improve Footer structure, add class names, use Infima transition ([@Simek](https://github.com/Simek)) + - [#3877](https://github.com/facebook/docusaurus/pull/3877) fix(v2): dynamic dark mode detection without toggle widget ([@hmil](https://github.com/hmil)) + - [#3854](https://github.com/facebook/docusaurus/pull/3854) fix(v2): refactor icons in theme-classic, fix swizzle issue ([@Simek](https://github.com/Simek)) + - [#3823](https://github.com/facebook/docusaurus/pull/3823) fix(v2): support rendering of singular tabs ([@aeneasr](https://github.com/aeneasr)) + - [#3817](https://github.com/facebook/docusaurus/pull/3817) fix(v2): Allow footer logo at attribute to be empty ([@aarongarciah](https://github.com/aarongarciah)) +- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` + - [#3900](https://github.com/facebook/docusaurus/pull/3900) fix(v2): correct typo in metas generated for Twitter cards ([@mpsq](https://github.com/mpsq)) +- Other + - [#3872](https://github.com/facebook/docusaurus/pull/3872) chore: add missing v1 generated files to ignores ([@Simek](https://github.com/Simek)) + - [#3833](https://github.com/facebook/docusaurus/pull/3833) fix(v2): temporary: disable crowdin until PR env variable permission fixed ([@slorber](https://github.com/slorber)) +- `stylelint-copyright` + - [#3852](https://github.com/facebook/docusaurus/pull/3852) fix(v2): to fix the canary release GH workflow ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-search-algolia` + - [#3853](https://github.com/facebook/docusaurus/pull/3853) fix(v2): fix DocSearch keyboard navigator ([@francoischalifour](https://github.com/francoischalifour)) + - [#3837](https://github.com/facebook/docusaurus/pull/3837) fix(v2): update SearchPage styling, fix appearance in dark mode ([@Simek](https://github.com/Simek)) + - [#3828](https://github.com/facebook/docusaurus/pull/3828) fix(v2): restore Algolia search ([@lex111](https://github.com/lex111)) + - [#3819](https://github.com/facebook/docusaurus/pull/3819) feat(search): update DocSearch to alpha.31 ([@francoischalifour](https://github.com/francoischalifour)) +- `docusaurus-plugin-content-docs` + - [#3839](https://github.com/facebook/docusaurus/pull/3839) fix(v2): remove unnecessary backtick in output ([@sivaraam](https://github.com/sivaraam)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#3829](https://github.com/facebook/docusaurus/pull/3829) fix(v2): fix search ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus` + - [#3824](https://github.com/facebook/docusaurus/pull/3824) fix(v2): update notifier dist tag ([@slorber](https://github.com/slorber)) + +#### :nail_care: Polish + +- `docusaurus` + - [#3880](https://github.com/facebook/docusaurus/pull/3880) polish(v2): improve docusaurus deploy logs ([@slorber](https://github.com/slorber)) + +#### :memo: Documentation + +- [#3931](https://github.com/facebook/docusaurus/pull/3931) docs(v2): blog.md with docs: false, for blog-only mode ([@Romstar](https://github.com/Romstar)) +- [#3924](https://github.com/facebook/docusaurus/pull/3924) docs(v2): Removed unnecessary closing parenthesis ([@Varshit07](https://github.com/Varshit07)) +- [#3928](https://github.com/facebook/docusaurus/pull/3928) docs(v2): add FoalTS to showcase page ([@LoicPoullain](https://github.com/LoicPoullain)) +- [#3899](https://github.com/facebook/docusaurus/pull/3899) docs(v2): Move sidebar content to its own page ([@ArtFlag](https://github.com/ArtFlag)) +- [#3856](https://github.com/facebook/docusaurus/pull/3856) docs(v2): typo ([@borool](https://github.com/borool)) +- [#3891](https://github.com/facebook/docusaurus/pull/3891) docs(v2): Wrap section about custom domains in :::info ([@Alex1304](https://github.com/Alex1304)) +- [#3871](https://github.com/facebook/docusaurus/pull/3871) docs(v2): missing `` mdx import ([@slorber](https://github.com/slorber)) +- [#3873](https://github.com/facebook/docusaurus/pull/3873) docs(v2): From docusaurus-migrate to @docusaurus/migrate ([@manzinello](https://github.com/manzinello)) +- [#3867](https://github.com/facebook/docusaurus/pull/3867) docs(v2): Add docusaurus-plugin-moesif to community plugins ([@dgilling](https://github.com/dgilling)) +- [#3851](https://github.com/facebook/docusaurus/pull/3851) docs(v2): Fixed Typo: Hided => Hidden ([@woodrufs](https://github.com/woodrufs)) +- [#3832](https://github.com/facebook/docusaurus/pull/3832) docs(v2): Add wasp to showcase ([@matijaSos](https://github.com/matijaSos)) +- [#3813](https://github.com/facebook/docusaurus/pull/3813) docs(v2): render deployment doc ([@davidmauskop](https://github.com/davidmauskop)) +- [#3835](https://github.com/facebook/docusaurus/pull/3835) docs(v2): update Client API docs page ([@Simek](https://github.com/Simek)) +- [#3831](https://github.com/facebook/docusaurus/pull/3831) docs(v2): Docs refactoring and reorganization ([@slorber](https://github.com/slorber)) + +#### :house: Internal + +- Other + - [#3912](https://github.com/facebook/docusaurus/pull/3912) chore(v2): remove docs for alpha v64 ([@lex111](https://github.com/lex111)) + - [#3907](https://github.com/facebook/docusaurus/pull/3907) chore(ci): fix canary release filtering ([@slorber](https://github.com/slorber)) + - [#3902](https://github.com/facebook/docusaurus/pull/3902) chore(deps): bump ini from 1.3.5 to 1.3.7 ([@dependabot[bot]](https://github.com/apps/dependabot)) + - [#3884](https://github.com/facebook/docusaurus/pull/3884) chore(ci): increase Lighthouse CI max_timeout ([@Simek](https://github.com/Simek)) + - [#3883](https://github.com/facebook/docusaurus/pull/3883) chore(v2): remove docs for alpha v62-63 ([@lex111](https://github.com/lex111)) + - [#3863](https://github.com/facebook/docusaurus/pull/3863) chore(ci): run V1 Build and Migration CLI tests conditionally on CI ([@Simek](https://github.com/Simek)) + - [#3861](https://github.com/facebook/docusaurus/pull/3861) chore(ci): reduce number of jobs, remove build from lighthouse pipeline ([@Simek](https://github.com/Simek)) + - [#3860](https://github.com/facebook/docusaurus/pull/3860) chore: add Yarn v2 cache directory to ignores ([@Simek](https://github.com/Simek)) + - [#3858](https://github.com/facebook/docusaurus/pull/3858) chore(v2): disable Crowdin for deploy previews ([@slorber](https://github.com/slorber)) + - [#3857](https://github.com/facebook/docusaurus/pull/3857) fix(v2): fix Crowdin ci commands ([@slorber](https://github.com/slorber)) + - [#3849](https://github.com/facebook/docusaurus/pull/3849) chore(ci): CI scripts cleanup, add Node 14 runs, bump checkout action ([@Simek](https://github.com/Simek)) + - [#3850](https://github.com/facebook/docusaurus/pull/3850) chore(v2): i18n CI: add write-translations call ([@slorber](https://github.com/slorber)) + - [#3848](https://github.com/facebook/docusaurus/pull/3848) chore(v2): fix CI typo ([@slorber](https://github.com/slorber)) + - [#3847](https://github.com/facebook/docusaurus/pull/3847) chore(v2): wire production Crowdin project + setup ([@slorber](https://github.com/slorber)) + - [#3846](https://github.com/facebook/docusaurus/pull/3846) chore(v2): fix PRs not able to add lighthouse/buildsize comment from works ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` + - [#3865](https://github.com/facebook/docusaurus/pull/3865) chore(v2): fix ignore paths and Prettier commands in themes ([@Simek](https://github.com/Simek)) +- `docusaurus-cssnano-preset`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` + - [#3844](https://github.com/facebook/docusaurus/pull/3844) chore(v2): fix several lint warnings, add missing types, cleanup ([@Simek](https://github.com/Simek)) +- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia` + - [#3838](https://github.com/facebook/docusaurus/pull/3838) refactor(v2): extract site title formatter to theme-common util ([@Simek](https://github.com/Simek)) + +#### Committers: 23 + +- Aarón García Hervás ([@aarongarciah](https://github.com/aarongarciah)) +- Alex1304 ([@Alex1304](https://github.com/Alex1304)) +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Arthur ([@ArtFlag](https://github.com/ArtFlag)) +- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) +- Cindy Gu ([@cindygu4](https://github.com/cindygu4)) +- Derric Gilling ([@dgilling](https://github.com/dgilling)) +- François Chalifour ([@francoischalifour](https://github.com/francoischalifour)) +- Hadrien Milano ([@hmil](https://github.com/hmil)) +- Kaartic Sivaraam ([@sivaraam](https://github.com/sivaraam)) +- Loïc Poullain ([@LoicPoullain](https://github.com/LoicPoullain)) +- Matija Sosic ([@matijaSos](https://github.com/matijaSos)) +- Matteo Manzinello ([@manzinello](https://github.com/manzinello)) +- Méril ([@mpsq](https://github.com/mpsq)) +- Oliver Ullman ([@oriooctopus](https://github.com/oriooctopus)) +- Rami ([@Romstar](https://github.com/Romstar)) +- Sarthak kundra ([@sarthakkundra](https://github.com/sarthakkundra)) +- Stephen Woodruff ([@woodrufs](https://github.com/woodrufs)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Varshit Shah ([@Varshit07](https://github.com/Varshit07)) +- [@borool](https://github.com/borool) +- [@davidmauskop](https://github.com/davidmauskop) +- hackerman ([@aeneasr](https://github.com/aeneasr)) + +## 2.0.0-alpha.69 (2020-11-24) + +#### :rocket: New Feature + +- `docusaurus-types`, `docusaurus` + - [#3802](https://github.com/facebook/docusaurus/pull/3802) feat(v2): add baseUrlIssueBanner configuration to disable banner ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#3807](https://github.com/facebook/docusaurus/pull/3807) chore(v2): upgrade Infima to v0.2.0-alpha.18 ([@lex111](https://github.com/lex111)) + - [#3806](https://github.com/facebook/docusaurus/pull/3806) fix(v2): remove aria-hidden attr from anchor link of heading ([@lex111](https://github.com/lex111)) + - [#3784](https://github.com/facebook/docusaurus/pull/3784) fix(v2): fix missing logo in dark theme when darkSrc was not set ([@Simek](https://github.com/Simek)) +- `docusaurus-theme-search-algolia` + - [#3804](https://github.com/facebook/docusaurus/pull/3804) fix(v2): Algolia: allow contextualSearch + facetFilters ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#3796](https://github.com/facebook/docusaurus/pull/3796) Adds createRequire for preset resolution ([@arcanis](https://github.com/arcanis)) + +#### :memo: Documentation + +- [#3803](https://github.com/facebook/docusaurus/pull/3803) docs(v2): fix docusaurus init issue when not using @latest ([@slorber](https://github.com/slorber)) +- [#3785](https://github.com/facebook/docusaurus/pull/3785) docs(v2): recommend Docusaurus 2 usage ([@slorber](https://github.com/slorber)) +- [#3783](https://github.com/facebook/docusaurus/pull/3783) docs(v2): remove @next tags needed to install v2 packages ([@slorber](https://github.com/slorber)) +- [#3781](https://github.com/facebook/docusaurus/pull/3781) docs(v2): rename zeit to vercel ([@camiluc](https://github.com/camiluc)) + +#### :house: Internal + +- [#3800](https://github.com/facebook/docusaurus/pull/3800) chore(v2): remove useless stylelint-copyright peerDependency ([@slorber](https://github.com/slorber)) +- [#3786](https://github.com/facebook/docusaurus/pull/3786) chore(v2): ensure publishConfig.access presence with tests ([@slorber](https://github.com/slorber)) + +#### Committers: 5 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) +- Maël Nison ([@arcanis](https://github.com/arcanis)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- [@camiluc](https://github.com/camiluc) + +## 2.0.0-alpha.68 (2020-11-18) + +#### :rocket: New Feature + +- Other + - [#3717](https://github.com/facebook/docusaurus/pull/3717) feat(v2): official CodeSandbox support ([@sammychinedu2ky](https://github.com/sammychinedu2ky)) +- `docusaurus-init` + - [#3729](https://github.com/facebook/docusaurus/pull/3729) feat(v2): allow init project via npm ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` + - [#3730](https://github.com/facebook/docusaurus/pull/3730) feat(v2): add ThemedImage component ([@Simek](https://github.com/Simek)) +- `docusaurus-cssnano-preset`, `docusaurus-theme-classic`, `docusaurus` + - [#3716](https://github.com/facebook/docusaurus/pull/3716) feat(v2): introduce new minification of CSS bundle ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#3694](https://github.com/facebook/docusaurus/pull/3694) feat(v2): Added the ability to specify GIT_PASS in deploy command (for CI purposes) ([@smcelhinney](https://github.com/smcelhinney)) + - [#3621](https://github.com/facebook/docusaurus/pull/3621) feat(v2): baseUrl config issues: show help message if css/js can't load ([@jcs98](https://github.com/jcs98)) + - [#3594](https://github.com/facebook/docusaurus/pull/3594) feat(v2): add support for key,cert in https ([@ThakurKarthik](https://github.com/ThakurKarthik)) +- `docusaurus-remark-plugin-npm2yarn` + - [#3705](https://github.com/facebook/docusaurus/pull/3705) feat(v2): add support for sync to npm2yarn tabs ([@lex111](https://github.com/lex111)) +- `docusaurus-init`, `docusaurus-migrate`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#3658](https://github.com/facebook/docusaurus/pull/3658) feat(v2): onBrokenMarkdownLinks config ([@AmyrAhmady](https://github.com/AmyrAhmady)) +- `docusaurus-theme-classic` + - [#3640](https://github.com/facebook/docusaurus/pull/3640) feat(v2): add skip to content link ([@lex111](https://github.com/lex111)) + - [#3615](https://github.com/facebook/docusaurus/pull/3615) feat(v2): add ability to hide doc sidebar ([@lex111](https://github.com/lex111)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#3749](https://github.com/facebook/docusaurus/pull/3749) fix(v2): add support for interleaving Markdown in code blocks ([@lex111](https://github.com/lex111)) + - [#3739](https://github.com/facebook/docusaurus/pull/3739) fix(v2): add support for prefers-reduced-motion in hideable sidebar ([@lex111](https://github.com/lex111)) + - [#3726](https://github.com/facebook/docusaurus/pull/3726) fix(v2): add thin scrollbar to proper element in TOC ([@lex111](https://github.com/lex111)) + - [#3681](https://github.com/facebook/docusaurus/pull/3681) Revert "refactor(v2): improve regex matching code-block title" ([@lex111](https://github.com/lex111)) + - [#3662](https://github.com/facebook/docusaurus/pull/3662) fix(v2): navbar dropdown crash when item.to is undefined ([@artemkovalyov](https://github.com/artemkovalyov)) + - [#3669](https://github.com/facebook/docusaurus/pull/3669) fix(v2): make scrollbar styles consistent ([@nategiraudeau](https://github.com/nategiraudeau)) + - [#3666](https://github.com/facebook/docusaurus/pull/3666) fix(v2): make optional title for footer links column ([@lex111](https://github.com/lex111)) + - [#3647](https://github.com/facebook/docusaurus/pull/3647) fix(v2): do not set height for mobile dropdown during build ([@lex111](https://github.com/lex111)) + - [#3650](https://github.com/facebook/docusaurus/pull/3650) fix(v2): add landmark for skip to content link ([@lex111](https://github.com/lex111)) + - [#3627](https://github.com/facebook/docusaurus/pull/3627) fix(v2): disable tabbing on hidden doc sidebar ([@lex111](https://github.com/lex111)) + - [#3637](https://github.com/facebook/docusaurus/pull/3637) fix(v2): wrap code blocks on print ([@haivp3010](https://github.com/haivp3010)) + - [#3603](https://github.com/facebook/docusaurus/pull/3603) fix(v2): animate dropdown properly ([@lex111](https://github.com/lex111)) + - [#3611](https://github.com/facebook/docusaurus/pull/3611) fix(v2): Added back support for optional logo field in theme-classic navbarConfig ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-theme-classic`, `docusaurus` + - [#3763](https://github.com/facebook/docusaurus/pull/3763) refactor(v2): various markup improvements ([@lex111](https://github.com/lex111)) + - [#3724](https://github.com/facebook/docusaurus/pull/3724) fix(v2): add support for non-ASCII chars in anchor link scroll ([@lex111](https://github.com/lex111)) +- `docusaurus-module-type-aliases`, `docusaurus` + - [#3723](https://github.com/facebook/docusaurus/pull/3723) fix(v2): restore prefetch functionality ([@lex111](https://github.com/lex111)) +- Other + - [#3760](https://github.com/facebook/docusaurus/pull/3760) fix(v2): codesandbox generated examples should use published init package ([@slorber](https://github.com/slorber)) + - [#3701](https://github.com/facebook/docusaurus/pull/3701) fix(v2): limit images height on showcase page ([@lex111](https://github.com/lex111)) +- `docusaurus-mdx-loader` + - [#3757](https://github.com/facebook/docusaurus/pull/3757) fix(v2): escape alt text in img tag ([@lex111](https://github.com/lex111)) + - [#3653](https://github.com/facebook/docusaurus/pull/3653) fix(v2): handle multiple asset links in one line properly ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-search-algolia`, `docusaurus-utils` + - [#3721](https://github.com/facebook/docusaurus/pull/3721) fix(v2): use swizzled SearchPage component if any ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#3725](https://github.com/facebook/docusaurus/pull/3725) fix(v2): fix inconsistent error output in swizzle command ([@lex111](https://github.com/lex111)) + - [#3704](https://github.com/facebook/docusaurus/pull/3704) refactor(v2): allow adding plugins depending on condition ([@lex111](https://github.com/lex111)) + - [#3691](https://github.com/facebook/docusaurus/pull/3691) fix(v2): use SVGO in webpack SVGR loader ([@charleskorn](https://github.com/charleskorn)) + - [#3667](https://github.com/facebook/docusaurus/pull/3667) fix(v2): Fix typo in BaseUrlSuggestionWarning ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-utils` + - [#3703](https://github.com/facebook/docusaurus/pull/3703) fix(v2): ignore export declarations in excerpt ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-search-algolia` + - [#3639](https://github.com/facebook/docusaurus/pull/3639) fix(v2): restore infinite scroll pagination on search page ([@lex111](https://github.com/lex111)) +- `docusaurus-types`, `docusaurus` + - [#3622](https://github.com/facebook/docusaurus/pull/3622) fix(v2): docusaurus start --poll 500 should work + better config load failure error ([@slorber](https://github.com/slorber)) + +#### :nail_care: Polish + +- `docusaurus` + - [#3765](https://github.com/facebook/docusaurus/pull/3765) chore(v2): replace wait-file with wait-on to reduce npm warnings ([@lex111](https://github.com/lex111)) + - [#3725](https://github.com/facebook/docusaurus/pull/3725) fix(v2): fix inconsistent error output in swizzle command ([@lex111](https://github.com/lex111)) + - [#3609](https://github.com/facebook/docusaurus/pull/3609) refactor(v2): Improve SSR error message: log page path ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#3764](https://github.com/facebook/docusaurus/pull/3764) refactor(v2): make accessible anchor links from keyboard ([@lex111](https://github.com/lex111)) + - [#3745](https://github.com/facebook/docusaurus/pull/3745) refactor(v2): introduce Logo component, remove useLogo hook ([@Simek](https://github.com/Simek)) + - [#3706](https://github.com/facebook/docusaurus/pull/3706) refactor(v2): render all tab panels at once ([@lex111](https://github.com/lex111)) + - [#3712](https://github.com/facebook/docusaurus/pull/3712) chore(v2): upgrade Infima to v0.2.0-alpha.15 ([@lex111](https://github.com/lex111)) + - [#3685](https://github.com/facebook/docusaurus/pull/3685) refactor(v2): improve regex matching code-block title ([@hong4rc](https://github.com/hong4rc)) + - [#3674](https://github.com/facebook/docusaurus/pull/3674) feat(v2): add additional wrapper class to blog pages ([@Simek](https://github.com/Simek)) + - [#3671](https://github.com/facebook/docusaurus/pull/3671) refactor(v2): improve regex matching code-block title ([@hong4rc](https://github.com/hong4rc)) + - [#3654](https://github.com/facebook/docusaurus/pull/3654) refactor(v2): clean up code blocks ([@lex111](https://github.com/lex111)) + - [#3649](https://github.com/facebook/docusaurus/pull/3649) refactor(v2): make code blocks scrollable from keyboard ([@lex111](https://github.com/lex111)) + - [#3626](https://github.com/facebook/docusaurus/pull/3626) refactor(v2): remove focus outline from mouse users ([@lex111](https://github.com/lex111)) +- `docusaurus-init` + - [#3709](https://github.com/facebook/docusaurus/pull/3709) chore(v2): adjust website npm package ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#3707](https://github.com/facebook/docusaurus/pull/3707) chore(v2): upgrade Infima to v0.2.0-alpha.14 ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus` + - [#3638](https://github.com/facebook/docusaurus/pull/3638) chore(v2): migrate hapi/joi to joi ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-search-algolia` + - [#3604](https://github.com/facebook/docusaurus/pull/3604) refactor(v2): use new way to get versions for search page ([@lex111](https://github.com/lex111)) + +#### :memo: Documentation + +- Other + - [#3762](https://github.com/facebook/docusaurus/pull/3762) Adding ConfigCat to showcase ([@sigewuzhere](https://github.com/sigewuzhere)) + - [#3750](https://github.com/facebook/docusaurus/pull/3750) docs(v2): add npm2yarn to typescript install command ([@davidjgoss](https://github.com/davidjgoss)) + - [#3743](https://github.com/facebook/docusaurus/pull/3743) docs(v2): convert teams page to MDX ([@slorber](https://github.com/slorber)) + - [#3737](https://github.com/facebook/docusaurus/pull/3737) docs(v2): add Inline SVG color override example ([@Simek](https://github.com/Simek)) + - [#3718](https://github.com/facebook/docusaurus/pull/3718) docs(v2): showcase Botonic ([@vanbasten17](https://github.com/vanbasten17)) + - [#3696](https://github.com/facebook/docusaurus/pull/3696) docs(v2): normalize showcase preview images height ([@Simek](https://github.com/Simek)) + - [#3699](https://github.com/facebook/docusaurus/pull/3699) docs(v2): deployment should use mdx extension ([@slorber](https://github.com/slorber)) + - [#3695](https://github.com/facebook/docusaurus/pull/3695) docs(v2): add React Native website to the showcase ([@Simek](https://github.com/Simek)) + - [#3645](https://github.com/facebook/docusaurus/pull/3645) Update Docusaurus v2 Showcase ([@ndom91](https://github.com/ndom91)) + - [#3644](https://github.com/facebook/docusaurus/pull/3644) docs(v2): update the link of joi ([@kenve](https://github.com/kenve)) + - [#3636](https://github.com/facebook/docusaurus/pull/3636) docs(v2): fix some misspellings ([@ka1bi4](https://github.com/ka1bi4)) + - [#3630](https://github.com/facebook/docusaurus/pull/3630) docs: remove runme ([@juzhiyuan](https://github.com/juzhiyuan)) +- `docusaurus-remark-plugin-npm2yarn` + - [#3624](https://github.com/facebook/docusaurus/pull/3624) Fix typo in remark-plugin-npm2yarn documentation ([@belemaire](https://github.com/belemaire)) + +#### :house: Internal + +- Other + - [#3769](https://github.com/facebook/docusaurus/pull/3769) docs(v2): fix statements background, update footer background ([@Simek](https://github.com/Simek)) + - [#3744](https://github.com/facebook/docusaurus/pull/3744) chore(v2): add build size bot workflow GitHub CI workflow ([@jcs98](https://github.com/jcs98)) + - [#3741](https://github.com/facebook/docusaurus/pull/3741) chore: update yarn lock again ([@slorber](https://github.com/slorber)) + - [#3740](https://github.com/facebook/docusaurus/pull/3740) chore: update yarn lock ([@slorber](https://github.com/slorber)) + - [#3738](https://github.com/facebook/docusaurus/pull/3738) chore(internal): add yarn deduplicate script, cleanup lock ([@Simek](https://github.com/Simek)) + - [#3732](https://github.com/facebook/docusaurus/pull/3732) fix(internal): fix clear script from the main package.json ([@Simek](https://github.com/Simek)) + - [#3708](https://github.com/facebook/docusaurus/pull/3708) chore(v2): remove docs for alpha v60-61 ([@lex111](https://github.com/lex111)) + - [#3693](https://github.com/facebook/docusaurus/pull/3693) fix(v2): fix website scripts on Windows by using cross-env ([@Simek](https://github.com/Simek)) + - [#3673](https://github.com/facebook/docusaurus/pull/3673) test(e2e): dogfood Yarn with enableGlobalCache ([@ylemkimon](https://github.com/ylemkimon)) + - [#3641](https://github.com/facebook/docusaurus/pull/3641) misc: fix unbound env variable in test release script ([@lex111](https://github.com/lex111)) +- `docusaurus-mdx-loader`, `docusaurus-migrate`, `lqip-loader` + - [#3766](https://github.com/facebook/docusaurus/pull/3766) chore(v2): fix several npm warnings ([@lex111](https://github.com/lex111)) +- `docusaurus-mdx-loader` + - [#3753](https://github.com/facebook/docusaurus/pull/3753) chore(v2): fix mismatch peer dependency in MDX loader ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#3742](https://github.com/facebook/docusaurus/pull/3742) chore(v2): pin version of babel-plugin-dynamic-import-node to 2.3.0 ([@lex111](https://github.com/lex111)) + - [#3734](https://github.com/facebook/docusaurus/pull/3734) chore(v2): downgrade babel-plugin-dynamic-import-node to 2.3.0 ([@lex111](https://github.com/lex111)) + - [#3714](https://github.com/facebook/docusaurus/pull/3714) chore(v2): fix prettier formatting ([@slorber](https://github.com/slorber)) + - [#3619](https://github.com/facebook/docusaurus/pull/3619) refactor(v2): add better error message for yarn workspace/monorepo/terser issue ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-pwa`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#3727](https://github.com/facebook/docusaurus/pull/3727) chore(v2): upgrade dependencies ([@lex111](https://github.com/lex111)) +- `docusaurus-1.x` + - [#3715](https://github.com/facebook/docusaurus/pull/3715) chore(v2): update Browserslist ([@lex111](https://github.com/lex111)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-sitemap` + - [#3675](https://github.com/facebook/docusaurus/pull/3675) fix(v2): add missing 'react' and 'webpack' peer dependencies ([@ylemkimon](https://github.com/ylemkimon)) +- `docusaurus-1.x`, `docusaurus-init-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` + - [#3613](https://github.com/facebook/docusaurus/pull/3613) fix: add repository metadata to all packages ([@rarkins](https://github.com/rarkins)) + +#### Committers: 26 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Anh Hong ([@hong4rc](https://github.com/hong4rc)) +- Artem Kovalov ([@artemkovalyov](https://github.com/artemkovalyov)) +- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) +- Benoît Lemaire ([@belemaire](https://github.com/belemaire)) +- Bright Egbo ([@egbobright](https://github.com/egbobright)) +- Charles Korn ([@charleskorn](https://github.com/charleskorn)) +- David Goss ([@davidjgoss](https://github.com/davidjgoss)) +- Gergely Sinka ([@sigewuzhere](https://github.com/sigewuzhere)) +- Hai ([@haivp3010](https://github.com/haivp3010)) +- Jainam Chirag Shah ([@jcs98](https://github.com/jcs98)) +- Marc Rabat Pla ([@vanbasten17](https://github.com/vanbasten17)) +- Nate Giraudeau ([@nategiraudeau](https://github.com/nategiraudeau)) +- Nico Domino ([@ndom91](https://github.com/ndom91)) +- Rhys Arkins ([@rarkins](https://github.com/rarkins)) +- Roman Bug ([@ka1bi4](https://github.com/ka1bi4)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Shenwei Wang ([@weareoutman](https://github.com/weareoutman)) +- Stephen McElhinney ([@smcelhinney](https://github.com/smcelhinney)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Thakur Karthik ([@ThakurKarthik](https://github.com/ThakurKarthik)) +- [@sammychinedu2ky](https://github.com/sammychinedu2ky) +- iAmir ([@AmyrAhmady](https://github.com/AmyrAhmady)) +- kenve ([@kenve](https://github.com/kenve)) +- ylemkimon ([@ylemkimon](https://github.com/ylemkimon)) +- 琚致远 ([@juzhiyuan](https://github.com/juzhiyuan)) + +## 2.0.0-alpha.67 (2020-11-18) + +Failed release + +## 2.0.0-alpha.66 (2020-10-19) + +#### :rocket: New Feature + +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#3593](https://github.com/facebook/docusaurus/pull/3593) feat(v2): blog sidebar ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader`, `docusaurus-remark-plugin-npm2yarn` + - [#3469](https://github.com/facebook/docusaurus/pull/3469) feat(v2): Extract npm2yarn plugin ([@fanny](https://github.com/fanny)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#3550](https://github.com/facebook/docusaurus/pull/3550) feat(v2): contextual search, dynamic Algolia facetFilters ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#3580](https://github.com/facebook/docusaurus/pull/3580) feat(v2): allow to define custom CSS class for Tabs component ([@Simek](https://github.com/Simek)) + - [#3553](https://github.com/facebook/docusaurus/pull/3553) feat(v2): make dropdown menu collapsible on mobiles ([@lex111](https://github.com/lex111)) +- `docusaurus-migrate`, `docusaurus-types`, `docusaurus` + - [#3573](https://github.com/facebook/docusaurus/pull/3573) feat(v2): Add themeConfig.noIndex option #3528 ([@hamzahamidi](https://github.com/hamzahamidi)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus` + - [#3543](https://github.com/facebook/docusaurus/pull/3543) feat(v2): persist docs preferred version ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus` + - [#3548](https://github.com/facebook/docusaurus/pull/3548) feat(v2): version dropdown before/after items + move site "All Versions" link ([@slorber](https://github.com/slorber)) +- `docusaurus-types`, `docusaurus` + - [#3545](https://github.com/facebook/docusaurus/pull/3545) feat(v2): site client modules ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#3539](https://github.com/facebook/docusaurus/pull/3539) feat(v2): doc navbar item type ([@slorber](https://github.com/slorber)) + +#### :boom: Breaking Change + +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#3550](https://github.com/facebook/docusaurus/pull/3550) feat(v2): contextual search, dynamic Algolia facetFilters ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic`, `docusaurus` + - [#3607](https://github.com/facebook/docusaurus/pull/3607) fix(v2): fix error with required href attr of link in mobiles ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#3602](https://github.com/facebook/docusaurus/pull/3602) fix(v2): make dropdown button clickable with mouse ([@lex111](https://github.com/lex111)) + - [#3601](https://github.com/facebook/docusaurus/pull/3601) fix(v2): fix table-of-content scroll highlighting issues ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` + - [#3599](https://github.com/facebook/docusaurus/pull/3599) fix(v2): remove event listeners on Tabs component unmount ([@lex111](https://github.com/lex111)) +- `docusaurus-types`, `docusaurus` + - [#3531](https://github.com/facebook/docusaurus/pull/3531) fix(v2): Fixes serve cli --port option ([@UmairKamran](https://github.com/UmairKamran)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#3585](https://github.com/facebook/docusaurus/pull/3585) refactor(v2): various dropdown improvements ([@lex111](https://github.com/lex111)) + - [#3588](https://github.com/facebook/docusaurus/pull/3588) refactor(v2): make accessible copy code button from keyboard ([@lex111](https://github.com/lex111)) + - [#3578](https://github.com/facebook/docusaurus/pull/3578) refactor(v2): apply common behavior to dropdowns ([@lex111](https://github.com/lex111)) + - [#3546](https://github.com/facebook/docusaurus/pull/3546) docs: various fixes and improvements ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus` + - [#3587](https://github.com/facebook/docusaurus/pull/3587) refactor(v2): various fixes ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#3569](https://github.com/facebook/docusaurus/pull/3569) refactor(v2): improve broken links error message ([@slorber](https://github.com/slorber)) + +#### :memo: Documentation + +- Other + - [#3576](https://github.com/facebook/docusaurus/pull/3576) docs(v2): removed obsolete "you" identifier ([@christian-bromann](https://github.com/christian-bromann)) + - [#3589](https://github.com/facebook/docusaurus/pull/3589) docs(v2): add taro to users ([@honlyHuang](https://github.com/honlyHuang)) + - [#3565](https://github.com/facebook/docusaurus/pull/3565) docs(v2): deployment, add required GitHub token scope infos ([@russtaylor](https://github.com/russtaylor)) + - [#3574](https://github.com/facebook/docusaurus/pull/3574) docs(v2): adding vue-nodegui to users ([@shubhamzanwar](https://github.com/shubhamzanwar)) + - [#3556](https://github.com/facebook/docusaurus/pull/3556) Added Axioms to users ([@abhishektiwari](https://github.com/abhishektiwari)) + - [#3558](https://github.com/facebook/docusaurus/pull/3558) docs(v2): embedding real source code in MDX as a code block ([@slorber](https://github.com/slorber)) + - [#3555](https://github.com/facebook/docusaurus/pull/3555) docs(v2): add "Wisdom" dev docs website to showcase. ([@jagracey](https://github.com/jagracey)) + - [#3532](https://github.com/facebook/docusaurus/pull/3532) docs(v2): change package name in example script ([@MatanBobi](https://github.com/MatanBobi)) + - [#3538](https://github.com/facebook/docusaurus/pull/3538) docs(v1): added drone for 1.0 #3491 ([@aakhtar3](https://github.com/aakhtar3)) + - [#3533](https://github.com/facebook/docusaurus/pull/3533) docs(v1): Fix broken link in the documentation ([@saintmalik](https://github.com/saintmalik)) + - [#3534](https://github.com/facebook/docusaurus/pull/3534) docs(v2): Fix url bugs in v2 docs ([@saintmalik](https://github.com/saintmalik)) +- `docusaurus-theme-classic` + - [#3546](https://github.com/facebook/docusaurus/pull/3546) docs: various fixes and improvements ([@lex111](https://github.com/lex111)) + +#### :house: Internal + +- `docusaurus-theme-search-algolia` + - [#3591](https://github.com/facebook/docusaurus/pull/3591) chore(v2): enable new contextual search feature ([@slorber](https://github.com/slorber)) +- Other + - [#3586](https://github.com/facebook/docusaurus/pull/3586) chore(v2): fix/upgrade react types ([@slorber](https://github.com/slorber)) + - [#3577](https://github.com/facebook/docusaurus/pull/3577) refactor(v2): clarify versions page ([@lex111](https://github.com/lex111)) + - [#3560](https://github.com/facebook/docusaurus/pull/3560) feat(v2): prevent using remote image urls in showcase ([@slorber](https://github.com/slorber)) + - [#3554](https://github.com/facebook/docusaurus/pull/3554) fix(v2): use absolute path to manifest file ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#3394](https://github.com/facebook/docusaurus/pull/3394) refactor(v2): add useThemeConfig hook + cleanup useless theme default values ([@imskr](https://github.com/imskr)) + +#### Committers: 17 + +- Abhishek Tiwari ([@abhishektiwari](https://github.com/abhishektiwari)) +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) +- Christian Bromann ([@christian-bromann](https://github.com/christian-bromann)) +- Fanny ([@fanny](https://github.com/fanny)) +- Hamza Hamidi ([@hamzahamidi](https://github.com/hamzahamidi)) +- John Gracey ([@jagracey](https://github.com/jagracey)) +- Matan Borenkraout ([@MatanBobi](https://github.com/MatanBobi)) +- Russ Taylor ([@russtaylor](https://github.com/russtaylor)) +- SaintMalik ([@saintmalik](https://github.com/saintmalik)) +- Shubham Kumar ([@imskr](https://github.com/imskr)) +- Shubham Zanwar ([@shubhamzanwar](https://github.com/shubhamzanwar)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Umair Kamran ([@UmairKamran](https://github.com/UmairKamran)) +- Utkarsh Goel ([@utkarsh867](https://github.com/utkarsh867)) +- [@aakhtar3](https://github.com/aakhtar3) +- honlyHuang ([@honlyHuang](https://github.com/honlyHuang)) + +## 2.0.0-alpha.65 (2020-10-02) + +#### :rocket: New Feature + +- `docusaurus` + - [#3497](https://github.com/facebook/docusaurus/pull/3497) feat(v2): env variable TERSER_PARALLEL to customize TerserPlugin.parallel ([@aeneasr](https://github.com/aeneasr)) + - [#3446](https://github.com/facebook/docusaurus/pull/3446) feat(v2): new docusaurus clear command ([@abadon7](https://github.com/abadon7)) + - [#3485](https://github.com/facebook/docusaurus/pull/3485) feat(v2): Add @theme-init components to user theme ([@edno](https://github.com/edno)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages` + - [#3467](https://github.com/facebook/docusaurus/pull/3467) feat(v2): add beforeDefaultRemarkPlugins/beforeDefaultRehypePlugins options to all md content plugins ([@ayshiff](https://github.com/ayshiff)) +- `docusaurus-init`, `docusaurus-theme-bootstrap` + - [#3496](https://github.com/facebook/docusaurus/pull/3496) feat(v2): migrate bootstrap components to ts ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#3474](https://github.com/facebook/docusaurus/pull/3474) feat(v2): allow to use array of files in customCss field ([@Simek](https://github.com/Simek)) +- `docusaurus-plugin-content-pages`, `docusaurus-theme-classic` + - [#3457](https://github.com/facebook/docusaurus/pull/3457) feat(v2): add optional custom wrapper class name for pages based on theme classic Layout ([@Simek](https://github.com/Simek)) + +#### :bug: Bug Fix + +- Other + - [#3517](https://github.com/facebook/docusaurus/pull/3517) fix(v1): v1 deploy preview should be available ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#3498](https://github.com/facebook/docusaurus/pull/3498) fix(v2): fixed props being passed to @svgr/webpack loader ([@anru](https://github.com/anru)) +- `docusaurus-theme-search-algolia` + - [#3456](https://github.com/facebook/docusaurus/pull/3456) fix(v2): use valid value for crossorigin attribute ([@lex111](https://github.com/lex111)) +- `docusaurus-utils` + - [#3427](https://github.com/facebook/docusaurus/pull/3427) fix(v2): normalizeUrl edge cases ([@ayshiff](https://github.com/ayshiff)) +- `docusaurus-theme-classic` + - [#3472](https://github.com/facebook/docusaurus/pull/3472) fix(v2): Show dropdown instead of a single button when there are two versions ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-plugin-content-docs` + - [#3441](https://github.com/facebook/docusaurus/pull/3441) fix(v2): fixing typo in error message ([@ayonious](https://github.com/ayonious)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#3499](https://github.com/facebook/docusaurus/pull/3499) chore(v2): upgrade Infima to 0.2.0-alpha.13 ([@lex111](https://github.com/lex111)) + +#### :memo: Documentation + +- `docusaurus` + - [#3502](https://github.com/facebook/docusaurus/pull/3502) docs(v2): add doc for wrapping theme components with @theme-original and @theme-init ([@slorber](https://github.com/slorber)) +- Other + - [#3473](https://github.com/facebook/docusaurus/pull/3473) misc: add License to the documentation ([@muskanvk](https://github.com/muskanvk)) + - [#3492](https://github.com/facebook/docusaurus/pull/3492) docs(v2): Added drone.io publish docs #3491 ([@aakhtar3](https://github.com/aakhtar3)) + - [#3479](https://github.com/facebook/docusaurus/pull/3479) docs(v2): remove redundant new line in code block ([@lex111](https://github.com/lex111)) + - [#3448](https://github.com/facebook/docusaurus/pull/3448) chore(v2): fix theme classic navbar style docs ([@Simek](https://github.com/Simek)) + +#### :house: Internal + +- `docusaurus-1.x`, `docusaurus-migrate` + - [#3504](https://github.com/facebook/docusaurus/pull/3504) chore(v1): move v1 docs inside website-1.x ([@slorber](https://github.com/slorber)) +- Other + - [#3506](https://github.com/facebook/docusaurus/pull/3506) chore(v2): v2 website should make it easy to contribute to upstream docs ([@slorber](https://github.com/slorber)) + - [#3511](https://github.com/facebook/docusaurus/pull/3511) misc: update CODEOWNERS ([@yangshun](https://github.com/yangshun)) + - [#3477](https://github.com/facebook/docusaurus/pull/3477) chore(v2): remove alpha 58 doc ([@lex111](https://github.com/lex111)) +- `docusaurus-utils-validation` + - [#3453](https://github.com/facebook/docusaurus/pull/3453) test(v2): add protocol relative uri validation test ([@moonrailgun](https://github.com/moonrailgun)) + +#### Committers: 18 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Andrey Rublev ([@anru](https://github.com/anru)) +- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) +- Grégory Heitz ([@edno](https://github.com/edno)) +- Henry Vélez ([@abadon7](https://github.com/abadon7)) +- Jeremy Hager ([@jeremyhager](https://github.com/jeremyhager)) +- Joel Marcey ([@JoelMarcey](https://github.com/JoelMarcey)) +- Long Ho ([@longlho](https://github.com/longlho)) +- Muskan Kumar ([@muskanvk](https://github.com/muskanvk)) +- Nahiyan Kamal ([@ayonious](https://github.com/ayonious)) +- Rémi Doreau ([@ayshiff](https://github.com/ayshiff)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tim Gates ([@timgates42](https://github.com/timgates42)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) +- [@aakhtar3](https://github.com/aakhtar3) +- hackerman ([@aeneasr](https://github.com/aeneasr)) +- moonrailgun ([@moonrailgun](https://github.com/moonrailgun)) + +## 2.0.0-alpha.64 (2020-09-11) + +#### :rocket: New Feature + +- `docusaurus-theme-classic` + - [#3432](https://github.com/facebook/docusaurus/pull/3432) feat(v2): add style property to theme-classic navbar ([@Simek](https://github.com/Simek)) + - [#3406](https://github.com/facebook/docusaurus/pull/3406) feat(v2): ability to add/override theme html metadatas ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-sitemap` + - [#3426](https://github.com/facebook/docusaurus/pull/3426) feat(v2): add option to add trailing slash to urls in sitemap ([@mpsq](https://github.com/mpsq)) + +#### :bug: Bug Fix + +- Other + - [#3438](https://github.com/facebook/docusaurus/pull/3438) fix(v2): docusaurus 2 PWA should work under baseurl (deploy previews) ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader` + - [#3435](https://github.com/facebook/docusaurus/pull/3435) fix(v2): fix empty link error message ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-pwa` + - [#3436](https://github.com/facebook/docusaurus/pull/3436) fix(v2): Correctly resolve sw.js path on windows ([@ashscodes](https://github.com/ashscodes)) +- `docusaurus-theme-classic` + - [#3433](https://github.com/facebook/docusaurus/pull/3433) fix(v2): fix theme-classic announcement bar closeable style ([@Simek](https://github.com/Simek)) +- `docusaurus-1.x` + - [#3429](https://github.com/facebook/docusaurus/pull/3429) fix(v1): versioned_docs and skip-next-release relative path issue ([@josephMG](https://github.com/josephMG)) +- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` + - [#3418](https://github.com/facebook/docusaurus/pull/3418) fix(v2): reset sidebar state on sidebar changes ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-debug` + - [#3405](https://github.com/facebook/docusaurus/pull/3405) fix(v2): fix debug plugin unscoped inline code global css ([@slorber](https://github.com/slorber)) + +#### :memo: Documentation + +- [#3428](https://github.com/facebook/docusaurus/pull/3428) docs(v2): fix grammar ([@thadguidry](https://github.com/thadguidry)) +- [#3425](https://github.com/facebook/docusaurus/pull/3425) docs(v2): mention Eta in ssrTemplate section ([@mpsq](https://github.com/mpsq)) +- [#3423](https://github.com/facebook/docusaurus/pull/3423) docs(v2): minor typo fix ([@rutikwankhade](https://github.com/rutikwankhade)) + +#### :house: Internal + +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus` + - [#3439](https://github.com/facebook/docusaurus/pull/3439) chore(v2): fix serialize-javascript security issue by upgrading webpack/workbox ([@slorber](https://github.com/slorber)) +- Other + - [#3401](https://github.com/facebook/docusaurus/pull/3401) chore(deps): bump decompress from 4.2.0 to 4.2.1 ([@dependabot[bot]](https://github.com/apps/dependabot)) + +#### Committers: 7 + +- Ash ([@ashscodes](https://github.com/ashscodes)) +- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) +- Méril ([@mpsq](https://github.com/mpsq)) +- Rutik Wankhade ([@rutikwankhade](https://github.com/rutikwankhade)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Thad Guidry ([@thadguidry](https://github.com/thadguidry)) +- [@josephMG](https://github.com/josephMG) + +## 2.0.0-alpha.63 (2020-09-03) + +#### :rocket: New Feature + +- `docusaurus-types`, `docusaurus` + - [#3387](https://github.com/facebook/docusaurus/pull/3387) feat(v2): allow users to specify a custom ssr HTML template ([@mpsq](https://github.com/mpsq)) +- `docusaurus-plugin-debug` + - [#3392](https://github.com/facebook/docusaurus/pull/3392) feat(v2): officially release @docusaurus/plugin-debug ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#3388](https://github.com/facebook/docusaurus/pull/3388) feat(v2): add isCloseable property for theme-classic announcement bar ([@Simek](https://github.com/Simek)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#3373](https://github.com/facebook/docusaurus/pull/3373) feat(v2): docs options.onlyIncludeVersions ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- Other + - [#3397](https://github.com/facebook/docusaurus/pull/3397) fix(v2): DocSearch should keep working after a new release (part 2/2) ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#3393](https://github.com/facebook/docusaurus/pull/3393) fix(v2): DocSearch should keep working after a new release (part 1/2) ([@slorber](https://github.com/slorber)) + - [#3381](https://github.com/facebook/docusaurus/pull/3381) fix(v2): alpha 62 doc fixes ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#3385](https://github.com/facebook/docusaurus/pull/3385) fix(v2): scripts should allow unknown values ([@slorber](https://github.com/slorber)) +- `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus` + - [#3382](https://github.com/facebook/docusaurus/pull/3382) fix(v2): allow using classic theme/preset without the docs plugin ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils-validation` + - [#3377](https://github.com/facebook/docusaurus/pull/3377) fix(v2): reject routeBasePath: '' ([@slorber](https://github.com/slorber)) + +#### :memo: Documentation + +- [#3390](https://github.com/facebook/docusaurus/pull/3390) docs(v1, v2): Update Deploy to Vercel guide ([@samsisle](https://github.com/samsisle)) +- [#3344](https://github.com/facebook/docusaurus/pull/3344) docs(v2): Update Deploy to Vercel guide ([@samsisle](https://github.com/samsisle)) + +#### :house: Internal + +- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus` + - [#3386](https://github.com/facebook/docusaurus/pull/3386) chore(v2): pin exact dependency versions ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x`, `docusaurus-init-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` + - [#3359](https://github.com/facebook/docusaurus/pull/3359) chore(v2): prepare v2.0.0.alpha-62 release ([@slorber](https://github.com/slorber)) + +#### Committers: 5 + +- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) +- Méril ([@mpsq](https://github.com/mpsq)) +- Sam Ko ([@samsisle](https://github.com/samsisle)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Thad Guidry ([@thadguidry](https://github.com/thadguidry)) + +## 2.0.0-alpha.62 (2020-08-28) + +#### :rocket: New Feature + +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#3357](https://github.com/facebook/docusaurus/pull/3357) feat(v2): docs version configuration: lastVersion, version.{path,label} ([@slorber](https://github.com/slorber)) + - [#3328](https://github.com/facebook/docusaurus/pull/3328) feat(v2): Provide docs plugin theme typing ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-theme-classic` + - [#3356](https://github.com/facebook/docusaurus/pull/3356) feat(v2): Provide type definitions for remaining theme-classic components ([@SamChou19815](https://github.com/SamChou19815)) + - [#3274](https://github.com/facebook/docusaurus/pull/3274) feat(v2): add TOC to blog posts ([@amy-lei](https://github.com/amy-lei)) +- `docusaurus-plugin-content-pages`, `docusaurus-theme-classic` + - [#3354](https://github.com/facebook/docusaurus/pull/3354) feat(v2): Provide type definitions for MDXPage from page plugin ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#3348](https://github.com/facebook/docusaurus/pull/3348) feat(v2): Provide typing to most of the theme-classic components ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-init`, `docusaurus-plugin-content-blog` + - [#3284](https://github.com/facebook/docusaurus/pull/3284) feat(v2): blog slug frontmatter ([@JeanMarcSaad](https://github.com/JeanMarcSaad)) +- `docusaurus-init`, `docusaurus-theme-bootstrap` + - [#2981](https://github.com/facebook/docusaurus/pull/2981) feat(v2): bootstrap theme, preset, template, CI previews ([@fanny](https://github.com/fanny)) +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#3267](https://github.com/facebook/docusaurus/pull/3267) feat(v2): Provide blog plugin theme typing ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-debug`, `docusaurus-preset-classic`, `docusaurus-theme-bootstrap`, `docusaurus-types`, `docusaurus` + - [#3229](https://github.com/facebook/docusaurus/pull/3229) feat(v2): debug pages + debug layout + ability to debug content ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#3021](https://github.com/facebook/docusaurus/pull/3021) feat(v2): update swizzle command to suggest component/theme ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-pages` + - [#3196](https://github.com/facebook/docusaurus/pull/3196) feat(v2): add support to ignore files in pages plugin ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils-validation`, `docusaurus` + - [#3204](https://github.com/facebook/docusaurus/pull/3204) feat(v2): blog + docs multi-instance plugins ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader` + - [#3096](https://github.com/facebook/docusaurus/pull/3096) feat(v2): add support to import assets using relative link in markdown syntax ([@anshulrgoyal](https://github.com/anshulrgoyal)) + +#### :bug: Bug Fix + +- `docusaurus-migrate` + - [#3358](https://github.com/facebook/docusaurus/pull/3358) fix(v2): fix migrate cli paths (sidebars/customcss) ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#3311](https://github.com/facebook/docusaurus/pull/3311) fix(v2): add https support in webpack devserver ([@arcvats](https://github.com/arcvats)) + - [#3313](https://github.com/facebook/docusaurus/pull/3313) fix(v2): resolve webpack loaders from siteDir/node_modules ([@anshulrgoyal](https://github.com/anshulrgoyal)) + - [#3308](https://github.com/facebook/docusaurus/pull/3308) fix(v2): brokenLinks should not report links that belong to an existing folder if folder/index.html exists ([@slorber](https://github.com/slorber)) + - [#3273](https://github.com/facebook/docusaurus/pull/3273) fix: logic error while deciding deploymentBranch ([@thehanimo](https://github.com/thehanimo)) + - [#3281](https://github.com/facebook/docusaurus/pull/3281) fix(v2): allow swizzling of component even if case doesn't match ([@anshulrgoyal](https://github.com/anshulrgoyal)) + - [#3222](https://github.com/facebook/docusaurus/pull/3222) fix(v2): update react-loadable-ssr-addon to solve yarn2 error ([@slorber](https://github.com/slorber)) + - [#3191](https://github.com/facebook/docusaurus/pull/3191) fix(v2): add missing `lodash.flatmap` dependency ([@ylemkimon](https://github.com/ylemkimon)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-bootstrap`, `docusaurus-theme-search-algolia`, `docusaurus-types` + - [#3355](https://github.com/facebook/docusaurus/pull/3355) fix(v2): Add missing dependencies to packages ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-theme-classic` + - [#3352](https://github.com/facebook/docusaurus/pull/3352) fix(v2): Allow the alt for the logo to be empty ([@Vinnl](https://github.com/Vinnl)) + - [#3240](https://github.com/facebook/docusaurus/pull/3240) fix(v2): navbar dropdown opened with tab, not closing on click outside ([@Ako92](https://github.com/Ako92)) +- `docusaurus-mdx-loader`, `docusaurus` + - [#3347](https://github.com/facebook/docusaurus/pull/3347) fix(v2): linking to asset or external html page -> don't use history.push() ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x` + - [#3340](https://github.com/facebook/docusaurus/pull/3340) fix(v1): show images after one line code block ([@adinaja](https://github.com/adinaja)) +- `docusaurus-1.x`, `docusaurus` + - [#3290](https://github.com/facebook/docusaurus/pull/3290) fix(v1,v2): Add initial-scale=1.0 to all meta viewport tags ([@nebrelbug](https://github.com/nebrelbug)) +- `docusaurus-theme-search-algolia` + - [#3297](https://github.com/facebook/docusaurus/pull/3297) fix(v2): keep DocSearch state on remounts ([@francoischalifour](https://github.com/francoischalifour)) + - [#3280](https://github.com/facebook/docusaurus/pull/3280) fix(v2): allow search page swizzle ([@Ako92](https://github.com/Ako92)) + - [#3263](https://github.com/facebook/docusaurus/pull/3263) fix(v2): do not index search pages ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-pages` + - [#3283](https://github.com/facebook/docusaurus/pull/3283) fix(v2): pass images in static dir to webpack-loader ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- Other + - [#3269](https://github.com/facebook/docusaurus/pull/3269) fix(v2): website feedback page hydration bug ([@mecm1993](https://github.com/mecm1993)) + - [#3200](https://github.com/facebook/docusaurus/pull/3200) fix(v1): self-host user images ([@leoigel](https://github.com/leoigel)) +- `docusaurus-plugin-google-gtag` + - [#3243](https://github.com/facebook/docusaurus/pull/3243) fix(v2): GTM, send page_view events on navigate ([@govardhan-srinivas](https://github.com/govardhan-srinivas)) +- `docusaurus-plugin-content-docs`, `docusaurus-utils` + - [#3262](https://github.com/facebook/docusaurus/pull/3262) fix(v2): doc path special char (space or other) should lead to a valid slug ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils-validation`, `docusaurus` + - [#3247](https://github.com/facebook/docusaurus/pull/3247) fix(v2): modify validation schema and tests for rehype/remark + remove duplicate dependency ([@teikjun](https://github.com/teikjun)) +- `docusaurus-init` + - [#3258](https://github.com/facebook/docusaurus/pull/3258) fix(v2): fix template alt image prop ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils-validation`, `docusaurus` + - [#3227](https://github.com/facebook/docusaurus/pull/3227) fix(v2): relax URI validation ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- `docusaurus-init`, `docusaurus-plugin-content-docs` + - [#3228](https://github.com/facebook/docusaurus/pull/3228) fix(v2): deprecate docs homePageId in favor of frontmatter "slug: /" ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus` + - [#3225](https://github.com/facebook/docusaurus/pull/3225) fix(v2): swizzle minor improvements ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#3210](https://github.com/facebook/docusaurus/pull/3210) fix(v2): fix theme validation for prism field and add tests ([@teikjun](https://github.com/teikjun)) +- `docusaurus-plugin-content-docs` + - [#3192](https://github.com/facebook/docusaurus/pull/3192) fix(v2): add missing `chalk` and `lodash` dependencies ([@ylemkimon](https://github.com/ylemkimon)) + +#### :nail_care: Polish + +- `docusaurus-module-type-aliases`, `docusaurus` + - [#3244](https://github.com/facebook/docusaurus/pull/3244) chore(v2): tighten up the TypeScript onboarding ([@orta](https://github.com/orta)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils`, `docusaurus` + - [#3245](https://github.com/facebook/docusaurus/pull/3245) refactor(v2): docs plugin refactor ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#3188](https://github.com/facebook/docusaurus/pull/3188) fix(v2): Add a missing whitespace before prompt to use `npm run serve` ([@SamChou19815](https://github.com/SamChou19815)) + +#### :memo: Documentation + +- Other + - [#3346](https://github.com/facebook/docusaurus/pull/3346) docs(v2): add draft doc ([@imskr](https://github.com/imskr)) + - [#3336](https://github.com/facebook/docusaurus/pull/3336) docs(v2): add Nisarag to Fellows section ([@FocalChord](https://github.com/FocalChord)) + - [#3335](https://github.com/facebook/docusaurus/pull/3335) docs(v2): update team profile ([@yangshun](https://github.com/yangshun)) + - [#3334](https://github.com/facebook/docusaurus/pull/3334) docs(v2): add Drew to Fellows section ([@Drewbi](https://github.com/Drewbi)) + - [#3333](https://github.com/facebook/docusaurus/pull/3333) docs(v2): add anshul and teikjun to fellows section of team page ([@teikjun](https://github.com/teikjun)) + - [#3326](https://github.com/facebook/docusaurus/pull/3326) docs(v1): showcase user Casbin ([@hsluoyz](https://github.com/hsluoyz)) + - [#3316](https://github.com/facebook/docusaurus/pull/3316) docs(v1): add Global CTO Forum to users ([@MirzayevFarid](https://github.com/MirzayevFarid)) + - [#3310](https://github.com/facebook/docusaurus/pull/3310) docs(v2): add "T-Regx" website to showcase ([@Danon](https://github.com/Danon)) + - [#3307](https://github.com/facebook/docusaurus/pull/3307) docs(v2): showcase SpotifyAPI-NET ([@JohnnyCrazy](https://github.com/JohnnyCrazy)) + - [#3295](https://github.com/facebook/docusaurus/pull/3295) docs(v2): showcase Oxidizer ([@vandreleal](https://github.com/vandreleal)) + - [#3287](https://github.com/facebook/docusaurus/pull/3287) docs: update README.md with some grammatical corrections ([@shalinikumari50](https://github.com/shalinikumari50)) + - [#3271](https://github.com/facebook/docusaurus/pull/3271) docs(v2): fix typo ([@thehanimo](https://github.com/thehanimo)) + - [#3277](https://github.com/facebook/docusaurus/pull/3277) docs(v1): Add Radity to users ([@tolunayakbulut](https://github.com/tolunayakbulut)) + - [#3276](https://github.com/facebook/docusaurus/pull/3276) docs: corrected some few typos in the docusaurus tech docs ([@ajifrank75](https://github.com/ajifrank75)) + - [#3249](https://github.com/facebook/docusaurus/pull/3249) docs(v2): fix migration command ([@BogdanDor](https://github.com/BogdanDor)) + - [#3248](https://github.com/facebook/docusaurus/pull/3248) Added twitter badge and modified discord Badges ([@Souravdey777](https://github.com/Souravdey777)) + - [#3251](https://github.com/facebook/docusaurus/pull/3251) docs(v2): fix migration command for earlier versions ([@teikjun](https://github.com/teikjun)) + - [#3252](https://github.com/facebook/docusaurus/pull/3252) docs(v2): docs typos ([@olawanlejoel](https://github.com/olawanlejoel)) + - [#3111](https://github.com/facebook/docusaurus/pull/3111) docs(v2): clarify theme-original and theme-init ([@Jonathannsegal](https://github.com/Jonathannsegal)) + - [#3232](https://github.com/facebook/docusaurus/pull/3232) docs(v2): showcase user QA-Board ([@arthur-flam](https://github.com/arthur-flam)) + - [#3205](https://github.com/facebook/docusaurus/pull/3205) docs: format reference links ([@lebogangolifant](https://github.com/lebogangolifant)) + - [#3194](https://github.com/facebook/docusaurus/pull/3194) docs(v2): Added switch config docs to theme-classic API ([@Drewbi](https://github.com/Drewbi)) + - [#3201](https://github.com/facebook/docusaurus/pull/3201) docs(v2): removed duplicate text under "Using React" section ([@boosh511](https://github.com/boosh511)) + - [#3186](https://github.com/facebook/docusaurus/pull/3186) docs(v1): formatting changelog ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#3202](https://github.com/facebook/docusaurus/pull/3202) fix(v2): fix svg loader ([@anshulrgoyal](https://github.com/anshulrgoyal)) + +#### :house: Internal + +- `docusaurus-migrate` + - [#3323](https://github.com/facebook/docusaurus/pull/3323) test(v2): Add unit test for migration of config file ([@BogdanDor](https://github.com/BogdanDor)) +- `docusaurus-theme-classic` + - [#3343](https://github.com/facebook/docusaurus/pull/3343) refactor(v2): announcement bar bad spelling + minor refactors ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog` + - [#3339](https://github.com/facebook/docusaurus/pull/3339) test(v2): make blog posts unit test ordering determinate ([@BogdanDor](https://github.com/BogdanDor)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-theme-classic`, `docusaurus-types` + - [#3306](https://github.com/facebook/docusaurus/pull/3306) chore(v2): Define type for markdown right table of contents ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-module-type-aliases`, `docusaurus` + - [#3244](https://github.com/facebook/docusaurus/pull/3244) chore(v2): tighten up the TypeScript onboarding ([@orta](https://github.com/orta)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils`, `docusaurus` + - [#3245](https://github.com/facebook/docusaurus/pull/3245) refactor(v2): docs plugin refactor ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#3282](https://github.com/facebook/docusaurus/pull/3282) chore(v2): fix javascript-serialize vulnerability ([@slorber](https://github.com/slorber)) + - [#3265](https://github.com/facebook/docusaurus/pull/3265) chore(v2): upgrade terser-webpack-plugin ([@dschaller](https://github.com/dschaller)) +- Other + - [#3241](https://github.com/facebook/docusaurus/pull/3241) chore(deps): bump prismjs from 1.20.0 to 1.21.0 ([@dependabot[bot]](https://github.com/apps/dependabot)) + - [#3259](https://github.com/facebook/docusaurus/pull/3259) chore(v2): fix slow commits due to lint-staged ([@slorber](https://github.com/slorber)) + - [#3197](https://github.com/facebook/docusaurus/pull/3197) chore(v2): lockfile update ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x` + - [#3218](https://github.com/facebook/docusaurus/pull/3218) chore(v1): release 1.14.6 ([@slorber](https://github.com/slorber)) + +#### :running_woman: Performance + +- `docusaurus-plugin-client-redirects`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#3238](https://github.com/facebook/docusaurus/pull/3238) refactor(v2): precompile ETA templates ([@slorber](https://github.com/slorber)) + +#### Committers: 39 + +- Ali Hosseini ([@Ako92](https://github.com/Ako92)) +- Amy Lei ([@amy-lei](https://github.com/amy-lei)) +- Anshul Goyal ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- Archit ([@arcvats](https://github.com/arcvats)) +- Arthur Flam ([@arthur-flam](https://github.com/arthur-flam)) +- Ben Gubler ([@nebrelbug](https://github.com/nebrelbug)) +- Bogdan Doroschenko ([@BogdanDor](https://github.com/BogdanDor)) +- Daniel Wilkowski ([@Danon](https://github.com/Danon)) +- Derek ([@dschaller](https://github.com/dschaller)) +- Drew Alexander ([@Drewbi](https://github.com/Drewbi)) +- Fanny ([@fanny](https://github.com/fanny)) +- Franklyn Chisom ([@ajifrank75](https://github.com/ajifrank75)) +- François Chalifour ([@francoischalifour](https://github.com/francoischalifour)) +- Govardhan Srinivas ([@govardhan-srinivas](https://github.com/govardhan-srinivas)) +- Hani Mohammed ([@thehanimo](https://github.com/thehanimo)) +- Jean-Marc Saad ([@JeanMarcSaad](https://github.com/JeanMarcSaad)) +- Jonas Dellinger ([@JohnnyCrazy](https://github.com/JohnnyCrazy)) +- Jonathan ([@Jonathannsegal](https://github.com/Jonathannsegal)) +- Manuel Cepeda ([@mecm1993](https://github.com/mecm1993)) +- Mirzayev Farid ([@MirzayevFarid](https://github.com/MirzayevFarid)) +- Nisarag ([@FocalChord](https://github.com/FocalChord)) +- Olawanle Joel ([@olawanlejoel](https://github.com/olawanlejoel)) +- Orta Therox ([@orta](https://github.com/orta)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Shubham Kumar ([@imskr](https://github.com/imskr)) +- Sourav Dey ([@Souravdey777](https://github.com/Souravdey777)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Teik Jun ([@teikjun](https://github.com/teikjun)) +- Tolunay Akbulut ([@tolunayakbulut](https://github.com/tolunayakbulut)) +- Vandré Leal ([@vandreleal](https://github.com/vandreleal)) +- Vincent ([@Vinnl](https://github.com/Vinnl)) +- Yang Luo ([@hsluoyz](https://github.com/hsluoyz)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) +- [@adinaja](https://github.com/adinaja) +- [@leoigel](https://github.com/leoigel) +- [@shalinikumari50](https://github.com/shalinikumari50) +- alex busnelli ([@boosh511](https://github.com/boosh511)) +- lebogang Olifant ([@lebogangolifant](https://github.com/lebogangolifant)) +- ylemkimon ([@ylemkimon](https://github.com/ylemkimon)) + +## 2.0.0-alpha.61 (2020-08-01) + +#### :rocket: New Feature + +- `docusaurus-types`, `docusaurus` + - [#3083](https://github.com/facebook/docusaurus/pull/3083) feat(v2): warn user when there are conflicting routes ([@teikjun](https://github.com/teikjun)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-utils-validation`, `docusaurus-utils` + - [#3158](https://github.com/facebook/docusaurus/pull/3158) feat(v2): markdown pages ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#3127](https://github.com/facebook/docusaurus/pull/3127) feat(v2): dark mode toggle customization ([@Drewbi](https://github.com/Drewbi)) +- `docusaurus-theme-search-algolia` + - [#3166](https://github.com/facebook/docusaurus/pull/3166) feat(v2): improve Algolia search accessibility ([@francoischalifour](https://github.com/francoischalifour)) +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#2359](https://github.com/facebook/docusaurus/pull/2359) feat(v2): support custom description for blog-only mode ([@zxuqian](https://github.com/zxuqian)) + +#### :bug: Bug Fix + +- `docusaurus-mdx-loader`, `docusaurus` + - [#3180](https://github.com/facebook/docusaurus/pull/3180) fix(v2): fix markdown images always using webpack url-loader ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#3171](https://github.com/facebook/docusaurus/pull/3171) fix(v2): tab label showing outline & background when clicked ([@mdfaizan7](https://github.com/mdfaizan7)) +- `docusaurus-init`, `docusaurus-theme-classic` + - [#3168](https://github.com/facebook/docusaurus/pull/3168) fix(v2): fix link items refusing attributes like target, rel etc... ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#3162](https://github.com/facebook/docusaurus/pull/3162) fix(v2): inability for users to pin their docusaurus version ([@BuckyMaler](https://github.com/BuckyMaler)) + +#### :memo: Documentation + +- [#3163](https://github.com/facebook/docusaurus/pull/3163) docs(v2): showcase user questdb ([@mpsq](https://github.com/mpsq)) + +#### :house: Internal + +- Other + - [#3164](https://github.com/facebook/docusaurus/pull/3164) chore(deps): bump elliptic from 6.5.2 to 6.5.3 ([@dependabot[bot]](https://github.com/apps/dependabot)) + - [#3157](https://github.com/facebook/docusaurus/pull/3157) chore(v2): remove alpha 59 doc ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x`, `docusaurus-init-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` + - [#3154](https://github.com/facebook/docusaurus/pull/3154) chore(v2): prepare v2.0.0.alpha-60 release ([@slorber](https://github.com/slorber)) + +#### Committers: 8 + +- Bucky Maler ([@BuckyMaler](https://github.com/BuckyMaler)) +- Drew Alexander ([@Drewbi](https://github.com/Drewbi)) +- Faizan ([@mdfaizan7](https://github.com/mdfaizan7)) +- François Chalifour ([@francoischalifour](https://github.com/francoischalifour)) +- Méril ([@mpsq](https://github.com/mpsq)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Teik Jun ([@teikjun](https://github.com/teikjun)) +- Xuqian ([@zxuqian](https://github.com/zxuqian)) + +## 2.0.0-alpha.60 (2020-07-29) + +#### :rocket: New Feature + +- `docusaurus` + - [#3134](https://github.com/facebook/docusaurus/pull/3134) feat(v2): add validation escape hatch ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x` + - [#3124](https://github.com/facebook/docusaurus/pull/3124) feat(v1): add 'slugPreprocessor' config option to allow users customize the hash links ([@Simek](https://github.com/Simek)) +- `docusaurus-theme-search-algolia` + - [#3133](https://github.com/facebook/docusaurus/pull/3133) feat(v2): add themeConfig validation to algolia theme ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus` + - [#3142](https://github.com/facebook/docusaurus/pull/3142) fix(v2): config validation fixes + add tests for config validation ([@teikjun](https://github.com/teikjun)) +- `docusaurus` + - [#3149](https://github.com/facebook/docusaurus/pull/3149) fix(v2): BrowserOnly should not return undefined ([@slorber](https://github.com/slorber)) + - [#3143](https://github.com/facebook/docusaurus/pull/3143) fix(v2): absolute Links should be automatically prefixed by baseurl ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` + - [#3141](https://github.com/facebook/docusaurus/pull/3141) fix(v2): remove buggy routesLoaded + deprecate routesLoaded lifecycle ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#3140](https://github.com/facebook/docusaurus/pull/3140) fix(v2): navbar item links should allow unknown attributes ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-search-algolia` + - [#3138](https://github.com/facebook/docusaurus/pull/3138) fix(v2): add accessible label for Algolia search button ([@hobadams](https://github.com/hobadams)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus` + - [#3120](https://github.com/facebook/docusaurus/pull/3120) fix(v2): make config validation less strict ([@teikjun](https://github.com/teikjun)) + +#### :memo: Documentation + +- [#3145](https://github.com/facebook/docusaurus/pull/3145) docs(v2): add myself to /team page + add TeamProfileCard component ([@slorber](https://github.com/slorber)) +- [#3146](https://github.com/facebook/docusaurus/pull/3146) docs(v2): prettier docs ([@slorber](https://github.com/slorber)) +- [#3116](https://github.com/facebook/docusaurus/pull/3116) chore(v2): docs updates after release ([@slorber](https://github.com/slorber)) + +#### :house: Internal + +- Other + - [#3130](https://github.com/facebook/docusaurus/pull/3130) chore(v2): remove old versions ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x`, `docusaurus-init-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` + - [#3114](https://github.com/facebook/docusaurus/pull/3114) chore(v2): prepare v2.0.0.alpha-59 release ([@slorber](https://github.com/slorber)) + +#### Committers: 4 + +- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) +- Hob Adams ([@hobadams](https://github.com/hobadams)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Teik Jun ([@teikjun](https://github.com/teikjun)) + +## 2.0.0-alpha.59 (2020-07-24) + +#### :rocket: New Feature + +- `docusaurus-migrate`, `docusaurus-plugin-client-redirects` + - [#3015](https://github.com/facebook/docusaurus/pull/3015) feat: automate migration from v1 to v2 ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- `docusaurus-init` + - [#3105](https://github.com/facebook/docusaurus/pull/3105) feat(v2): add docusaurus script for npm users ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-search-algolia` + - [#2815](https://github.com/facebook/docusaurus/pull/2815) feat(v2): introduce DocSearch v3 search ([@francoischalifour](https://github.com/francoischalifour)) +- `docusaurus-init`, `docusaurus-types`, `docusaurus` + - [#3059](https://github.com/facebook/docusaurus/pull/3059) feat(v2): broken links detection ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-utils` + - [#3084](https://github.com/facebook/docusaurus/pull/3084) feat(v2): absolute slugs and slug resolution system ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` + - [#3069](https://github.com/facebook/docusaurus/pull/3069) feat(v2): support for adding relative images and handling broken image links ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- `docusaurus-init`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-debug`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#2971](https://github.com/facebook/docusaurus/pull/2971) feat(v2): global data + useGlobalData + docs versions dropdown ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus` + - [#3080](https://github.com/facebook/docusaurus/pull/3080) feat(v2): add support for serve command ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-debug`, `docusaurus-types`, `docusaurus` + - [#3058](https://github.com/facebook/docusaurus/pull/3058) feat(v2): useDocusaurusContext().siteMetadata ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#3032](https://github.com/facebook/docusaurus/pull/3032) feat(v2): notify users when docusaurus version is outdated ([@teikjun](https://github.com/teikjun)) + - [#3033](https://github.com/facebook/docusaurus/pull/3033) feat(v2): add useBaseUrlUtils() hook ([@slorber](https://github.com/slorber)) + - [#3006](https://github.com/facebook/docusaurus/pull/3006) feat(v2): prompt user when default port is in use ([@taylorallen0913](https://github.com/taylorallen0913)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-debug`, `docusaurus` + - [#3050](https://github.com/facebook/docusaurus/pull/3050) feat(v2): Collect plugin versions to allow them to be inspected in debug plugin ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-theme-classic` + - [#3038](https://github.com/facebook/docusaurus/pull/3038) feat(v2): Support keywords meta in blog posts ([@dpkg](https://github.com/dpkg)) + - [#2974](https://github.com/facebook/docusaurus/pull/2974) feat(v2): Error when hooks depends on context is used outside of Layout ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-plugin-pwa`, `docusaurus` + - [#2205](https://github.com/facebook/docusaurus/pull/2205) feat(v2): Plugin for Offline/PWA support ([@codemonkey800](https://github.com/codemonkey800)) +- `docusaurus-plugin-ideal-image`, `docusaurus-types`, `docusaurus` + - [#2994](https://github.com/facebook/docusaurus/pull/2994) feat(v2): configureWebpack merge strategy + use file-loader for common asset types ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs` + - [#2989](https://github.com/facebook/docusaurus/pull/2989) feat(v2): add disableVersioning config to docs plugin ([@slorber](https://github.com/slorber)) + - [#2877](https://github.com/facebook/docusaurus/pull/2877) feat(v2): allow skipping build docs for next version ([@lex111](https://github.com/lex111)) +- `docusaurus-1.x` + - [#2955](https://github.com/facebook/docusaurus/pull/2955) feat(v1): add deletedDocs config to fix unwanted versioning fallback ([@aldeed](https://github.com/aldeed)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-types`, `docusaurus` + - [#2943](https://github.com/facebook/docusaurus/pull/2943) feat(v2): option and config validation life cycle method for official plugins ([@anshulrgoyal](https://github.com/anshulrgoyal)) + +#### :boom: Breaking Change + +- `docusaurus-init`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-debug`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#2971](https://github.com/facebook/docusaurus/pull/2971) feat(v2): global data + useGlobalData + docs versions dropdown ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus` + - [#3012](https://github.com/facebook/docusaurus/pull/3012) fix(v2): refactor color mode system ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus` + - [#3107](https://github.com/facebook/docusaurus/pull/3107) fix(v2): broken links detector: ignore existing folders ([@slorber](https://github.com/slorber)) + - [#3112](https://github.com/facebook/docusaurus/pull/3112) fix(v2): baseUrl is wrongly appended to anchor links ([@slorber](https://github.com/slorber)) + - [#3063](https://github.com/facebook/docusaurus/pull/3063) fix(v2): classify link hrefs with protocol identifier as internal ([@svtfrida](https://github.com/svtfrida)) +- `docusaurus-theme-classic` + - [#3106](https://github.com/facebook/docusaurus/pull/3106) fix(v2): dropdown navbar item: validation too strict ([@slorber](https://github.com/slorber)) + - [#3029](https://github.com/facebook/docusaurus/pull/3029) fix(v2): change description for blog post paginator ([@teikjun](https://github.com/teikjun)) +- `docusaurus-plugin-content-docs` + - [#3108](https://github.com/facebook/docusaurus/pull/3108) fix(v2): fix docs instance path typo ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-pages` + - [#3025](https://github.com/facebook/docusaurus/pull/3025) fix(v2):pass siteConfig as prop to pages ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- `docusaurus-init` + - [#3008](https://github.com/facebook/docusaurus/pull/3008) chore(v2): Add E2E test for yarn v2 ([@SamChou19815](https://github.com/SamChou19815)) +- Other + - [#3017](https://github.com/facebook/docusaurus/pull/3017) fix(v2): fix broken links on versions page ([@teikjun](https://github.com/teikjun)) +- `docusaurus-theme-classic`, `docusaurus` + - [#3012](https://github.com/facebook/docusaurus/pull/3012) fix(v2): refactor color mode system ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs`, `docusaurus-utils`, `docusaurus` + - [#3001](https://github.com/facebook/docusaurus/pull/3001) fix(v2): refactor routes.ts + add route hash for chunkNames key ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects`, `docusaurus-utils`, `docusaurus` + - [#3010](https://github.com/facebook/docusaurus/pull/3010) fix(v2): make client-redirect-plugin not baseUrl sensitive ([@teikjun](https://github.com/teikjun)) +- `docusaurus-1.x` + - [#2993](https://github.com/facebook/docusaurus/pull/2993) fix(relative path): last update date and by isn’t generated if localh… ([@amirulahmad](https://github.com/amirulahmad)) +- `docusaurus-plugin-client-redirects` + - [#2969](https://github.com/facebook/docusaurus/pull/2969) fix: fromExtensions and toExtensions translation when used with baseUrl ([@jknoxville](https://github.com/jknoxville)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic`, `docusaurus` + - [#3088](https://github.com/facebook/docusaurus/pull/3088) improve navbar menu ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader` + - [#3087](https://github.com/facebook/docusaurus/pull/3087) refactor(v2): async md image transformer + pathname protocol as an escape hatch ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-theme-live-codeblock`, `docusaurus-types` + - [#2970](https://github.com/facebook/docusaurus/pull/2970) feat(v2): add option validation for remaining official plugins ([@teikjun](https://github.com/teikjun)) +- `docusaurus` + - [#2987](https://github.com/facebook/docusaurus/pull/2987) chore(v2): use joi for config validation ([@anshulrgoyal](https://github.com/anshulrgoyal)) + +#### :memo: Documentation + +- [#3026](https://github.com/facebook/docusaurus/pull/3026) docs(v2): add documentation for migration command ([@teikjun](https://github.com/teikjun)) +- [#3094](https://github.com/facebook/docusaurus/pull/3094) docs(v2): showcase user Clutch ([@danielhochman](https://github.com/danielhochman)) +- [#3101](https://github.com/facebook/docusaurus/pull/3101) docs(v2):Add azure-pipelines CI guide ([@ayan-b](https://github.com/ayan-b)) +- [#3098](https://github.com/facebook/docusaurus/pull/3098) docs: Add azure-pipelines CI guide ([@ayan-b](https://github.com/ayan-b)) +- [#3086](https://github.com/facebook/docusaurus/pull/3086) doc(v2): replace heading position ([@eKhattak](https://github.com/eKhattak)) +- [#3082](https://github.com/facebook/docusaurus/pull/3082) fixing few typos and enhancing few sentences clarity ([@aladin002dz](https://github.com/aladin002dz)) +- [#3078](https://github.com/facebook/docusaurus/pull/3078) Updated link for #docusaurus-2-dev discord ([@jordanliu](https://github.com/jordanliu)) +- [#3076](https://github.com/facebook/docusaurus/pull/3076) docs(v2): showcase Runlet ([@vandreleal](https://github.com/vandreleal)) +- [#3040](https://github.com/facebook/docusaurus/pull/3040) docs(v2): correct the documentation for docs-only mode ([@teikjun](https://github.com/teikjun)) +- [#3034](https://github.com/facebook/docusaurus/pull/3034) docs(v2): showcase user Tasit ([@pcowgill](https://github.com/pcowgill)) +- [#3022](https://github.com/facebook/docusaurus/pull/3022) docs(v2): showcase Eta ([@nebrelbug](https://github.com/nebrelbug)) +- [#3011](https://github.com/facebook/docusaurus/pull/3011) docs(v1): external links ([@slorber](https://github.com/slorber)) +- [#2997](https://github.com/facebook/docusaurus/pull/2997) docs(v2): Document TypeScript support ([@SamChou19815](https://github.com/SamChou19815)) +- [#2973](https://github.com/facebook/docusaurus/pull/2973) docs(v2): Fix typo in markdown-features ([@ehsanjso](https://github.com/ehsanjso)) +- [#2991](https://github.com/facebook/docusaurus/pull/2991) Showcase Amphora Data ([@xtellurian](https://github.com/xtellurian)) +- [#2983](https://github.com/facebook/docusaurus/pull/2983) docs(v2): add plugin redirects production build note ([@slorber](https://github.com/slorber)) +- [#2967](https://github.com/facebook/docusaurus/pull/2967) docs(v2): fix typos in plugin-content examples ([@hi-matbub](https://github.com/hi-matbub)) +- [#2960](https://github.com/facebook/docusaurus/pull/2960) doc(v2): publish doc update after alpha.58 release ([@slorber](https://github.com/slorber)) +- [#2966](https://github.com/facebook/docusaurus/pull/2966) docs(v2): fix typo in plugin-content-pages example ([@hi-matbub](https://github.com/hi-matbub)) + +#### :house: Internal + +- `docusaurus-migrate` + - [#3113](https://github.com/facebook/docusaurus/pull/3113) chore(v2): ability to test the migration cli easily ([@slorber](https://github.com/slorber)) +- Other + - [#3099](https://github.com/facebook/docusaurus/pull/3099) fix(v2): netlify.toml shouldn't affect v1 site deployment config ([@slorber](https://github.com/slorber)) + - [#3068](https://github.com/facebook/docusaurus/pull/3068) chore(deps): bump lodash from 4.17.15 to 4.17.19 ([@dependabot[bot]](https://github.com/apps/dependabot)) + - [#2958](https://github.com/facebook/docusaurus/pull/2958) docs(v2): rename 2.0.0-alpha.57 to 2.0.0-alpha.58 ([@yangshun](https://github.com/yangshun)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus` + - [#3093](https://github.com/facebook/docusaurus/pull/3093) fix(v2): fix recent baseurl issues ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader` + - [#3087](https://github.com/facebook/docusaurus/pull/3087) refactor(v2): async md image transformer + pathname protocol as an escape hatch ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-pwa`, `docusaurus` + - [#3055](https://github.com/facebook/docusaurus/pull/3055) chore(v2): Adopt corejs 3 and only import at entry point ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-init`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-utils`, `docusaurus` + - [#2998](https://github.com/facebook/docusaurus/pull/2998) chore(v2): refactor yarn tsc to yarn build + add theme-classic watch mode ([@slorber](https://github.com/slorber)) +- `docusaurus-init` + - [#3008](https://github.com/facebook/docusaurus/pull/3008) chore(v2): Add E2E test for yarn v2 ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-plugin-content-docs`, `docusaurus-utils`, `docusaurus` + - [#3001](https://github.com/facebook/docusaurus/pull/3001) fix(v2): refactor routes.ts + add route hash for chunkNames key ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#3007](https://github.com/facebook/docusaurus/pull/3007) fix(v2): Add two missing docusaurus core babel dependency ([@SamChou19815](https://github.com/SamChou19815)) + - [#2987](https://github.com/facebook/docusaurus/pull/2987) chore(v2): use joi for config validation ([@anshulrgoyal](https://github.com/anshulrgoyal)) + - [#2950](https://github.com/facebook/docusaurus/pull/2950) chore(v2): Implement a simple E2E testing mechanism for `docusausus start` ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-theme-live-codeblock`, `docusaurus-types` + - [#2970](https://github.com/facebook/docusaurus/pull/2970) feat(v2): add option validation for remaining official plugins ([@teikjun](https://github.com/teikjun)) +- `docusaurus-theme-classic` + - [#2996](https://github.com/facebook/docusaurus/pull/2996) chore(v2): Merge devDependencies in theme-classic ([@SamChou19815](https://github.com/SamChou19815)) + - [#2977](https://github.com/facebook/docusaurus/pull/2977) chore(v2): Remove extraneous package-lock.json ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-plugin-client-redirects` + - [#2962](https://github.com/facebook/docusaurus/pull/2962) Feat: replace yup with joi for cleaner validation ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- `docusaurus-init`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#2976](https://github.com/facebook/docusaurus/pull/2976) chore(v2): Fix more eslint errors ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-sitemap`, `docusaurus-utils`, `docusaurus`, `lqip-loader` + - [#2972](https://github.com/facebook/docusaurus/pull/2972) chore(v2): Fix a lot of eslint warnings ([@SamChou19815](https://github.com/SamChou19815)) + +#### Committers: 25 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Amirul Ahmad ([@amirulahmad](https://github.com/amirulahmad)) +- Anshul Goyal ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- Arsalan Khattak ([@eKhattak](https://github.com/eKhattak)) +- Ayan Banerjee ([@ayan-b](https://github.com/ayan-b)) +- Ben Gubler ([@nebrelbug](https://github.com/nebrelbug)) +- Daniel Hochman ([@danielhochman](https://github.com/danielhochman)) +- Deepak Giri ([@dpkg](https://github.com/dpkg)) +- Eric Dobbertin ([@aldeed](https://github.com/aldeed)) +- François Chalifour ([@francoischalifour](https://github.com/francoischalifour)) +- Frida Hjelm ([@svtfrida](https://github.com/svtfrida)) +- Jeremy Asuncion ([@codemonkey800](https://github.com/codemonkey800)) +- John Knox ([@jknoxville](https://github.com/jknoxville)) +- Jordan Liu ([@jordanliu](https://github.com/jordanliu)) +- Mahfoudh Arous ([@aladin002dz](https://github.com/aladin002dz)) +- Paul Cowgill ([@pcowgill](https://github.com/pcowgill)) +- Rian Finnegan ([@xtellurian](https://github.com/xtellurian)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Taylor Allen ([@taylorallen0913](https://github.com/taylorallen0913)) +- Teik Jun ([@teikjun](https://github.com/teikjun)) +- Vandré Leal ([@vandreleal](https://github.com/vandreleal)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) +- ehsan jso ([@ehsanjso](https://github.com/ehsanjso)) +- matbub ([@hi-matbub](https://github.com/hi-matbub)) + +## 2.0.0-alpha.58 (2020-06-18) + +#### :rocket: New Feature + +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#2916](https://github.com/facebook/docusaurus/pull/2916) feat(v2): add a banner that links to latest version of documentation ([@teikjun](https://github.com/teikjun)) + - [#2682](https://github.com/facebook/docusaurus/pull/2682) feat(v2): expanded sidebar categories by default ([@jsjoeio](https://github.com/jsjoeio)) +- `docusaurus-plugin-debug`, `docusaurus-preset-classic` + - [#2928](https://github.com/facebook/docusaurus/pull/2928) feat(v2): Implement proof-of-concept Docusaurus Debug Dashboard ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-init`, `docusaurus` + - [#2903](https://github.com/facebook/docusaurus/pull/2903) feat(v2): Allow configuring babel via babel.config.js ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-plugin-client-redirects`, `docusaurus-utils` + - [#2793](https://github.com/facebook/docusaurus/pull/2793) feat(v2): docusaurus-plugin-client-redirects ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-live-codeblock` + - [#2826](https://github.com/facebook/docusaurus/pull/2826) feat(v2): allow adding components to react-live scope ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus` + - [#2856](https://github.com/facebook/docusaurus/pull/2856) feat(v2): allow specifying meta image for blog posts ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#2841](https://github.com/facebook/docusaurus/pull/2841) feat(v2): Allow swizzling prism-include-languages in theme-classic ([@SamChou19815](https://github.com/SamChou19815)) + +#### :boom: Breaking Change + +- `docusaurus-init`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#2895](https://github.com/facebook/docusaurus/pull/2895) chore(v2): replace classnames with clsx ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs` + - [#2861](https://github.com/facebook/docusaurus/pull/2861) fix(v2): do not create route for document that serve as docs home page ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#2682](https://github.com/facebook/docusaurus/pull/2682) feat(v2): expanded sidebar categories by default ([@jsjoeio](https://github.com/jsjoeio)) + +#### :bug: Bug Fix + +- `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` + - [#2905](https://github.com/facebook/docusaurus/pull/2905) fix(v2): fix docs homepage permalink issues ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#2932](https://github.com/facebook/docusaurus/pull/2932) fix(v2): Add hooks to detect window resize, toggle off sidebar and navbar in desktop ([@guillaumejacquart](https://github.com/guillaumejacquart)) + - [#2909](https://github.com/facebook/docusaurus/pull/2909) fix(v2): adjust anchor offset when routes switched ([@lex111](https://github.com/lex111)) + - [#2896](https://github.com/facebook/docusaurus/pull/2896) fix(v2): set correct canonical url for docs home page ([@lex111](https://github.com/lex111)) + - [#2893](https://github.com/facebook/docusaurus/pull/2893) fix(v2): Do not automatically change tab when a non-existing option is selected ([@SamChou19815](https://github.com/SamChou19815)) + - [#2888](https://github.com/facebook/docusaurus/pull/2888) fix(v2): restore styles for menu scrollbar ([@lex111](https://github.com/lex111)) + - [#2857](https://github.com/facebook/docusaurus/pull/2857) fix(v2): treat inline code in raw HTML as native element ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#2951](https://github.com/facebook/docusaurus/pull/2951) fix(v2): Add optional-chaining and nullish-coalescing babel plugin ([@SamChou19815](https://github.com/SamChou19815)) + - [#2921](https://github.com/facebook/docusaurus/pull/2921) fix(v2): upgrade react-loadable-ssr-addon ([@slorber](https://github.com/slorber)) + - [#2854](https://github.com/facebook/docusaurus/pull/2854) fix(v2): fix broken build when swizzled NotFound component exist ([@lex111](https://github.com/lex111)) + - [#2829](https://github.com/facebook/docusaurus/pull/2829) fix(v2): Fix plugin path resolution ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-preset-classic` + - [#2944](https://github.com/facebook/docusaurus/pull/2944) fix(v2): Declare @docusaurus-plugin-debug as dependency of preset classic ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-init` + - [#2902](https://github.com/facebook/docusaurus/pull/2902) feat(v2): add nojekyll file to static folder for all templates ([@teikjun](https://github.com/teikjun)) +- `docusaurus-theme-bootstrap` + - [#2860](https://github.com/facebook/docusaurus/pull/2860) fix(v2): bootstrap doc sidebar ([@fanny](https://github.com/fanny)) +- Other + - [#2874](https://github.com/facebook/docusaurus/pull/2874) fix(v2): Getting Started URL ([@fanny](https://github.com/fanny)) +- `docusaurus-plugin-content-docs` + - [#2861](https://github.com/facebook/docusaurus/pull/2861) fix(v2): do not create route for document that serve as docs home page ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#2867](https://github.com/facebook/docusaurus/pull/2867) fix(v2): fix FOUC in doc sidebar and various improvements ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-search-algolia` + - [#2838](https://github.com/facebook/docusaurus/pull/2838) fix(v2): use base url to navigate to search page ([@tetunori](https://github.com/tetunori)) +- `docusaurus-utils` + - [#2855](https://github.com/facebook/docusaurus/pull/2855) fix(v2): strip images and footnotes for excerpt correctly ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-live-codeblock` + - [#2835](https://github.com/facebook/docusaurus/pull/2835) fix(v2): set proper font for live editor ([@lex111](https://github.com/lex111)) + +#### :nail_care: Polish + +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils`, `docusaurus` + - [#2884](https://github.com/facebook/docusaurus/pull/2884) polish(v2): improve Docusaurus 1 to 2 migration developer experience ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#2870](https://github.com/facebook/docusaurus/pull/2870) refactor(v2): combine nested theme providers into one ([@lex111](https://github.com/lex111)) + - [#2880](https://github.com/facebook/docusaurus/pull/2880) fix(v2): render as regular text uncollapsible categories ([@lex111](https://github.com/lex111)) + - [#2864](https://github.com/facebook/docusaurus/pull/2864) refactor(v2): add aria role for doc sidebar ([@lex111](https://github.com/lex111)) + - [#2859](https://github.com/facebook/docusaurus/pull/2859) refactor(v2): add aria label to paginators ([@lex111](https://github.com/lex111)) + - [#2858](https://github.com/facebook/docusaurus/pull/2858) refactor(v2): add missing main landmark for needed pages ([@lex111](https://github.com/lex111)) +- Other + - [#2862](https://github.com/facebook/docusaurus/pull/2862) Updated banner in solidarity ([@JoelMarcey](https://github.com/JoelMarcey)) + +#### :memo: Documentation + +- [#2946](https://github.com/facebook/docusaurus/pull/2946) docs(v2): add require.resolve to plugin imports on remaining pages ([@teikjun](https://github.com/teikjun)) +- [#2941](https://github.com/facebook/docusaurus/pull/2941) docs(v2): wrap all plugin imports in require.resolve() ([@TomBrien](https://github.com/TomBrien)) +- [#2934](https://github.com/facebook/docusaurus/pull/2934) docs(v2): add useThemeContext note ([@Drewbi](https://github.com/Drewbi)) +- [#2935](https://github.com/facebook/docusaurus/pull/2935) docs(v2): Add router implementation note ([@Drewbi](https://github.com/Drewbi)) +- [#2933](https://github.com/facebook/docusaurus/pull/2933) docs(v2): add documentation for multiple blogs ([@teikjun](https://github.com/teikjun)) +- [#2910](https://github.com/facebook/docusaurus/pull/2910) docs(v2): fix GitHub action workflow in docs ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- [#2886](https://github.com/facebook/docusaurus/pull/2886) docs(v2): fix typo in command on installation page ([@pglezen](https://github.com/pglezen)) +- [#2887](https://github.com/facebook/docusaurus/pull/2887) docs(v2): make .nojekyll warning more obvious ([@yangshun](https://github.com/yangshun)) +- [#2865](https://github.com/facebook/docusaurus/pull/2865) docs(v2): description field in frontmatter of blog post ([@lex111](https://github.com/lex111)) +- [#2839](https://github.com/facebook/docusaurus/pull/2839) docs(v2): \_index docs page does not show a sidebar ([@aeneasr](https://github.com/aeneasr)) +- [#2852](https://github.com/facebook/docusaurus/pull/2852) misc: move runme demo in block quote about v2 ([@lex111](https://github.com/lex111)) +- [#2842](https://github.com/facebook/docusaurus/pull/2842) docs(v2): Update ZEIT to Vercel ([@Nishikoh](https://github.com/Nishikoh)) + +#### :house: Internal + +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` + - [#2948](https://github.com/facebook/docusaurus/pull/2948) refactor(v2): legacy export = syntax ([@slorber](https://github.com/slorber)) +- `docusaurus-init`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-utils`, `docusaurus` + - [#2922](https://github.com/facebook/docusaurus/pull/2922) misc(v2): better dx: yarn clear, yarn watch, yarn serve ([@slorber](https://github.com/slorber)) +- Other + - [#2929](https://github.com/facebook/docusaurus/pull/2929) chore(v2): Run E2E tests in CI ([@SamChou19815](https://github.com/SamChou19815)) + - [#2899](https://github.com/facebook/docusaurus/pull/2899) chore(deps): bump websocket-extensions from 0.1.3 to 0.1.4 ([@dependabot[bot]](https://github.com/apps/dependabot)) + - [#2897](https://github.com/facebook/docusaurus/pull/2897) refactor(v2): synchronize yarn/npm command on site ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-bootstrap` + - [#2931](https://github.com/facebook/docusaurus/pull/2931) chore(v2): remove unused hooks from bootstrap theme ([@fanny](https://github.com/fanny)) +- `docusaurus-1.x`, `docusaurus-plugin-content-docs` + - [#2906](https://github.com/facebook/docusaurus/pull/2906) chore(v2): fix async tests ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#2858](https://github.com/facebook/docusaurus/pull/2858) refactor(v2): add missing main landmark for needed pages ([@lex111](https://github.com/lex111)) + +#### :running_woman: Performance + +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-sitemap` + - [#2936](https://github.com/facebook/docusaurus/pull/2936) perf(v2): convert synchronous filewrite to asynchronous ([@moonrailgun](https://github.com/moonrailgun)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#2900](https://github.com/facebook/docusaurus/pull/2900) chore(v2): replace Clipboard with copy-text-to-clipboard ([@lex111](https://github.com/lex111)) +- `docusaurus-init`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#2895](https://github.com/facebook/docusaurus/pull/2895) chore(v2): replace classnames with clsx ([@lex111](https://github.com/lex111)) + +#### Committers: 18 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Anshul Goyal ([@anshulrgoyal](https://github.com/anshulrgoyal)) +- Drew Alexander ([@Drewbi](https://github.com/Drewbi)) +- Fanny ([@fanny](https://github.com/fanny)) +- Guillaume Jacquart ([@guillaumejacquart](https://github.com/guillaumejacquart)) +- Joe Previte ([@jsjoeio](https://github.com/jsjoeio)) +- Joel Marcey ([@JoelMarcey](https://github.com/JoelMarcey)) +- Koki Nishihara ([@Nishikoh](https://github.com/Nishikoh)) +- Paul Glezen ([@pglezen](https://github.com/pglezen)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Teik Jun ([@teikjun](https://github.com/teikjun)) +- Tom Brien ([@TomBrien](https://github.com/TomBrien)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) +- [@belokonm](https://github.com/belokonm) +- hackerman ([@aeneasr](https://github.com/aeneasr)) +- moonrailgun ([@moonrailgun](https://github.com/moonrailgun)) +- tetunori ([@tetunori](https://github.com/tetunori)) + +## 2.0.0-alpha.57 (2020-06-18) + +Bad release, check ## 2.0.0-alpha.58 + +## 2.0.0-alpha.56 (2020-05-28) + +#### :boom: Breaking Change + +- If you refer to modules (plugins) in your config file in a string form, you will need to replace them with `require.resolve` calls, for example: + +```diff +- plugins: ['@docusaurus/plugin-google-analytics'] ++ plugins: [require.resolve('@docusaurus/plugin-google-analytics')] +``` + +- `docusaurus-theme-classic` + - [#2818](https://github.com/facebook/docusaurus/pull/2818) feat(v2): automatically add base url to logo link ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#2791](https://github.com/facebook/docusaurus/pull/2791) refactor(v2): show search icon only on mobiles ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#2780](https://github.com/facebook/docusaurus/pull/2780) feat(v2): open external links in new tab by default ([@jknoxville](https://github.com/jknoxville)) + +#### :rocket: New Feature + +- `docusaurus-types`, `docusaurus` + - [#2770](https://github.com/facebook/docusaurus/pull/2770) feat(v2): allow deploy without building website ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#2818](https://github.com/facebook/docusaurus/pull/2818) feat(v2): automatically add base url to logo link ([@lex111](https://github.com/lex111)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#2645](https://github.com/facebook/docusaurus/pull/2645) fix(v2): enable scrolling for sidebar menu only ([@lex111](https://github.com/lex111)) + - [#2800](https://github.com/facebook/docusaurus/pull/2800) fix(v2): make proper h1 font size on mobiles ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#2788](https://github.com/facebook/docusaurus/pull/2788) fix(v2): use `require.resolve` for all webpack presets and plugins ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus-plugin-content-docs` + - [#2785](https://github.com/facebook/docusaurus/pull/2785) fix(v2): do not show sidebar on reserved docs home page ([@lex111](https://github.com/lex111)) + - [#2777](https://github.com/facebook/docusaurus/pull/2777) fix(v2): check for docs homepage correctly ([@lex111](https://github.com/lex111)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#2820](https://github.com/facebook/docusaurus/pull/2820) chore(v2): upgrade Infima to 0.2.0-alpha.12 ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-search-algolia` + - [#2814](https://github.com/facebook/docusaurus/pull/2814) refactor(v2): align search icon to center on mobiles ([@lex111](https://github.com/lex111)) + - [#2799](https://github.com/facebook/docusaurus/pull/2799) refactor(v2): increase search input on medium screens ([@lex111](https://github.com/lex111)) +- `docusaurus-init` + - [#2802](https://github.com/facebook/docusaurus/pull/2802) misc: minor improvements for init templates ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#2791](https://github.com/facebook/docusaurus/pull/2791) refactor(v2): show search icon only on mobiles ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#2783](https://github.com/facebook/docusaurus/pull/2783) refactor(v2): make external links more secure ([@lex111](https://github.com/lex111)) + +#### :memo: Documentation + +- [#2809](https://github.com/facebook/docusaurus/pull/2809) docs(v2): add mention on DocSearch when you run the crawler on your own ([@s-pace](https://github.com/s-pace)) + +#### :house: Internal + +- [#2778](https://github.com/facebook/docusaurus/pull/2778) fix(v2): do not highlight root docs path in navbar ([@lex111](https://github.com/lex111)) + +#### Committers: 8 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- James McShane ([@jmcshane](https://github.com/jmcshane)) +- John Knox ([@jknoxville](https://github.com/jknoxville)) +- Kasper Bøgebjerg Pedersen ([@kasperp](https://github.com/kasperp)) +- Muhammad Ali ([@mrmuhammadali](https://github.com/mrmuhammadali)) +- Piotr Baran ([@piotros](https://github.com/piotros)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Sylvain Pace ([@s-pace](https://github.com/s-pace)) + +## 2.0.0-alpha.55 (2020-05-19) + +#### :boom: Breaking Change + +- `infima` + + - The following Infima classes have been renamed for consistency: + + - `page-item` → `pagination__item` + - `pagination-nav__link--label` → `pagination-nav__label` + - `pagination-nav__link--sublabel` → `pagination-nav__sublabel` + - `tab-item` → `tabs__item` + - `tab-item--active` → `tabs__item--active` + + If you have swizzled components, you need to replace these class names. + +- `docusaurus` + + - [#2764](https://github.com/facebook/docusaurus/pull/2764) feat(v2): allow import SVG images ([@lex111](https://github.com/lex111)) + +#### :rocket: New Feature + +- `docusaurus` + - [#2764](https://github.com/facebook/docusaurus/pull/2764) feat(v2): allow import SVG images ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#2690](https://github.com/facebook/docusaurus/pull/2690) feat(v2): allow activeBaseTest in NavLink ([@nebrelbug](https://github.com/nebrelbug)) + - [#2694](https://github.com/facebook/docusaurus/pull/2694) feat(v2): add canonical URL to `` ([@jcomack](https://github.com/jcomack)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#2652](https://github.com/facebook/docusaurus/pull/2652) feat(v2): allow home page for docs ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#2756](https://github.com/facebook/docusaurus/pull/2756) feat(v2): add search page 🔎 ([@lex111](https://github.com/lex111)) + +#### :bug: Bug Fix + +- `docusaurus-plugin-content-docs`, `docusaurus-utils` + - [#2701](https://github.com/facebook/docusaurus/pull/2701) fix(v2): remove Markdown syntax from excerpt ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#2765](https://github.com/facebook/docusaurus/pull/2765) fix(v2): remove invalid attr from mobile nav links ([@lex111](https://github.com/lex111)) + - [#2760](https://github.com/facebook/docusaurus/pull/2760) fix(v2): move anchor link to right of heading ([@lex111](https://github.com/lex111)) + - [#2758](https://github.com/facebook/docusaurus/pull/2758) fix(v2): remove extra top margin of tab item ([@lex111](https://github.com/lex111)) + - [#2759](https://github.com/facebook/docusaurus/pull/2759) fix(v2): restore hiding of docs toc ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-search-algolia` + - [#2762](https://github.com/facebook/docusaurus/pull/2762) fix(v2): avoid duplication search input in navbar ([@lex111](https://github.com/lex111)) +- `lqip-loader` + - [#2693](https://github.com/facebook/docusaurus/pull/2693) fix(v2): add support ES Module to lqip-loader ([@ykzts](https://github.com/ykzts)) +- `docusaurus-init` + - [#2751](https://github.com/facebook/docusaurus/pull/2751) fix(v2): fix index page features.length when 0 ([@jdeniau](https://github.com/jdeniau)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#2773](https://github.com/facebook/docusaurus/pull/2773) chore(v2): upgrade Infima to 0.2.0-alpha.11 ([@lex111](https://github.com/lex111)) + - [#2766](https://github.com/facebook/docusaurus/pull/2766) refactor(v2): remove extra active CSS class for menu item links ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-live-codeblock` + - [#2767](https://github.com/facebook/docusaurus/pull/2767) refactor(v2): add support for dark mode to live code blocks ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-search-algolia` + - [#2761](https://github.com/facebook/docusaurus/pull/2761) refactor(v2): improve UX of search page ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` + - [#2729](https://github.com/facebook/docusaurus/pull/2729) chore(v2): upgrade Infima to 0.2.0-alpha.10 ([@lex111](https://github.com/lex111)) +- `docusaurus-utils` + - [#2696](https://github.com/facebook/docusaurus/pull/2696) refactor(v2): make semicolon optional in imports for excerpt ([@lex111](https://github.com/lex111)) + +#### :memo: Documentation + +- [#2768](https://github.com/facebook/docusaurus/pull/2768) docs(v2): various improvements ([@lex111](https://github.com/lex111)) +- [#2670](https://github.com/facebook/docusaurus/pull/2670) docs(v2): add deployment workflow manual for GitHub Actions ([@artemkovalyov](https://github.com/artemkovalyov)) + +#### :house: Internal + +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus` + - [#2464](https://github.com/facebook/docusaurus/pull/2464) refactor(v2): add @theme-init alias to give access to initial components ([@lex111](https://github.com/lex111)) + +#### :running_woman: Performance + +- `docusaurus` + - [#2684](https://github.com/facebook/docusaurus/pull/2684) refactor(v2): replace EJS with Eta for SSR generation ([@nebrelbug](https://github.com/nebrelbug)) + +#### Committers: 13 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Artem Kovalov ([@artemkovalyov](https://github.com/artemkovalyov)) +- Ben Gubler ([@nebrelbug](https://github.com/nebrelbug)) +- Fanny ([@fanny](https://github.com/fanny)) +- Jimmy ([@jcomack](https://github.com/jcomack)) +- Jonny Nabors ([@jonnynabors](https://github.com/jonnynabors)) +- Julien Deniau ([@jdeniau](https://github.com/jdeniau)) +- Marco Moretti ([@marcosvega91](https://github.com/marcosvega91)) +- Rajiv Singh ([@iamrajiv](https://github.com/iamrajiv)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Taylor Reece ([@taylorreece](https://github.com/taylorreece)) +- Yamagishi Kazutoshi ([@ykzts](https://github.com/ykzts)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) + +## 2.0.0-alpha.54 (2020-04-28) + +**HOTFIX for 2.0.0-alpha.53**. + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#2688](https://github.com/facebook/docusaurus/pull/2688) fix(v2): add default value for options in theme classic ([@lex111](https://github.com/lex111)) +- `docusaurus-module-type-aliases` + - [#2687](https://github.com/facebook/docusaurus/pull/2687) fix(v2): Add all webpack module aliases to type declaration file ([@SamChou19815](https://github.com/SamChou19815)) + +#### :memo: Documentation + +- [#2680](https://github.com/facebook/docusaurus/pull/2680) docs(v2): add swizzle example ([@jsjoeio](https://github.com/jsjoeio)) + +#### Committers: 3 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Joe Previte ([@jsjoeio](https://github.com/jsjoeio)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) + +## 2.0.0-alpha.53 (2020-04-27) + +**HOTFIX for 2.0.0-alpha.51**. + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#2676](https://github.com/facebook/docusaurus/pull/2676) fix(v2): allow build website without custom css ([@lex111](https://github.com/lex111)) + +#### Committers: 1 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) + +## 2.0.0-alpha.51 (2020-04-27) + +#### :boom: Breaking Change + +- `infima` + - The following infima variables have been renamed for consistency: + - `--ifm-font-base-color` → `--ifm-font-color-base` + - `--ifm-font-base-color-inverse` → `--ifm-font-color-base-inverse` + - `--ifm-font-color-secondary` → `--ifm-font-color-secondary` + +#### :rocket: New Feature + +- `docusaurus-theme-classic` + - [#2660](https://github.com/facebook/docusaurus/pull/2660) feat(v2): add ability to specify CSS class for navbar item ([@lex111](https://github.com/lex111)) + - [#2597](https://github.com/facebook/docusaurus/pull/2597) feat(v2): add ability set dark mode by default ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#2665](https://github.com/facebook/docusaurus/pull/2665) feat(v2): add fallback to BrowserOnly component ([@lex111](https://github.com/lex111)) +- `docusaurus-types`, `docusaurus` + - [#2630](https://github.com/facebook/docusaurus/pull/2630) feat(v2): add CLI option for polling ([@TomBrien](https://github.com/TomBrien)) +- `docusaurus-init` + - [#2541](https://github.com/facebook/docusaurus/pull/2541) feat(v2): add showReadingTime and editUrl to the templates ([@fanny](https://github.com/fanny)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils` + - [#2524](https://github.com/facebook/docusaurus/pull/2524) feat(v2): add edit url in post page ([@fanny](https://github.com/fanny)) +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#2531](https://github.com/facebook/docusaurus/pull/2531) feat(v2): add blog post estimated reading time ([@JoseRenan](https://github.com/JoseRenan)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#2672](https://github.com/facebook/docusaurus/pull/2672) fix(v2): add a11y support for dropdown ([@lex111](https://github.com/lex111)) + - [#2649](https://github.com/facebook/docusaurus/pull/2649) fix(v2): hide sidebar after click on child item ([@lex111](https://github.com/lex111)) + - [#2631](https://github.com/facebook/docusaurus/pull/2631) fix(v2): hide doc sidebar on mobiles ([@lex111](https://github.com/lex111)) + - [#2626](https://github.com/facebook/docusaurus/pull/2626) fix(v2): make border right of doc sidebar equals doc page ([@lex111](https://github.com/lex111)) + - [#2625](https://github.com/facebook/docusaurus/pull/2625) fix(v2): disable tab focus on collapsed doc sidebar items ([@lex111](https://github.com/lex111)) + - [#2602](https://github.com/facebook/docusaurus/pull/2602) fix(v2): inherit color for announcement bar close icon ([@lex111](https://github.com/lex111)) + - [#2582](https://github.com/facebook/docusaurus/pull/2582) fix(v2): remove horizontal scroll on docs page ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#2666](https://github.com/facebook/docusaurus/pull/2666) chore(v2): upgrade prism-react-renderer to latest version ([@lex111](https://github.com/lex111)) + - [#2533](https://github.com/facebook/docusaurus/pull/2533) fix(v2): add rounded corners in code blocks properly ([@lex111](https://github.com/lex111)) +- `docusaurus-1.x`, `docusaurus-init-1.x`, `docusaurus-init`, `docusaurus-plugin-content-docs`, `docusaurus` + - [#2661](https://github.com/facebook/docusaurus/pull/2661) chore: upgrade shelljs to 0.8.4 ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-preset-classic`, `docusaurus-theme-classic` + - [#2642](https://github.com/facebook/docusaurus/pull/2642) fix(v2): use remark-admonitions separately in each plugin instead of in preset only ([@lex111](https://github.com/lex111)) +- `docusaurus-utils` + - [#2380](https://github.com/facebook/docusaurus/pull/2380) fix(v2): ignore import declarations in excerpt ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-sitemap` + - [#2616](https://github.com/facebook/docusaurus/pull/2616) fix(v2): don't include 404 page in sitemaps ([@RDIL](https://github.com/RDIL)) + - [#2530](https://github.com/facebook/docusaurus/pull/2530) fix(v2): Use `writeFileSync` to write generated sitemap.xml to avoid early termination ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus` + - [#2558](https://github.com/facebook/docusaurus/pull/2558) fix(v2): properly link top-level github pages sites in deploy command ([@RDIL](https://github.com/RDIL)) + - [#2580](https://github.com/facebook/docusaurus/pull/2580) fix(v2): do not process anchor links by router ([@lex111](https://github.com/lex111)) + - [#2579](https://github.com/facebook/docusaurus/pull/2579) fix(v2): treat mailto and tel links properly ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog` + - [#2540](https://github.com/facebook/docusaurus/pull/2540) fix(v2): use synchronous write for generate blog feeds ([@lex111](https://github.com/lex111)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#2656](https://github.com/facebook/docusaurus/pull/2656) refactor(v2): lose focus of active sidebar item after click on it ([@lex111](https://github.com/lex111)) + - [#2627](https://github.com/facebook/docusaurus/pull/2627) refactor(v2): extract scroll position detection into separate hook ([@lex111](https://github.com/lex111)) + - [#2595](https://github.com/facebook/docusaurus/pull/2595) refactor(v2): make margin top on blog pages as on other pages ([@lex111](https://github.com/lex111)) + - [#2588](https://github.com/facebook/docusaurus/pull/2588) refactor(v2): remove redundant container on docs page ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus` + - [#2585](https://github.com/facebook/docusaurus/pull/2585) refactor(v2): use nav link component only where needed ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#2556](https://github.com/facebook/docusaurus/pull/2556) refactor(v2): enhance CLI experience ([@RDIL](https://github.com/RDIL)) + - [#2529](https://github.com/facebook/docusaurus/pull/2529) refactor(v2): replace few Lodash methods with native counterparts ([@Simek](https://github.com/Simek)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#2534](https://github.com/facebook/docusaurus/pull/2534) refactor(v2): make better code blocks ([@lex111](https://github.com/lex111)) + - [#2526](https://github.com/facebook/docusaurus/pull/2526) fix(v2): make code block nicer again ([@yangshun](https://github.com/yangshun)) +- `docusaurus-plugin-content-docs` + - [#2519](https://github.com/facebook/docusaurus/pull/2519) chore(v2): use single method Lodash packages in docs plugin ([@Simek](https://github.com/Simek)) + +#### :memo: Documentation + +- [#2659](https://github.com/facebook/docusaurus/pull/2659) fix(docs): mention that appID is optional ([@s-pace](https://github.com/s-pace)) +- [#2596](https://github.com/facebook/docusaurus/pull/2596) docs(v2): remove duplicated package.json in installation directory structure ([@jaylees14](https://github.com/jaylees14)) +- [#2572](https://github.com/facebook/docusaurus/pull/2572) docs(v2): mention that `plugin-ideal-image` only perform compression on a production build ([@Noah-Silvera](https://github.com/Noah-Silvera)) +- [#2570](https://github.com/facebook/docusaurus/pull/2570) docs(v2): fix syntax error for @docusaurus/plugin-ideal-image example ([@Noah-Silvera](https://github.com/Noah-Silvera)) +- [#2566](https://github.com/facebook/docusaurus/pull/2566) docs(v2): be more polite ([@lex111](https://github.com/lex111)) +- [#2559](https://github.com/facebook/docusaurus/pull/2559) doc(v2): remove legacy blog metadata ([@RDIL](https://github.com/RDIL)) +- [#2549](https://github.com/facebook/docusaurus/pull/2549) docs(v2): command for swizzling all components ([@fanny](https://github.com/fanny)) +- [#2547](https://github.com/facebook/docusaurus/pull/2547) docs(v2): Fix typo in team page ([@SamChou19815](https://github.com/SamChou19815)) +- [#2545](https://github.com/facebook/docusaurus/pull/2545) docs(v2): add community pages ([@yangshun](https://github.com/yangshun)) +- [#2521](https://github.com/facebook/docusaurus/pull/2521) docs(v2): useThemeContext hook ([@lex111](https://github.com/lex111)) + +#### :house: Internal + +- `docusaurus-types`, `docusaurus` + - [#2578](https://github.com/facebook/docusaurus/pull/2578) refactor(v2): Convert docusaurus-core to TypeScript ([@SamChou19815](https://github.com/SamChou19815)) +- Other + - [#2569](https://github.com/facebook/docusaurus/pull/2569) docs(v2): showcase user Tourmaline ([@watzon](https://github.com/watzon)) + - [#2553](https://github.com/facebook/docusaurus/pull/2553) misc(v2): remove deprecated/useless lerna field ([@slorber](https://github.com/slorber)) +- `docusaurus-1.x`, `lqip-loader` + - [#2563](https://github.com/facebook/docusaurus/pull/2563) chore(v2): fix lint, tweak lqip-loader utils comment ([@Simek](https://github.com/Simek)) +- `lqip-loader` + - [#2561](https://github.com/facebook/docusaurus/pull/2561) chore(v2): add lqip-loader tests, clarify loader code, improve README ([@Simek](https://github.com/Simek)) +- `docusaurus-plugin-ideal-image`, `lqip-loader` + - [#2544](https://github.com/facebook/docusaurus/pull/2544) refactor(v2): import lqip-loader to monorepo, fix build on Node 13, fix lint-staged ([@Simek](https://github.com/Simek)) +- `docusaurus-init` + - [#2542](https://github.com/facebook/docusaurus/pull/2542) chore(v2): update Prettier config ([@lex111](https://github.com/lex111)) +- `docusaurus-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` + - [#2538](https://github.com/facebook/docusaurus/pull/2538) chore(v2): upgrade devDependencies ([@yangshun](https://github.com/yangshun)) +- `docusaurus-utils` + - [#2536](https://github.com/facebook/docusaurus/pull/2536) refactor(v2): replace Lodash with single methods packages in utils ([@Simek](https://github.com/Simek)) +- `docusaurus` + - [#2535](https://github.com/facebook/docusaurus/pull/2535) refactor(v2): replace Lodash with single methods packages in core ([@Simek](https://github.com/Simek)) + +#### Committers: 18 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Anayo Oleru ([@AnayoOleru](https://github.com/AnayoOleru)) +- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) +- Chris Watson ([@watzon](https://github.com/watzon)) +- Fanny ([@fanny](https://github.com/fanny)) +- Jay Lees ([@jaylees14](https://github.com/jaylees14)) +- Joe Previte ([@jsjoeio](https://github.com/jsjoeio)) +- José Renan ([@JoseRenan](https://github.com/JoseRenan)) +- Kamil Kisiela ([@kamilkisiela](https://github.com/kamilkisiela)) +- Kristóf Poduszló ([@kripod](https://github.com/kripod)) +- Mehmet Yatkı ([@yatki](https://github.com/yatki)) +- Noah Silvera ([@Noah-Silvera](https://github.com/Noah-Silvera)) +- Reece Dunham ([@RDIL](https://github.com/RDIL)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Sylvain Pace ([@s-pace](https://github.com/s-pace)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Tom Brien ([@TomBrien](https://github.com/TomBrien)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) + +## 2.0.0-alpha.50 (2020-04-02) + +**HOTFIX for 2.0.0-alpha.49**. + +#### :bug: Bug Fix + +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#2509](https://github.com/facebook/docusaurus/pull/2509) fix(v2): synchronize code block components changes ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#2498](https://github.com/facebook/docusaurus/pull/2498) fix(v2): blog item styling ([@yangshun](https://github.com/yangshun)) + - [#2489](https://github.com/facebook/docusaurus/pull/2489) fix(v2): fix HTML issues nav dropdown and highlight docs item ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#2496](https://github.com/facebook/docusaurus/pull/2496) fix(v2): do not force terminate building when running deploy command ([@lex111](https://github.com/lex111)) +- `docusaurus-utils` + - [#2497](https://github.com/facebook/docusaurus/pull/2497) fix(v2): unbreak blog-only mode routing by deplicating starting forward slashes ([@SamChou19815](https://github.com/SamChou19815)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#2505](https://github.com/facebook/docusaurus/pull/2505) fix(v2): tweak colors for announcement bar ([@yangshun](https://github.com/yangshun)) + - [#2504](https://github.com/facebook/docusaurus/pull/2504) refactor(v2): improve announcement bar ([@lex111](https://github.com/lex111)) + - [#2495](https://github.com/facebook/docusaurus/pull/2495) refactor(v2): update HTML markup of pagination for better a11y ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#2502](https://github.com/facebook/docusaurus/pull/2502) fix(v2): make code block nicer ([@yangshun](https://github.com/yangshun)) +- `docusaurus-plugin-content-docs`, `docusaurus` + - [#2490](https://github.com/facebook/docusaurus/pull/2490) fix(v2): use lodash instead of array-map-polyfill ([@lex111](https://github.com/lex111)) + +#### :memo: Documentation + +- `docusaurus-theme-classic` + - [#2500](https://github.com/facebook/docusaurus/pull/2500) docs(v2): misc docs updates ([@yangshun](https://github.com/yangshun)) + +#### :house: Internal + +- [#2486](https://github.com/facebook/docusaurus/pull/2486) misc: add instructions about test release ([@lex111](https://github.com/lex111)) + +#### Committers: 5 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Can Gencer ([@cangencer](https://github.com/cangencer)) +- Richard Chan ([@iWun](https://github.com/iWun)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) + +## 2.0.0-alpha.49 (2020-04-01) + +#### :rocket: New Feature + +- `docusaurus-theme-classic` + - [#2487](https://github.com/facebook/docusaurus/pull/2487) feat(v2): nav dropdown ([@yangshun](https://github.com/yangshun)) + - [#2456](https://github.com/facebook/docusaurus/pull/2456) feat(v2): support comments for code highlighting ([@elviswolcott](https://github.com/elviswolcott)) + - [#2330](https://github.com/facebook/docusaurus/pull/2330) feat(v2): add announcement bar ([@lex111](https://github.com/lex111)) + - [#2440](https://github.com/facebook/docusaurus/pull/2440) feat(v2): make clickable sidebar logo ([@lex111](https://github.com/lex111)) + - [#2366](https://github.com/facebook/docusaurus/pull/2366) feat(v2): support syncing tab choices ([@SamChou19815](https://github.com/SamChou19815)) +- `docusaurus` + - [#2323](https://github.com/facebook/docusaurus/pull/2323) feat(v2): add a way to exclude components from build-time prerendering ([@lex111](https://github.com/lex111)) + - [#2469](https://github.com/facebook/docusaurus/pull/2469) feat(v2): add TypeScript support for theme components ([@SamChou19815](https://github.com/SamChou19815)) + - [#2455](https://github.com/facebook/docusaurus/pull/2455) feat(v2): add @theme-original alias to give access to pre-swizzled components ([@yangshun](https://github.com/yangshun)) + - [#2438](https://github.com/facebook/docusaurus/pull/2438) feat(v2): add version to page's generated meta tags ([@lex111](https://github.com/lex111)) +- `docusaurus-types`, `docusaurus` + - [#2474](https://github.com/facebook/docusaurus/pull/2474) feat(v2): add ability to create unminimized bundles ([@lex111](https://github.com/lex111)) + - [#2417](https://github.com/facebook/docusaurus/pull/2417) feat(v2): allow custom output directory for build ([@ZachJW34](https://github.com/ZachJW34)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#2346](https://github.com/facebook/docusaurus/pull/2346) feat(v2): add filename in CodeBlock ([@KohheePeace](https://github.com/KohheePeace)) +- `docusaurus-plugin-content-docs`, `docusaurus` + - [#2444](https://github.com/facebook/docusaurus/pull/2444) feat(v2): allow nested sidebar category shorthand syntax ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#2483](https://github.com/facebook/docusaurus/pull/2483) fix(v2): do not render sidebar logo if used sticky navbar ([@lex111](https://github.com/lex111)) + - [#2475](https://github.com/facebook/docusaurus/pull/2475) fix(v2): make correct Open Graph title for doc page ([@lex111](https://github.com/lex111)) + - [#2436](https://github.com/facebook/docusaurus/pull/2436) fix(v2): update twitter:card to summary_large_image ([@lex111](https://github.com/lex111)) + - [#2434](https://github.com/facebook/docusaurus/pull/2434) fix(v2): add support dark logo for sidebar logo ([@lex111](https://github.com/lex111)) + - [#2420](https://github.com/facebook/docusaurus/pull/2420) fix(v2): fix external URL for og:image tag ([@38elements](https://github.com/38elements)) +- `docusaurus-theme-live-codeblock` + - [#2480](https://github.com/facebook/docusaurus/pull/2480) fix(v2): various improvements for accessibility ([@lex111](https://github.com/lex111)) +- `docusaurus-mdx-loader`, `docusaurus-theme-classic` + - [#2479](https://github.com/facebook/docusaurus/pull/2479) chore(v2): upgrade MDX to 1.5.8 ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#2476](https://github.com/facebook/docusaurus/pull/2476) fix(v2): improve code block scroll accessibility ([@lex111](https://github.com/lex111)) + - [#2442](https://github.com/facebook/docusaurus/pull/2442) fix(v2): various improvements for accessibility ([@lex111](https://github.com/lex111)) +- `docusaurus-preset-classic`, `docusaurus-theme-classic` + - [#2477](https://github.com/facebook/docusaurus/pull/2477) chore(v2): upgrade remark-admonitions for a11y fixes ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#2462](https://github.com/facebook/docusaurus/pull/2462) fix(v2): do not force terminate building when bundle analyzer is on ([@lex111](https://github.com/lex111)) + - [#2393](https://github.com/facebook/docusaurus/pull/2393) fix(v2): normalize location for route matching ([@rlamana](https://github.com/rlamana)) + - [#2443](https://github.com/facebook/docusaurus/pull/2443) fix(v2): always exit after successful build ([@mohrash92](https://github.com/mohrash92)) + - [#2437](https://github.com/facebook/docusaurus/pull/2437) fix(v2): do not force terminate building if client bundle failed in development mode ([@lex111](https://github.com/lex111)) + - [#2424](https://github.com/facebook/docusaurus/pull/2424) fix(v2): make correct internal link check ([@lex111](https://github.com/lex111)) +- `docusaurus-preset-classic` + - [#2451](https://github.com/facebook/docusaurus/pull/2451) fix(v2): pass options to remark-admonitions ([@elviswolcott](https://github.com/elviswolcott)) +- `docusaurus-mdx-loader` + - [#2426](https://github.com/facebook/docusaurus/pull/2426) fix(v2): remove HTML from heading slug ([@lex111](https://github.com/lex111)) +- `docusaurus-utils` + - [#2405](https://github.com/facebook/docusaurus/pull/2405) fix(v2): properly dedupe forward slashes in the entire URL path ([@rlamana](https://github.com/rlamana)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#2485](https://github.com/facebook/docusaurus/pull/2485) refactor(v2): remove unnecessary X-UA-Compatible meta tag ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog` + - [#2460](https://github.com/facebook/docusaurus/pull/2460) refactor(v2): use single method package instead of whole Lodash package in blog plugin ([@Simek](https://github.com/Simek)) +- Other + - [#2428](https://github.com/facebook/docusaurus/pull/2428) polish(v2): use npm-to-yarn for the npm2yarn remark plugin ([@nebrelbug](https://github.com/nebrelbug)) + +#### :memo: Documentation + +- Other + - [#2478](https://github.com/facebook/docusaurus/pull/2478) docs(v2): mark that in dev server some features may not work ([@lex111](https://github.com/lex111)) + - [#2472](https://github.com/facebook/docusaurus/pull/2472) docs(v2): fix typo in deployment docs ([@GermaVinsmoke](https://github.com/GermaVinsmoke)) + - [#2423](https://github.com/facebook/docusaurus/pull/2423) docs(v2): add Sass/SCSS under the styling section ([@rlamana](https://github.com/rlamana)) + - [#2446](https://github.com/facebook/docusaurus/pull/2446) docs(v2): add docusaurus-plugin-sass to community plugins ([@rlamana](https://github.com/rlamana)) + - [#2408](https://github.com/facebook/docusaurus/pull/2408) docs(v2): suggest Surge for quick deployment ([@fakela](https://github.com/fakela)) + - [#2401](https://github.com/facebook/docusaurus/pull/2401) docs(v2): add resources page ([@yangshun](https://github.com/yangshun)) + - [#2413](https://github.com/facebook/docusaurus/pull/2413) docs(v2): include appId key for Algolia ([@TheodoreChu](https://github.com/TheodoreChu)) + - [#2411](https://github.com/facebook/docusaurus/pull/2411) docs:(v2): add Netlify configuration warning ([@bravo-kernel](https://github.com/bravo-kernel)) + - [#2397](https://github.com/facebook/docusaurus/pull/2397) docs(v2):update alpha version to current version ([@fakela](https://github.com/fakela)) + - [#2395](https://github.com/facebook/docusaurus/pull/2395) docs(v2): clarify instructions on docs-only mode ([@phoqe](https://github.com/phoqe)) +- `docusaurus-init` + - [#2458](https://github.com/facebook/docusaurus/pull/2458) fix(v2): expand broken admonitions ([@elviswolcott](https://github.com/elviswolcott)) + +#### :house: Internal + +- `docusaurus` + - [#2461](https://github.com/facebook/docusaurus/pull/2461) chore(v2): upgrade react-dev-utils ([@lex111](https://github.com/lex111)) +- Other + - [#2450](https://github.com/facebook/docusaurus/pull/2450) docs(v2): Adding Motion Layout to Docusaurus users ([@jeffersonlicet](https://github.com/jeffersonlicet)) + - [#2450](https://github.com/facebook/docusaurus/pull/2450) docs(v2): Adding Motion Layout to Docusaurus users ([@jeffersonlicet](https://github.com/jeffersonlicet)) + - [#2439](https://github.com/facebook/docusaurus/pull/2439) polish(v2): add logo for dark mode ([@lex111](https://github.com/lex111)) + - [#2435](https://github.com/facebook/docusaurus/pull/2435) fix(v2): fix aspect ratio for Open Graph image ([@lex111](https://github.com/lex111)) + - [#2433](https://github.com/facebook/docusaurus/pull/2433) chore(v2): ignore JetBrains editors .iml files ([@slorber](https://github.com/slorber)) + - [#2416](https://github.com/facebook/docusaurus/pull/2416) docs(v2): Add Build Tracker to Showcase page ([@paularmstrong](https://github.com/paularmstrong)) + - [#2388](https://github.com/facebook/docusaurus/pull/2388) docs(v1): showcase user Day.js ([@iamkun](https://github.com/iamkun)) +- `stylelint-copyright` + - [#2415](https://github.com/facebook/docusaurus/pull/2415) misc: improve stylelint rule ([@ayshiff](https://github.com/ayshiff)) + +#### Committers: 24 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) +- Ben Gubler ([@nebrelbug](https://github.com/nebrelbug)) +- Elvis Wolcott ([@elviswolcott](https://github.com/elviswolcott)) +- Fanny ([@fanny](https://github.com/fanny)) +- Favour Kelvin ([@fakela](https://github.com/fakela)) +- Jefferson Licet ([@jeffersonlicet](https://github.com/jeffersonlicet)) +- Kohhee Peace ([@KohheePeace](https://github.com/KohheePeace)) +- Linus Långberg ([@phoqe](https://github.com/phoqe)) +- Luke Collier ([@lukecollier](https://github.com/lukecollier)) +- Nisar Hassan Naqvi ([@nisarhassan12](https://github.com/nisarhassan12)) +- Paul Armstrong ([@paularmstrong](https://github.com/paularmstrong)) +- Ramón Lamana ([@rlamana](https://github.com/rlamana)) +- Rémi Doreau ([@ayshiff](https://github.com/ayshiff)) +- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Theodore Chu ([@TheodoreChu](https://github.com/TheodoreChu)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) +- [@38elements](https://github.com/38elements) +- [@GermaVinsmoke](https://github.com/GermaVinsmoke) +- [@ZachJW34](https://github.com/ZachJW34) +- [@bravo-kernel](https://github.com/bravo-kernel) +- [@iamkun](https://github.com/iamkun) +- [@mohrash92](https://github.com/mohrash92) + +## 2.0.0-alpha.48 (2020-03-08) + +**HOTFIX for 2.0.0-alpha.44**. + +#### :bug: Bug Fix + +- Other + - [#2383](https://github.com/facebook/docusaurus/pull/2383) fix(v2): specify proper version for stylelint-copyright ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#2382](https://github.com/facebook/docusaurus/pull/2382) fix(v2): add missing preset-typescript dependency ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#2386](https://github.com/facebook/docusaurus/pull/2386) fix(v2): add missing prismjs dependency and Noop component ([@lex111](https://github.com/lex111)) + +#### Committers: 1 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) + +## 2.0.0-alpha.44 (2020-03-08) + +#### :rocket: New Feature + +- `docusaurus-theme-classic` + - [#2250](https://github.com/facebook/docusaurus/pull/2250) feat(v2): add support specify new languages for Prism ([@lex111](https://github.com/lex111)) + - [#2344](https://github.com/facebook/docusaurus/pull/2344) feat(v2): allow specifying custom target for logo link ([@lex111](https://github.com/lex111)) + - [#2327](https://github.com/facebook/docusaurus/pull/2327) feat(v2): add ability to use HTML in footer copyright ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog` + - [#2335](https://github.com/facebook/docusaurus/pull/2335) feat(v2): add draft feature to blog posts ([@lex111](https://github.com/lex111)) +- `docusaurus-init`, `docusaurus-theme-classic` + - [#2303](https://github.com/facebook/docusaurus/pull/2303) docs(v2): Nav links activeBasePath ([@yangshun](https://github.com/yangshun)) +- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus` + - [#2296](https://github.com/facebook/docusaurus/pull/2296) feat(v2): add ExecutionEnvironment API ([@yangshun](https://github.com/yangshun)) + +#### :bug: Bug Fix + +- `docusaurus` + - [#2345](https://github.com/facebook/docusaurus/pull/2345) fix(v2): force terminate building if client bundle failed ([@lex111](https://github.com/lex111)) + - [#2310](https://github.com/facebook/docusaurus/pull/2310) fix(v2): add @babel/preset-typescript to babel-loader ([@deniaz](https://github.com/deniaz)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#2371](https://github.com/facebook/docusaurus/pull/2371) fix(v2): remove line break from end of code blocks ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog` + - [#2326](https://github.com/facebook/docusaurus/pull/2326) fix(v2): linkify blog posts ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#2324](https://github.com/facebook/docusaurus/pull/2324) fix(v2): properly set dark mode logo on build-time prerendering ([@lex111](https://github.com/lex111)) + - [#2325](https://github.com/facebook/docusaurus/pull/2325) fix(v2): switch a toggle when system theme changed ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-pages`, `docusaurus-utils` + - [#2334](https://github.com/facebook/docusaurus/pull/2334) fix(v2): make proper path to pages in TS ([@lex111](https://github.com/lex111)) +- Other + - [#2316](https://github.com/facebook/docusaurus/pull/2316) fix(v2): properly scale logo on IE 11 ([@lex111](https://github.com/lex111)) + +#### :nail_care: Polish + +- `docusaurus-theme-search-algolia` + - [#2376](https://github.com/facebook/docusaurus/pull/2376) refactor(v2): clean up and improve Algolia styles ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` + - [#2372](https://github.com/facebook/docusaurus/pull/2372) chore(v2): upgrade Infima and remark-admonitions ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#2367](https://github.com/facebook/docusaurus/pull/2367) refactor(v2): increase CSS specificity on application container ([@lex111](https://github.com/lex111)) +- `docusaurus-init`, `stylelint-copyright` + - [#2363](https://github.com/facebook/docusaurus/pull/2363) fix(v2): improve stylelint copyright header rule ([@yangshun](https://github.com/yangshun)) +- `docusaurus-types`, `docusaurus` + - [#2342](https://github.com/facebook/docusaurus/pull/2342) chore(v2): mark tagline field as optional ([@lex111](https://github.com/lex111)) + +#### :memo: Documentation + +- [#2378](https://github.com/facebook/docusaurus/pull/2378) docs(v2): add section for docs-only mode ([@phoqe](https://github.com/phoqe)) +- [#2357](https://github.com/facebook/docusaurus/pull/2357) docs(v2): fix getPathsToWatch() example syntax in lifecycle APIs ([@rlamana](https://github.com/rlamana)) +- [#2351](https://github.com/facebook/docusaurus/pull/2351) docs(v2): add examples to plugin usage doc ([@Noah-Silvera](https://github.com/Noah-Silvera)) +- [#2343](https://github.com/facebook/docusaurus/pull/2343) docs(v2): fix typo in remark-admonitions example ([@hassanfarid](https://github.com/hassanfarid)) +- [#2340](https://github.com/facebook/docusaurus/pull/2340) docs(v2): mention about disabling Jekyll when using GitHub pages ([@amilajack](https://github.com/amilajack)) +- [#2338](https://github.com/facebook/docusaurus/pull/2338) docs(v2): guide on upgrading Docusaurus within a project ([@TheodoreChu](https://github.com/TheodoreChu)) +- [#2313](https://github.com/facebook/docusaurus/pull/2313) docs(v2): move the quotes to remark admonitions ([@Zhencha0Cai](https://github.com/Zhencha0Cai)) +- [#2307](https://github.com/facebook/docusaurus/pull/2307) docs(v1): fix Windows instructions for GitHub Pages publishing ([@jartuso](https://github.com/jartuso)) +- [#2300](https://github.com/facebook/docusaurus/pull/2300) docs(v2): make blog plugin config example valid ([@balloob](https://github.com/balloob)) +- [#2289](https://github.com/facebook/docusaurus/pull/2289) docs(v2): add instructions on Travis CI deployment ([@mohamedsgap](https://github.com/mohamedsgap)) + +#### :house: Internal + +- Other + - [#2369](https://github.com/facebook/docusaurus/pull/2369) misc: mention about v2 in README file ([@lex111](https://github.com/lex111)) + - [#2368](https://github.com/facebook/docusaurus/pull/2368) misc: add note about edits in versioned docs ([@lex111](https://github.com/lex111)) + - [#2333](https://github.com/facebook/docusaurus/pull/2333) docs: update use of npm/yarn in contributing.md ([@jsjoeio](https://github.com/jsjoeio)) + - [#2328](https://github.com/facebook/docusaurus/pull/2328) docs(v2): remove unwanted black line from DocSearch showcase image ([@s-pace](https://github.com/s-pace)) + - [#2319](https://github.com/facebook/docusaurus/pull/2319) docs(v2): showcase user Algolia ([@scottilee](https://github.com/scottilee)) +- `docusaurus-init` + - [#2322](https://github.com/facebook/docusaurus/pull/2322) docs(v2): fix misc styling ([@lex111](https://github.com/lex111)) + +#### Committers: 16 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Amila Welihinda ([@amilajack](https://github.com/amilajack)) +- Hassan Farid ([@hassanfarid](https://github.com/hassanfarid)) +- Joe Previte ([@jsjoeio](https://github.com/jsjoeio)) +- Linus Långberg ([@phoqe](https://github.com/phoqe)) +- Mohamed Abdel Nasser ([@mohamedsgap](https://github.com/mohamedsgap)) +- Noah Silvera ([@Noah-Silvera](https://github.com/Noah-Silvera)) +- Paulus Schoutsen ([@balloob](https://github.com/balloob)) +- Ramón Lamana ([@rlamana](https://github.com/rlamana)) +- Robert ([@deniaz](https://github.com/deniaz)) +- Scott Lee ([@scottilee](https://github.com/scottilee)) +- Sylvain Pace ([@s-pace](https://github.com/s-pace)) +- Theodore Chu ([@TheodoreChu](https://github.com/TheodoreChu)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) +- Zhenchao Cai ([@Zhencha0Cai](https://github.com/Zhencha0Cai)) +- [@jartuso](https://github.com/jartuso) + +## 2.0.0-alpha.43 (2020-02-18) + +**HOTFIX for 2.0.0-alpha.41**. + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#2292](https://github.com/facebook/docusaurus/pull/2292) chore(v2): update Infima to 0.2.0-alpha.4 ([@yangshun](https://github.com/yangshun)) + - [#2291](https://github.com/facebook/docusaurus/pull/2291) fix(v2): fix build and deps install ([@lex111](https://github.com/lex111)) + +#### Committers: 2 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) + +## 2.0.0-alpha.41 (2020-02-16) + +#### :rocket: New Feature + +- `docusaurus-init`, `docusaurus-preset-classic`, `docusaurus-theme-classic` + - [#2224](https://github.com/facebook/docusaurus/pull/2224) feat(v2): add remark-admonitions to @docusaurus/preset-classic ([@elviswolcott](https://github.com/elviswolcott)) +- `docusaurus-theme-classic`, `docusaurus` + - [#2263](https://github.com/facebook/docusaurus/pull/2263) feat(v2): pluralize posts on tag's page ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#2261](https://github.com/facebook/docusaurus/pull/2261) feat(v2): allow to specify different logo for dark mode ([@lex111](https://github.com/lex111)) + - [#2253](https://github.com/facebook/docusaurus/pull/2253) feat(v2): allow specify custom link for logo ([@lex111](https://github.com/lex111)) + - [#2255](https://github.com/facebook/docusaurus/pull/2255) feat(v2): add site title to meta title ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-pages`, `docusaurus-utils`, `docusaurus` + - [#2221](https://github.com/facebook/docusaurus/pull/2221) feat(v2): allow for TypeScript pages and components ([@jonathanrdelgado](https://github.com/jonathanrdelgado)) + +#### :boom: Breaking Change + +- `docusaurus-theme-classic` + - [#2235](https://github.com/facebook/docusaurus/pull/2235) fix(v2): show doc sidebar on pages with case-sensitive paths ([@lex111](https://github.com/lex111)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#2285](https://github.com/facebook/docusaurus/pull/2285) fix(v2): fix codeblock copy button not including blank lines ([@KohheePeace](https://github.com/KohheePeace)) + - [#2241](https://github.com/facebook/docusaurus/pull/2241) fix(v2): make code blocks scrollable ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#2259](https://github.com/facebook/docusaurus/pull/2259) fix(v2): use site title if enabled blog-only mode ([@lex111](https://github.com/lex111)) + - [#2248](https://github.com/facebook/docusaurus/pull/2248) fix(v2): adjust correct behavior of navbar when active anchor ([@lex111](https://github.com/lex111)) + - [#2235](https://github.com/facebook/docusaurus/pull/2235) fix(v2): show doc sidebar on pages with case-sensitive paths ([@lex111](https://github.com/lex111)) + - [#2162](https://github.com/facebook/docusaurus/pull/2162) fix(v2): unify anchor behavior ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-search-algolia` + - [#2262](https://github.com/facebook/docusaurus/pull/2262) fix(v2): remove focus on search input when hovering over it ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#2240](https://github.com/facebook/docusaurus/pull/2240) fix(v2): hide read more button on non-truncated posts ([@lex111](https://github.com/lex111)) +- `docusaurus` + - [#2237](https://github.com/facebook/docusaurus/pull/2237) fix(v2): include base url in 404 route ([@lex111](https://github.com/lex111)) +- `docusaurus-mdx-loader` + - [#2236](https://github.com/facebook/docusaurus/pull/2236) fix(v2): escape link text in TOC ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-live-codeblock` + - [#2227](https://github.com/facebook/docusaurus/pull/2227) fix(v2): render correct theme for live code blocks on SSR ([@lex111](https://github.com/lex111)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#2254](https://github.com/facebook/docusaurus/pull/2254) refactor(v2): avoid to use raw theme values ([@lex111](https://github.com/lex111)) + +#### :memo: Documentation + +- [#2281](https://github.com/facebook/docusaurus/pull/2281) docs: update windows deploy command ([@OndrejNepozitek](https://github.com/OndrejNepozitek)) +- [#2257](https://github.com/facebook/docusaurus/pull/2257) docs(v2): require using JSX flavored style objects in mdx ([@wgao19](https://github.com/wgao19)) +- [#2251](https://github.com/facebook/docusaurus/pull/2251) docs(v2): collapsible categories in sidebar ([@lex111](https://github.com/lex111)) +- [#2218](https://github.com/facebook/docusaurus/pull/2218) docs(v2): update link to available prism themes ([@jsjoeio](https://github.com/jsjoeio)) +- [#2216](https://github.com/facebook/docusaurus/pull/2216) docs(v2): fix plugin-content-docs config comment typo ([@sdowding](https://github.com/sdowding)) + +#### :house: Internal + +- Other + - [#2256](https://github.com/facebook/docusaurus/pull/2256) fix(v2): add title for Feedback page ([@lex111](https://github.com/lex111)) + - [#2246](https://github.com/facebook/docusaurus/pull/2246) docs(v2): add Benthos to showcase ([@Jeffail](https://github.com/Jeffail)) + - [#2242](https://github.com/facebook/docusaurus/pull/2242) docs(v1): showcase user Jafar ([@galhavivi](https://github.com/galhavivi)) + - [#2238](https://github.com/facebook/docusaurus/pull/2238) docs(v1): showcase Dime ([@hbulens](https://github.com/hbulens)) + - [#2233](https://github.com/facebook/docusaurus/pull/2233) docs(v2): showcase user supabase ([@awalias](https://github.com/awalias)) + - [#2226](https://github.com/facebook/docusaurus/pull/2226) docs(v1): showcase user Adapt.js ([@mterrel](https://github.com/mterrel)) + - [#2225](https://github.com/facebook/docusaurus/pull/2225) docs(v1): add The Diff Podcast to users ([@JoelMarcey](https://github.com/JoelMarcey)) + - [#2219](https://github.com/facebook/docusaurus/pull/2219) chore(v1): Updated users list, removing sites not using docusaurus ([@jjwill](https://github.com/jjwill)) +- `docusaurus-theme-classic`, `docusaurus` + - [#2239](https://github.com/facebook/docusaurus/pull/2239) chore(eslint): require curly brackets on all blocks ([@lex111](https://github.com/lex111)) + +#### Committers: 18 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Ashley Jeffs ([@Jeffail](https://github.com/Jeffail)) +- Elie Dutheil ([@edwandr](https://github.com/edwandr)) +- Elvis Wolcott ([@elviswolcott](https://github.com/elviswolcott)) +- Evan Rubinton ([@erubi](https://github.com/erubi)) +- Gal Havivi ([@galhavivi](https://github.com/galhavivi)) +- Hanseung Yoo ([@trustyoo86](https://github.com/trustyoo86)) +- Hendrik Bulens ([@hbulens](https://github.com/hbulens)) +- JavaScript Joe ([@jsjoeio](https://github.com/jsjoeio)) +- Joel Marcey ([@JoelMarcey](https://github.com/JoelMarcey)) +- Jonathan Delgado ([@jonathanrdelgado](https://github.com/jonathanrdelgado)) +- Joshua Williams ([@jjwill](https://github.com/jjwill)) +- KohheePeace ([@KohheePeace](https://github.com/KohheePeace)) +- Mark Terrel ([@mterrel](https://github.com/mterrel)) +- Ondřej Nepožitek ([@OndrejNepozitek](https://github.com/OndrejNepozitek)) +- Scott Dowding ([@sdowding](https://github.com/sdowding)) +- Wei Gao ([@wgao19](https://github.com/wgao19)) +- [@awalias](https://github.com/awalias) + +## 2.0.0-alpha.40 (2019-12-25) + +#### :rocket: New Feature + +- `docusaurus-theme-classic` + - [#2117](https://github.com/facebook/docusaurus/pull/2117) feat(v2): auto switch theme depending on the system theme ([@lex111](https://github.com/lex111)) + - [#2055](https://github.com/facebook/docusaurus/pull/2055) feat(v2): hide navbar on scroll ([@lex111](https://github.com/lex111)) + +#### :bug: Bug Fix + +- `docusaurus` + - [#2145](https://github.com/facebook/docusaurus/pull/2145) fix(v2): remove style-loader, use minicssextract in both dev & prod ([@endiliey](https://github.com/endiliey)) + - [#2122](https://github.com/facebook/docusaurus/pull/2122) fix(v2): dont collapse whitespace in minified html ([@endiliey](https://github.com/endiliey)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` + - [#2105](https://github.com/facebook/docusaurus/pull/2105) fix(v2): move metadata export after compiling MDX to avoid weird MDX parsing error. ([@endiliey](https://github.com/endiliey)) +- `docusaurus-theme-classic` + - [#2113](https://github.com/facebook/docusaurus/pull/2113) fix(v2): set stored theme only if it exists ([@lex111](https://github.com/lex111)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#2129](https://github.com/facebook/docusaurus/pull/2129) fix(v2): disable scroll while mobile menu open ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic`, `docusaurus` + - [#2127](https://github.com/facebook/docusaurus/pull/2127) refactor(v2): toggle data-theme with vanilla js instead of react helmet ([@endiliey](https://github.com/endiliey)) +- `docusaurus-theme-search-algolia`, `docusaurus` + - [#2125](https://github.com/facebook/docusaurus/pull/2125) feat(v2): lazy load algolia css so its not render blocking ([@endiliey](https://github.com/endiliey)) + +#### :memo: Documentation + +- Other + - [#2135](https://github.com/facebook/docusaurus/pull/2135) docs(v1): add space between "out" and "Docusaurus" ([@TransmissionsDev](https://github.com/TransmissionsDev)) + - [#2128](https://github.com/facebook/docusaurus/pull/2128) docs(v1): showcase user Shrine ([@janko](https://github.com/janko)) + - [#2110](https://github.com/facebook/docusaurus/pull/2110) docs(v2): fix pages routing inaccurate info ([@endiliey](https://github.com/endiliey)) + - [#2106](https://github.com/facebook/docusaurus/pull/2106) fix(v2): add missing hyphen in color generator ([@lex111](https://github.com/lex111)) + - [#2104](https://github.com/facebook/docusaurus/pull/2104) feat(v2): add color generator for primary colors ([@yangshun](https://github.com/yangshun)) + - [#2103](https://github.com/facebook/docusaurus/pull/2103) docs: mention about moving docs directory into website ([@yangshun](https://github.com/yangshun)) +- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` + - [#2114](https://github.com/facebook/docusaurus/pull/2114) fix(v2): add syntax highlight to generated colors ([@lex111](https://github.com/lex111)) + +#### :house: Internal + +- Other + - [#2126](https://github.com/facebook/docusaurus/pull/2126) docs: promote Docusaurus 2 usage ([@yangshun](https://github.com/yangshun)) + - [#2119](https://github.com/facebook/docusaurus/pull/2119) fix(v2): align GH button in vertical center ([@lex111](https://github.com/lex111)) +- `docusaurus-init` + - [#2124](https://github.com/facebook/docusaurus/pull/2124) feat(v2): add Facebook Docusaurus 2 template ([@yangshun](https://github.com/yangshun)) +- `docusaurus` + - [#2111](https://github.com/facebook/docusaurus/pull/2111) feat(v2): explicit babel/runtime version ([@endiliey](https://github.com/endiliey)) +- `docusaurus-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-live-codeblock`, `docusaurus` + - [#2102](https://github.com/facebook/docusaurus/pull/2102) misc: add command to run prettier on docs ([@yangshun](https://github.com/yangshun)) + +#### :running_woman: Performance + +- `docusaurus` + - [#2118](https://github.com/facebook/docusaurus/pull/2118) perf(v2): reduce HTML payload by eliminating chunk-map ([@endiliey](https://github.com/endiliey)) + - [#2116](https://github.com/facebook/docusaurus/pull/2116) feat(v2): minify html ([@endiliey](https://github.com/endiliey)) + +#### Committers: 6 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Endi ([@endiliey](https://github.com/endiliey)) +- Janko Marohnić ([@janko](https://github.com/janko)) +- Nick McCurdy ([@nickmccurdy](https://github.com/nickmccurdy)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) +- t11s ([@TransmissionsDev](https://github.com/TransmissionsDev)) + +## 2.0.0-alpha.39 (2019-12-07) + +#### :bug: Bug Fix + +- `docusaurus` + - [#2099](https://github.com/facebook/docusaurus/pull/2099) fix(v2): escape import path on windows ([@endiliey](https://github.com/endiliey)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` + - [#2095](https://github.com/facebook/docusaurus/pull/2095) fix(v2): metadata error if markdown does not have ending line ([@endiliey](https://github.com/endiliey)) + +#### :house: Internal + +- Other + - [#2100](https://github.com/facebook/docusaurus/pull/2100) chore(CI): docusaurus build on Windows with GitHub actions ([@endiliey](https://github.com/endiliey)) +- `docusaurus` + - [#2096](https://github.com/facebook/docusaurus/pull/2096) feat(v2): better & nice looking error overlay ([@endiliey](https://github.com/endiliey)) + +#### Committers: 1 + +- Endi ([@endiliey](https://github.com/endiliey)) + +## 2.0.0-alpha.38 (2019-12-06) + +#### :boom: Breaking Change + +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-utils` + - [#2088](https://github.com/facebook/docusaurus/pull/2088) perf(v2): smaller bundlesize by embedding metadata to content ([@endiliey](https://github.com/endiliey)) + +If you have swizzled any Docs/Blog component that depends on metadata, you'll have to update. If you haven't, no action is needed. + +For example, if you've swizzled `@theme/DocItem`. You'll have to update + +```diff +- const {metadata, content: DocContent} = props; ++ const {content: DocContent} = props; ++ const {metadata} = DocContent; +``` + +#### :bug: Bug Fix + +- `docusaurus` + - [#2086](https://github.com/facebook/docusaurus/pull/2086) fix(v2): windows compatibility regression ([@endiliey](https://github.com/endiliey)) +- `docusaurus-plugin-ideal-image` + - [#2074](https://github.com/facebook/docusaurus/pull/2074) fix(v2): fix plugin-ideal-image breaking website (exports not defined) ([@endiliey](https://github.com/endiliey)) + +#### :nail_care: Polish + +- `docusaurus-mdx-loader` + - [#2085](https://github.com/facebook/docusaurus/pull/2085) misc(v2): update mdx loader plugin README ([@shivangna](https://github.com/shivangna)) + +#### :house: Internal + +- `docusaurus-1.x` + - [#2087](https://github.com/facebook/docusaurus/pull/2087) fix(v1): add key to versions.map in versions.js ([@FeynmanDNA](https://github.com/FeynmanDNA)) + - [#2083](https://github.com/facebook/docusaurus/pull/2083) refactor(v1): fix props for ProjectTitle ([@FeynmanDNA](https://github.com/FeynmanDNA)) +- `docusaurus` + - [#2081](https://github.com/facebook/docusaurus/pull/2081) refactor(v2): move scripts/stylesheets injection to server side ([@endiliey](https://github.com/endiliey)) + - [#2080](https://github.com/facebook/docusaurus/pull/2080) refactor(v2): minor code refactoring on component creator ([@endiliey](https://github.com/endiliey)) + +#### :running_woman: Performance + +- `docusaurus-utils` + - [#2089](https://github.com/facebook/docusaurus/pull/2089) perf(v2): improve dev build time by not overwriting file if possible ([@endiliey](https://github.com/endiliey)) +- `docusaurus-theme-search-algolia` + - [#2079](https://github.com/facebook/docusaurus/pull/2079) perf(v2): algolia search result no longer cause full page refresh ([@endiliey](https://github.com/endiliey)) + - [#2076](https://github.com/facebook/docusaurus/pull/2076) perf(v2): load algolia JS only when user interacts with search ([@endiliey](https://github.com/endiliey)) + +#### Committers: 4 + +- Endi ([@endiliey](https://github.com/endiliey)) +- KYY ([@FeynmanDNA](https://github.com/FeynmanDNA)) +- Shivangna Kaistha ([@shivangna](https://github.com/shivangna)) +- kaichu ([@qshiwu](https://github.com/qshiwu)) + +## 2.0.0-alpha.37 (2019-12-01) + +#### :boom: Breaking Change + +- `docusaurus-init`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus` + - [#2045](https://github.com/facebook/docusaurus/pull/2045) breaking(v2): minimum required nodejs version 8.9-> 8.10 so we can use es2017 ([@endiliey](https://github.com/endiliey)) + +#### :rocket: New Feature + +- `docusaurus-theme-classic`, `docusaurus` + - [#2069](https://github.com/facebook/docusaurus/pull/2069) feat(v2): support prefers-color-scheme & fix dark mode FOUC on refresh ([@endiliey](https://github.com/endiliey)) +- `docusaurus-plugin-content-blog` + - [#2000](https://github.com/facebook/docusaurus/pull/2000) feat(v2): add meta RSS/Atom feed links to head ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` + - [#2057](https://github.com/facebook/docusaurus/pull/2057) feat(v2): injectHtmlTags API to inject head and/or body html tags ([@endiliey](https://github.com/endiliey)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus` + - [#2032](https://github.com/facebook/docusaurus/pull/2032) feat(v2): allow non sidebar category to be first item of sidebar ([@endiliey](https://github.com/endiliey)) +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` + - [#1983](https://github.com/facebook/docusaurus/pull/1983) feat(v2): docs versioning ❄️🔥 ([@endiliey](https://github.com/endiliey)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic`, `docusaurus` + - [#2069](https://github.com/facebook/docusaurus/pull/2069) feat(v2): support prefers-color-scheme & fix dark mode FOUC on refresh ([@endiliey](https://github.com/endiliey)) +- `docusaurus-mdx-loader` + - [#2067](https://github.com/facebook/docusaurus/pull/2067) fix(v2): toc should not be broken for heading with html inline code ([@endiliey](https://github.com/endiliey)) +- `docusaurus-theme-classic` + - [#2064](https://github.com/facebook/docusaurus/pull/2064) fix(v2): markdown reference to file should not be page not found ([@endiliey](https://github.com/endiliey)) + - [#2061](https://github.com/facebook/docusaurus/pull/2061) fix(v2): fix docs sidebar highlighting if link is partially matched ([@endiliey](https://github.com/endiliey)) +- `docusaurus` + - [#2042](https://github.com/facebook/docusaurus/pull/2042) fix(v2): remove css order warning if css imports are not sorted ([@endiliey](https://github.com/endiliey)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#2066](https://github.com/facebook/docusaurus/pull/2066) refactor(v2): add title attribute to anchor link ([@lex111](https://github.com/lex111)) + - [#1990](https://github.com/facebook/docusaurus/pull/1990) refactor(v2): make better a11y for tabs ([@lex111](https://github.com/lex111)) + - [#2034](https://github.com/facebook/docusaurus/pull/2034) feat(v2): style sidebar on overflow ([@endiliey](https://github.com/endiliey)) + +#### :memo: Documentation + +- Other + - [#2068](https://github.com/facebook/docusaurus/pull/2068) docs(v2): quick proofread docs ([@endiliey](https://github.com/endiliey)) + - [#2047](https://github.com/facebook/docusaurus/pull/2047) docs(v2): add manual migration guide for versioning ([@endiliey](https://github.com/endiliey)) + - [#2036](https://github.com/facebook/docusaurus/pull/2036) docs(v2): Reorganize migration guide ([@wgao19](https://github.com/wgao19)) + - [#2052](https://github.com/facebook/docusaurus/pull/2052) fix(v2): make proper spelling of Yarn in tabs ([@lex111](https://github.com/lex111)) + - [#2040](https://github.com/facebook/docusaurus/pull/2040) docs(v2): showcase user vector.dev :) ([@binarylogic](https://github.com/binarylogic)) + - [#2038](https://github.com/facebook/docusaurus/pull/2038) docs(v2): add documentation on versioning ([@endiliey](https://github.com/endiliey)) + - [#2037](https://github.com/facebook/docusaurus/pull/2037) docs(v2): display yarn and npm command on website ([@endiliey](https://github.com/endiliey)) + - [#2051](https://github.com/facebook/docusaurus/pull/2051) docs(v2): more examples on lifecycle apis, cleanup ([@endiliey](https://github.com/endiliey)) + +#### :house: Internal + +- `docusaurus-plugin-content-blog` + - [#2072](https://github.com/facebook/docusaurus/pull/2072) refactor(v2): stronger typing for blog plugin ([@endiliey](https://github.com/endiliey)) +- `docusaurus` + - [#2060](https://github.com/facebook/docusaurus/pull/2060) fix(v2): clean generated manifest from previous build so we dont use the wrong one ([@endiliey](https://github.com/endiliey)) + - [#2033](https://github.com/facebook/docusaurus/pull/2033) refactor(v2): move unused generated files out from build folder ([@endiliey](https://github.com/endiliey)) +- `docusaurus-types`, `docusaurus` + - [#2043](https://github.com/facebook/docusaurus/pull/2043) refactor(v2): stronger typing for route gen ([@endiliey](https://github.com/endiliey)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-ideal-image`, `docusaurus-types`, `docusaurus` + - [#2044](https://github.com/facebook/docusaurus/pull/2044) chore(v2): bump deps ([@endiliey](https://github.com/endiliey)) +- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-docs`, `docusaurus` + - [#2029](https://github.com/facebook/docusaurus/pull/2029) chore(v2): bump deps and remove unused deps ([@endiliey](https://github.com/endiliey)) + +#### :running_woman: Performance + +- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag` + - [#2070](https://github.com/facebook/docusaurus/pull/2070) perf(v2): more performant gtag and analytics plugin ([@endiliey](https://github.com/endiliey)) +- `docusaurus` + - [#2046](https://github.com/facebook/docusaurus/pull/2046) perf(v2): use webpack future version of asset emitting logic to free memory ([@endiliey](https://github.com/endiliey)) + - [#2039](https://github.com/facebook/docusaurus/pull/2039) perf(v2): replace unnecessary json stringify(string) with inline string ([@endiliey](https://github.com/endiliey)) + - [#2035](https://github.com/facebook/docusaurus/pull/2035) perf(v2): use @babel/runtime plugin to reduce codesize ([@endiliey](https://github.com/endiliey)) +- `docusaurus-plugin-content-docs` + - [#2054](https://github.com/facebook/docusaurus/pull/2054) perf(v2): unblock metadata processing when possible ([@endiliey](https://github.com/endiliey)) + +#### Committers: 5 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Binary Logic ([@binarylogic](https://github.com/binarylogic)) +- Dongwoo Gim ([@gimdongwoo](https://github.com/gimdongwoo)) +- Endi ([@endiliey](https://github.com/endiliey)) +- Wei Gao ([@wgao19](https://github.com/wgao19)) + +## 2.0.0-alpha.36 (2019-11-22) + +#### :boom: Breaking Change + +- `docusaurus-init`, `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#1989](https://github.com/facebook/docusaurus/pull/1989) misc(v2): change blog front matter to snake_case ([@yangshun](https://github.com/yangshun)) + +#### :rocket: New Feature + +- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` + - [#2012](https://github.com/facebook/docusaurus/pull/2012) feat(v2): allow hiding docs table of contents ([@yangshun](https://github.com/yangshun)) + +#### :bug: Bug Fix + +- `docusaurus` + - [#2007](https://github.com/facebook/docusaurus/pull/2007) feat(v2): only create one css file to avoid code-split css loading problem ([@endiliey](https://github.com/endiliey)) +- `docusaurus-theme-classic` + - [#2005](https://github.com/facebook/docusaurus/pull/2005) fix(v2): adjust first-level heading offset ([@lex111](https://github.com/lex111)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#2013](https://github.com/facebook/docusaurus/pull/2013) refactor(v2): split out dark mode toggle so it is easily swizzle-able ([@endiliey](https://github.com/endiliey)) + - [#2017](https://github.com/facebook/docusaurus/pull/2017) feat(v2): style right sidebar scrollbar when overflow ([@endiliey](https://github.com/endiliey)) + - [#2003](https://github.com/facebook/docusaurus/pull/2003) refactor(v2): improve semantic markup of blog ([@lex111](https://github.com/lex111)) + +#### :house: Internal + +- `docusaurus` + - [#2024](https://github.com/facebook/docusaurus/pull/2024) test(v2): babel exclude transpilation logic to prevent regression ([@endiliey](https://github.com/endiliey)) + - [#2014](https://github.com/facebook/docusaurus/pull/2014) feat(v2): add meta generator docusaurus ([@endiliey](https://github.com/endiliey)) +- `docusaurus-mdx-loader`, `docusaurus-plugin-ideal-image` + - [#2015](https://github.com/facebook/docusaurus/pull/2015) chore(v2): bump & remove unused deps ([@endiliey](https://github.com/endiliey)) +- Other + - [#2009](https://github.com/facebook/docusaurus/pull/2009) misc(v2): branding update ([@yangshun](https://github.com/yangshun)) + +#### :memo: Documentation + +- [#2010](https://github.com/facebook/docusaurus/pull/2010) docs(v2): misc updates ([@yangshun](https://github.com/yangshun)) + +#### Committers: 3 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Endi ([@endiliey](https://github.com/endiliey)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) + +## 2.0.0-alpha.35 (2019-11-17) + +#### :rocket: New Feature + +- `docusaurus-theme-classic` + - [#1965](https://github.com/facebook/docusaurus/pull/1965) feat(v2): add ability specify link in footer logo ([@lex111](https://github.com/lex111)) + +#### :bug: Bug Fix + +- `docusaurus-mdx-loader`, `docusaurus-theme-classic` + - [#1992](https://github.com/facebook/docusaurus/pull/1992) fix(v2): static phrasing content should be rendered correctly in TOC ([@endiliey](https://github.com/endiliey)) +- `docusaurus-theme-classic` + - [#1999](https://github.com/facebook/docusaurus/pull/1999) fix(v2): remove hashbang when click on category ([@lex111](https://github.com/lex111)) + - [#1962](https://github.com/facebook/docusaurus/pull/1962) fix(v2): make not clickable post title on post item page ([@lex111](https://github.com/lex111)) + - [#1980](https://github.com/facebook/docusaurus/pull/1980) fix(v2): remove invalid label attribute of footer links ([@lex111](https://github.com/lex111)) + - [#1978](https://github.com/facebook/docusaurus/pull/1978) fix(v2): use regular div instead of main tag for wrapper layout page ([@lex111](https://github.com/lex111)) + - [#1975](https://github.com/facebook/docusaurus/pull/1975) fix(v2): move header inside article tag in doc page ([@lex111](https://github.com/lex111)) + - [#1974](https://github.com/facebook/docusaurus/pull/1974) fix(v2): remove invalid attributes of nav links ([@lex111](https://github.com/lex111)) + - [#1963](https://github.com/facebook/docusaurus/pull/1963) fix(v2): remove empty containers when no data in blog pages ([@lex111](https://github.com/lex111)) + - [#1966](https://github.com/facebook/docusaurus/pull/1966) fix(v2): remove duplicate meta tags ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs` + - [#1994](https://github.com/facebook/docusaurus/pull/1994) fix(v2): throw error if first level item of a sidebar is not category ([@endiliey](https://github.com/endiliey)) + +#### :nail_care: Polish + +- `docusaurus-theme-search-algolia` + - [#2001](https://github.com/facebook/docusaurus/pull/2001) fix(v2): improve UI of search ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-classic` + - [#1991](https://github.com/facebook/docusaurus/pull/1991) fix(v2): remove accessible anchors via keyboard ([@lex111](https://github.com/lex111)) + - [#1987](https://github.com/facebook/docusaurus/pull/1987) refactor(v2): replace h1 tag with h2 in blog list pages ([@lex111](https://github.com/lex111)) + - [#1981](https://github.com/facebook/docusaurus/pull/1981) fix(v2): use tag time for showing last update of doc item ([@lex111](https://github.com/lex111)) + - [#1977](https://github.com/facebook/docusaurus/pull/1977) feat(v2): add aria-label to read more links for a11y ([@lex111](https://github.com/lex111)) + - [#1964](https://github.com/facebook/docusaurus/pull/1964) fix(v2): use tag time for showing post item date ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-docs` + - [#1994](https://github.com/facebook/docusaurus/pull/1994) fix(v2): throw error if first level item of a sidebar is not category ([@endiliey](https://github.com/endiliey)) +- Other + - [#1986](https://github.com/facebook/docusaurus/pull/1986) fix(v2): remove obsolete iframe attributes ([@lex111](https://github.com/lex111)) +- `docusaurus-init` + - [#1982](https://github.com/facebook/docusaurus/pull/1982) feat(v2): add FB link to footer ([@lex111](https://github.com/lex111)) +- `docusaurus-plugin-content-blog` + - [#1968](https://github.com/facebook/docusaurus/pull/1968) refactor(v2): simplify blog truncate function ([@endiliey](https://github.com/endiliey)) + +#### :memo: Documentation + +- Other + - [#1988](https://github.com/facebook/docusaurus/pull/1988) docs(v2): fix syntax highlighting for YML code blocks ([@lex111](https://github.com/lex111)) + - [#1976](https://github.com/facebook/docusaurus/pull/1976) docs(v2): Add section to blog document about feed location ([@vinnytheviking](https://github.com/vinnytheviking)) + - [#1970](https://github.com/facebook/docusaurus/pull/1970) docs(v2): update configureWebpack utility functions ([@jamiedavenport](https://github.com/jamiedavenport)) +- `docusaurus-1.x` + - [#1961](https://github.com/facebook/docusaurus/pull/1961) docs(v1): remove exclusive language ([@ericcarboni](https://github.com/ericcarboni)) + +#### :house: Internal + +- Other + - [#2002](https://github.com/facebook/docusaurus/pull/2002) fix(v2): fix browser window menu icon on smaller screen ([@lex111](https://github.com/lex111)) + - [#1986](https://github.com/facebook/docusaurus/pull/1986) fix(v2): remove obsolete iframe attributes ([@lex111](https://github.com/lex111)) +- `docusaurus-init` + - [#1982](https://github.com/facebook/docusaurus/pull/1982) feat(v2): add FB link to footer ([@lex111](https://github.com/lex111)) +- `docusaurus-1.x`, `docusaurus-init-1.x`, `docusaurus-init`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-types`, `docusaurus` + - [#1985](https://github.com/facebook/docusaurus/pull/1985) chore(v2): update dependencies ([@endiliey](https://github.com/endiliey)) + +#### :running_woman: Performance + +- `docusaurus` + - [#1979](https://github.com/facebook/docusaurus/pull/1979) perf(v2): reduce main bundle size by using es5 if possible ([@endiliey](https://github.com/endiliey)) + +#### Committers: 6 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Endi ([@endiliey](https://github.com/endiliey)) +- Eric Carboni ([@ericcarboni](https://github.com/ericcarboni)) +- Jamie Davenport ([@jamiedavenport](https://github.com/jamiedavenport)) +- Nick McCormick ([@kenning](https://github.com/kenning)) +- Vincent van der Walt ([@vinnytheviking](https://github.com/vinnytheviking)) + +## 2.0.0-alpha.34 (2019-11-11) + +#### :rocket: New Feature + +- `docusaurus-theme-classic` + - [#1956](https://github.com/facebook/docusaurus/pull/1956) feat(v2): add ability hide dark mode toggle ([@lex111](https://github.com/lex111)) + +#### :boom: Breaking Change + +- `docusaurus-plugin-content-docs` + - [#1958](https://github.com/facebook/docusaurus/pull/1958) breaking(v2): editUrl should point to website instead of docsDir ([@endiliey](https://github.com/endiliey)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic` + - [#1959](https://github.com/facebook/docusaurus/pull/1959) fix(v2): useTOC hooks should not be called in each nested children ([@endiliey](https://github.com/endiliey)) + +#### :nail_care: Polish + +- `docusaurus-plugin-content-docs`, `docusaurus` + - [#1957](https://github.com/facebook/docusaurus/pull/1957) refactor(v2): avoid synchronous/ blocking operation when possible ([@endiliey](https://github.com/endiliey)) + +#### :memo: Documentation + +- [#1953](https://github.com/facebook/docusaurus/pull/1953) fix(v2): update Infima website URL ([@yangshun](https://github.com/yangshun)) + +#### :house: Internal + +- `docusaurus-1.x`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#1955](https://github.com/facebook/docusaurus/pull/1955) chore: bump dev dependencies ([@endiliey](https://github.com/endiliey)) +- Other + - [#1952](https://github.com/facebook/docusaurus/pull/1952) chore(v2): add lerna-changelog ([@endiliey](https://github.com/endiliey)) + +#### :running_woman: Performance + +- `docusaurus-plugin-content-docs`, `docusaurus-utils`, `docusaurus` + - [#1951](https://github.com/facebook/docusaurus/pull/1951) perf(v2): skip runtime fileHash cache in prod & get timestamp asynchronously ([@endiliey](https://github.com/endiliey)) + - [#1950](https://github.com/facebook/docusaurus/pull/1950) perf(v2): more efficient hot reload & consistent filegen ([@endiliey](https://github.com/endiliey)) + +#### Committers: 3 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Endi ([@endiliey](https://github.com/endiliey)) +- Yangshun Tay ([@yangshun](https://github.com/yangshun)) + +## 2.0.0-alpha.33 (2019-11-08) + +#### Features + +- Table of contents is now highlighted depending on current active headings. (thanks to awesome @SantiagoGdaR) [#1896](https://github.com/facebook/docusaurus/pull/1896) +- Official blog plugin can now generate feed for blog posts. (thanks to awesome @moozzyk) [#1916](https://github.com/facebook/docusaurus/pull/1916) +- **BREAKING** `prismTheme` is renamed to `theme` as part new `prism` object in `themeConfig` field in your `docusaurus.config.js`. Eg: + ```diff + themeConfig: { + - prismTheme: require('prism-react-renderer/themes/dracula'), + + prism: { + + theme: require('prism-react-renderer/themes/dracula'), + + }, + }, + ``` +- Added new `prism` option `defaultLanguage` that is used if the language is not specified in code blocks. [#1910](https://github.com/facebook/docusaurus/pull/1910) + +#### Fixes + +- Fix babel/env not picking the correct browserslist configuration during development. When running `docusaurus start`, `process.env.NODE_ENV` is now consistently set to `development`. +- Ensure routes config generation to be more consistent in ordering. Nested routes should be placed last in routes.js. This will allow user to create `src/pages/docs.js` to create custom docs page for `/docs` or even `src/pages/docs/super.js` to create page for `/docs/super/`; +- Fix watcher does not trigger reload on windows. +- Fix build compilation error if exists only one code tab. +- Add minor padding to docs container so that hash-link won't be cut off. + +#### Others + +- Misc dependency upgrades. +- Stability improvement (more tests) & refactoring on docs plugin to prevent regression. + +## 2.0.0-alpha.32 (2019-11-04) + +#### Features + +- Add `` component for client side redirect. Example Usage: + +```js +import React from 'react'; +import {Redirect} from '@docusaurus/router'; + +function Home() { + return ; +} +``` + +- Allow user to add custom HTML to footer items. [#1905](https://github.com/facebook/docusaurus/pull/1905) +- Added code block line highlighting feature (thanks @lex111)! If you have previously swizzled the `CodeBlock` theme component, it is recommended to update your source code to have this feature. ([#1860](https://github.com/facebook/Docusaurus/issues/1860)) + +#### Bug Fixes + +- Fix `@theme/Tabs` component to be able to create tabs with only one item. +- Fix MDX `@theme/Heading` component. If there is no id, it should not create anchor link. +- Fixed a bug in which if `themeConfig.algolia` is not defined, the custom searchbar won't appear. If you've swizzled Algolia `SearchBar` component before, please update your source code otherwise CSS might break. See [#1909](https://github.com/facebook/docusaurus/pull/1909/files) for reference. + +```js +- ++
+``` + +- Slightly adjust search icon position to be more aligned on small width device. ([#1893](https://github.com/facebook/Docusaurus/issues/1893)) +- Fix algolia styling bug, previously search suggestion result is sometimes hidden. ([#1915](https://github.com/facebook/Docusaurus/issues/1915)) +- Changed the way we read the `USE_SSH` env variable during deployment to be the same as in v1. +- Fix accessing `docs/` or `/docs/xxxx` that does not match any existing doc page should return 404 (Not found) page, not blank page. ([#1903](https://github.com/facebook/Docusaurus/issues/1903)) +- Prioritize `@docusaurus/core` dependencies/ node_modules over user's node_modules. This fix a bug whereby if user has core-js@3 on its own node_modules but docusaurus depends on core-js@2, we previously encounter `Module not found: core-js/modules/xxxx` (because core-js@3 doesn't have that). +- Fix a bug where docs plugin add `/docs` route even if docs folder is empty. We also improved docs plugin test coverage to 100% for stability before working on docs versioning. ([#1912](https://github.com/facebook/Docusaurus/issues/1912)) + +#### Performance Improvement + +- Reduce memory usage consumption. ([#1900](https://github.com/facebook/Docusaurus/issues/1900)) +- Significantly reduce main bundle size and initial HTML payload on production build. Generated files from webpack is also shorter in name. ([#1898](https://github.com/facebook/Docusaurus/issues/1898)) +- Simplify blog metadata. Previously, accessing `/blog/post-xxx` will request for next and prev blog post metadata too aside from target post metadata. We should only request target post metadata. ([#1908](https://github.com/facebook/Docusaurus/issues/1908)) + +#### Others + +- Convert sitemap plugin to TypeScript. ([#1894](https://github.com/facebook/Docusaurus/issues/1894)) +- Refactor dark mode toggle into a hook. ([#1899](https://github.com/facebook/Docusaurus/issues/1899)) + +## 2.0.0-alpha.31 (2019-10-26) + +- Footer is now sticky/ pinned to the bottom of the viewport in desktop browsers. +- Footer is now also displayed in docs page for consistency. +- Remove empty doc sidebar container if sidebar for a particular doc page does not exist. Otherwise, it will cause an additional empty space. +- Default PostCSS loader now only polyfills stage 3+ features (previously it was stage 2) like Create React App. Stage 2 CSS is considered relatively unstable and subject to change while Stage 3 features will likely become a standard. +- Fix search bar focus bug. When you put the focus on search input, previously the focus will remain although we have clicked to other area outside of the search input. +- New themeConfig option `sidebarCollapsible`. It is on by default. If explicitly set to `false`, all doc items in sidebar is expanded. Otherwise, it will still be a collapsible sidebar. +- Disable adding hashes to the generated class names of CSS modules in dev mode. Generating unique identifiers takes some time, which can be saved since including paths to files in class names is enough to avoid collisions. +- Fix showing sidebar category with empty items. +- Update infima from 0.2.0-alpha.2 to 0.2.0-alpha.3 + - Fix pagination nav and right sidebar color contrast ratio + - Fix sidebar arrow color in dark mode + - Fix footer mobile issue + - Increase sidebar width + - etc + +## 2.0.0-alpha.30 (2019-10-22) + +- Fix babel transpilation include/exclude logic to be more efficient. This also fix a very weird bug `TypeError: Cannot assign to read only property 'exports' of object '#'`.([#1868](https://github.com/facebook/docusaurus/pull/1868)) + +If you are still encountering the error. Please check whether you use `module.exports` for your `.js` file instead of doing `export` (mixing CJS and ES). See https://github.com/webpack/webpack/issues/4039#issuecomment-477779322 and https://github.com/webpack/webpack/issues/4039#issuecomment-273804003 for more context. + +## 2.0.0-alpha.29 (2019-10-21) + +**HOTFIX for 2.0.0-alpha.28**. + +- Fix missing `core-js` dependencies on `@docusaurus/core`. +- Fix wrong `@babel/env` preset configuration that causes build compilation error. +- New UI for webpack compilation progress bar. + +## 2.0.0-alpha.28 (2019-10-21) + +- Further reduce memory usage to avoid heap memory allocation failure. +- Fix `keywords` frontmatter for SEO not working properly. +- Fix `swizzle` command not passing context properly to theme packages. +- Add `extendCli` api for plugins. This will allow plugin to further extend Docusaurus CLI. +- Fix `swizzle` command not being able to swizzle single js file. +- Fix logo URL in footer to be appended with baseUrl automatically. +- Add the option `--no-open` for `start` command. +- Set `@babel/env` useBuiltins to `usage`. This will automatically use browserlist and import polyfills required. +- Modified TerserWebpackPlugin `terserOptions` for better cross-browser compatibility. +- **BREAKING** `withBaseUrl` is renamed to `useBaseUrl` because its a React Hooks. Make sure you import/rename it correctly. Eg: `import useBaseUrl from '@docusaurus/useBaseUrl`; +- Fix potential security vulnerability because we're exposing the directory structure of the host machine. +- Upgrade dependencies. + +## 2.0.0-alpha.27 (2019-10-14) + +- Add `@theme/Tabs` which can be used to implement multi-language code tabs. +- Implement `custom_edit_url` and `hide_title` markdown header for docusaurus v1 feature parity. +- Reduce memory usage and slightly faster production build. +- Misc dependency upgrades. + +## 2.0.0-alpha.26 (2019-10-12) + +- Docs, pages plugin is rewritten in TypeScript +- Docs improvements and tweaks + - Improved metadata which results in smaller bundle size. + - Docs sidebar can now be more than one level deep, theoretically up to infinity + - Collapsible docs sidebar! + - Make doc page title larger + - Add `editUrl` option (URL for editing) to docs plugin. If this field is set, there will be an "Edit this page" link for each doc page. Example: 'https://github.com/facebook/docusaurus/edit/master/docs' + - Add `showLastUpdateTime` and `showLastUpdateAuthor` options to docs plugin to further achieve v1 parity of showing last update data for a particular doc +- Slight tweaks to the Blog components - blog title is larger now +- Code Blocks + - Change default theme from Night Owl to Palenight + - Slight tweaks to playground/preview components +- Add `scripts` and `stylesheets` field to `docusaurus.config.js` +- More documentation... + +## 2.0.0-alpha.25 (2019-10-01) + +- Blog plugin is rewritten in TypeScript and can now support CJK +- Upgrade key direct dependencies such as webpack, mdx and babel to latest +- Do not escape html and body attributes +- For devices with very small viewport width, the searchbar is replaced with a search icon. On tap of the search icon the searchbar is expanded and the text beside the logo is hidden and remains hidden while the search bar is expanded. +- Add `date` frontMatter support for blog plugin +- Add `truncateMarker` option to blog plugin, support string or regex. +- Webpack `optimization.removeAvailableModules` is now disabled for performance gain. See https://github.com/webpack/webpack/releases/tag/v4.38.0 for more context. + +## 2.0.0-alpha.24 (2019-07-24) + +- Remove unused metadata for pages. This minimize number of http request & smaller bundle size. +- Upgrade dependencies of css-loader from 2.x to 3.x. CSS modules localIdentName hash now only use the last 4 characters instead of 8. +- Fix broken markdown linking replacement for mdx files +- Fix potential security vulnerability because we're exposing the directory structure of the host machine. Instead of absolute path, we use relative path from site directory. Resulting in shorter webpack chunk naming and smaller bundle size. +- Use contenthash instead of chunkhash for better long term caching +- Allow user to customize generated heading from MDX. Swizzle `@theme/Heading` + +## 2.0.0-alpha.23 (2019-07-21) + +- Fix docusaurus route config generation for certain edge case + +## 2.0.0-alpha.22 (2019-07-20) + +- Add missing dependencies on `@docusaurus/preset-classic` +- New plugin `@docusaurus/plugin-ideal-image` to generate an almost ideal image (responsive, lazy-loading, and low quality placeholder) +- Better Twitter/discord image preview. Previously the size is too zoomed +- Allow prism syntax highlighting theme customization. Refer to https://docusaurus.io/docs/markdown-features#syntax-highlighting +- CSS is now autoprefixed using postcss +- Faster, lighter webpack bundle size +- `@docusaurus/theme-live-codeblock` is now much smaller in size and no longer only load on viewport +- Blog markdown files now support using the id field to specify the path + +## 2.0.0-alpha.21 (2019-07-14) + +- Fix babel-loader not transpiling docusaurus package + +## 2.0.0-alpha.20 (2019-07-14) + +- Add copy codeblock button +- Add Google analytics and Google gtag plugins. +- Move source components to `/src`. Please create a `website/src` directory and move your `/pages` and `/theme` code into it. This is to make it easier to integrate your website with external build/static analysis tooling (you can now just pass in `src/**/*.js` as the path to process). +- Adde more documentation thanks to @wgao19. +- Deprecate the current docs plugin. The docs plugin as of 2.0.0-alpha.19 is heavily based on V1 specifications and we intend to create a better one that fixes some of the inconsistencies in V1. If you have swizzled any doc components, you will have to update their names. You are highly encourages to not swizzle the legacy doc components until we have completed the new docs plugin. +- Separate v2 init command to new package @docusaurus/init +- Render 404.html page +- Improve SEO +- Clicking on the logo in the mobile sliding navigation will now bring you to the homepage. +- Performance + - Disable webpack output pathinfo. Webpack has the ability to generate path info in the output bundle. However, this puts garbage collection pressure on projects that bundle thousands of modules. Not very useful for our case + - Drop cache-loader in CI and test environment because it has an initial overhead. We always start from scratch in vm instance like CI so cache-loader is useless + - Better splitchunks and babel default webpack config + +## 2.0.0-alpha.19 (2019-06-07) + +- Add a sensible default for browserslist config. +- UI + - Add sun and moon emoji to the dark mode toggle. + - Mobile responsive menu. + - Right table of contents for docs is now sticky. +- Plugins + - Change plugin definitions from classes to functions. Refer to the new plugin docs. + - Implement Clients module API. + - Change format within `docusaurus.config.js` to be like presets. +- Deps + - Infima CSS is now locked down to specific versions and not relying upon the CDN which reads from trunk. + - Update dependencies to latest +- Customize/ Override infima CSS variables by passing options into the classic preset. + +``` +presets: [ + [ + '@docusaurus/preset-classic', + { + theme: { + customCss: require.resolve('./css/custom.css'), + }, + ... + }, + ], +], +``` + +- Allow passing remark and rehype plugins to mdx-loader for docs and blog plugin +- Move themes component of docs and blog to be part of theme-classic +- Use composition style for prism syntax highlighting instead of doing it via rehype plugin +- Pass MDXProvider to docs and blog. To change the provided MDX components, run `docusaurus swizzle @docusaurus/theme-classic MDXComponents` +- Add @docusaurus/theme-livecodeblock plugin +- Better run-time code generation & webpack splitchunks optimization +- Minify css for production build +- Fix weird scrolling problem when navigating to a route with a `hash` location diff --git a/CHANGELOG.md b/CHANGELOG.md index 02aac58ae9..59c365d070 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1762,6800 +1762,3 @@ Failed release - ozaki ([@OzakIOne](https://github.com/OzakIOne)) - sykp241095 ([@sykp241095](https://github.com/sykp241095)) - 初冬 ([@chudongvip](https://github.com/chudongvip)) - -## 2.4.3 (2023-09-20) - -#### :bug: Bug Fix - -- `docusaurus-plugin-content-docs` - - [#9107](https://github.com/facebook/docusaurus/pull/9107) fix(content-docs): sidebar generator should return customProps for doc items ([@TheCatLady](https://github.com/TheCatLady)) -- `docusaurus-theme-classic` - - [#9108](https://github.com/facebook/docusaurus/pull/9108) feat(theme-classic): add description & keywords microdata to blog posts ([@TheCatLady](https://github.com/TheCatLady)) - - [#9099](https://github.com/facebook/docusaurus/pull/9099) fix(theme): only set classname on ul elements if they have an existing class ([@homotechsual](https://github.com/homotechsual)) - - [#9243](https://github.com/facebook/docusaurus/pull/9243) fix(theme-common): ThemedComponent should display something when JS is disabled ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#9130](https://github.com/facebook/docusaurus/pull/9130) fix(theme): canonical url should be not change after hydration if url accessed with/without trailing slash ([@ori-shalom](https://github.com/ori-shalom)) - -#### Committers: 4 - -- Mikey O'Toole ([@homotechsual](https://github.com/homotechsual)) -- Ori Shalom ([@ori-shalom](https://github.com/ori-shalom)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- [@TheCatLady](https://github.com/TheCatLady) - -## 2.4.2 (2023-09-20) - -Bad npm publish, please use 2.4.3 - -## 2.4.1 (2023-05-15) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#8971](https://github.com/facebook/docusaurus/pull/8971) fix(theme): fix collapsible sidebar behavior when prefers-reduced-motion ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-translations` - - [#8933](https://github.com/facebook/docusaurus/pull/8933) fix(theme-translations): fix Turkish translation for aria label "Enter key" ([@LiberaTeMetuMortis](https://github.com/LiberaTeMetuMortis)) -- `docusaurus` - - [#8908](https://github.com/facebook/docusaurus/pull/8908) fix(core): Correct yarn upgrade command for yarn 2.x ([@andrewnicols](https://github.com/andrewnicols)) -- `docusaurus-plugin-content-blog`, `docusaurus-theme-common`, `docusaurus-utils-common`, `docusaurus` - - [#8909](https://github.com/facebook/docusaurus/pull/8909) fix(theme): add \_\_ prefix to technical anchors, search crawlers (Algolia) should ignore them ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-common` - - [#8906](https://github.com/facebook/docusaurus/pull/8906) fix(theme-common): fix collapsible component with prefers-reduced-motion ([@slorber](https://github.com/slorber)) - - [#8873](https://github.com/facebook/docusaurus/pull/8873) fix(theme-common): fix confusing theme error message: bad sidebar id suggestions ([@slorber](https://github.com/slorber)) -- `docusaurus-utils` - - [#8874](https://github.com/facebook/docusaurus/pull/8874) fix(utils): handle Markdown links with spaces to route correctly ([@morsko1](https://github.com/morsko1)) -- `docusaurus-theme-classic`, `docusaurus-theme-translations` - - [#8842](https://github.com/facebook/docusaurus/pull/8842) fix(theme-translations): remove redundant navigation text in aria label ([@tarunrajput](https://github.com/tarunrajput)) -- `create-docusaurus` - - [#8831](https://github.com/facebook/docusaurus/pull/8831) fix(create): add missing await ([@SACHINnANYAKKARA](https://github.com/SACHINnANYAKKARA)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#8862](https://github.com/facebook/docusaurus/pull/8862) refactor(theme): expose copy, success and word-wrap icons as standalone components ([@armano2](https://github.com/armano2)) - -#### Committers: 7 - -- Aleksandr Vladykin ([@morsko1](https://github.com/morsko1)) -- Andrew Lyons ([@andrewnicols](https://github.com/andrewnicols)) -- Armano ([@armano2](https://github.com/armano2)) -- MetuMortis ([@LiberaTeMetuMortis](https://github.com/LiberaTeMetuMortis)) -- Sachin Nanayakkara ([@SACHINnANYAKKARA](https://github.com/SACHINnANYAKKARA)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tarun Chauhan ([@tarunrajput](https://github.com/tarunrajput)) - -## 2.4.0 (2023-03-23) - -#### :rocket: New Feature - -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#8236](https://github.com/facebook/docusaurus/pull/8236) feat(content-docs): add support for sidebar item category/link descriptions in generated index page ([@ZarakiKanzaki](https://github.com/ZarakiKanzaki)) -- `docusaurus-theme-classic` - - [#8708](https://github.com/facebook/docusaurus/pull/8708) feat(theme): allow to load a Docusaurus page with theme from query-string: ?docusaurus-theme=dark ([@slorber](https://github.com/slorber)) - - [#8616](https://github.com/facebook/docusaurus/pull/8616) feat(theme): add ability to translate navbar+footer logo alt text ([@Mysterious-Dev](https://github.com/Mysterious-Dev)) -- `docusaurus-remark-plugin-npm2yarn` - - [#8690](https://github.com/facebook/docusaurus/pull/8690) feat(npm-to-yarn): add support for PnPm and custom converters ([@armano2](https://github.com/armano2)) -- `docusaurus` - - [#8677](https://github.com/facebook/docusaurus/pull/8677) feat(core): add script env variables: NODE_ENV + BABEL_ENV + DOCUSAURUS_CURRENT_LOCALE (temporary i18n workaround) ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#8674](https://github.com/facebook/docusaurus/pull/8674) feat(theme-classic): respect `prefers-reduced-motion: reduce` mediaquery, bump Infima to alpha.43 ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-translations` - - [#8668](https://github.com/facebook/docusaurus/pull/8668) feat(theme-translations): add Hungarian theme translations ([@trueqap](https://github.com/trueqap)) - - [#8631](https://github.com/facebook/docusaurus/pull/8631) feat(theme-translations): add Norwegian (Bokmål) theme translation ([@dr0nn1](https://github.com/dr0nn1)) -- `docusaurus-theme-common` - - [#8656](https://github.com/facebook/docusaurus/pull/8656) feat(theme-common): allow passing a string for details summary ([@pReya](https://github.com/pReya)) -- `docusaurus-plugin-google-gtag` - - [#8620](https://github.com/facebook/docusaurus/pull/8620) feat(gtag-plugin): gtag should support multiple tracking ids, notably for the UA => GA4 transition ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#8803](https://github.com/facebook/docusaurus/pull/8803) fix(theme): codeblock buttons should be kept on the right when using RTL locale ([@Vishruta-Patil](https://github.com/Vishruta-Patil)) - - [#8615](https://github.com/facebook/docusaurus/pull/8615) fix(theme): improve color toggle when using dark navbar ([@dewanshDT](https://github.com/dewanshDT)) - - [#8699](https://github.com/facebook/docusaurus/pull/8699) fix(theme-classic): fix tab focus bug in dropdown (#8697) ([@kagankan](https://github.com/kagankan)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#8801](https://github.com/facebook/docusaurus/pull/8801) fix(theme): allow tabs children to be falsy ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-common`, `docusaurus-theme-search-algolia` - - [#8757](https://github.com/facebook/docusaurus/pull/8757) fix(search): search page should react to querystring changes + cleanup/refactor ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#8746](https://github.com/facebook/docusaurus/pull/8746) fix(core): baseUrl error banner link anchor case ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-translations` - - [#8744](https://github.com/facebook/docusaurus/pull/8744) fix(theme-translations): fix wrong arabic words (tip/next) ([@Anasqx](https://github.com/Anasqx)) - -#### :nail_care: Polish - -- `create-docusaurus` - - [#8712](https://github.com/facebook/docusaurus/pull/8712) polish(create-docusaurus): the starter template should use a navbar item "docSidebar" instead of "doc" (less fragile on updates) ([@biplavmz](https://github.com/biplavmz)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-common`, `docusaurus` - - [#8735](https://github.com/facebook/docusaurus/pull/8735) polish(theme): better error messages on navbar item rendering failures + ErrorCauseBoundary API ([@tannerdolby](https://github.com/tannerdolby)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus` - - [#8736](https://github.com/facebook/docusaurus/pull/8736) polish(core): better styling for error screens ([@tannerdolby](https://github.com/tannerdolby)) - -#### Committers: 14 - -- Anas ([@Anasqx](https://github.com/Anasqx)) -- Armano ([@armano2](https://github.com/armano2)) -- Davide Donadio ([@ZarakiKanzaki](https://github.com/ZarakiKanzaki)) -- Dewansh Thakur ([@dewanshDT](https://github.com/dewanshDT)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Kagan ([@kagankan](https://github.com/kagankan)) -- Moritz Stückler ([@pReya](https://github.com/pReya)) -- Mysterious_Dev ([@Mysterious-Dev](https://github.com/Mysterious-Dev)) -- Petter Drønnen ([@dr0nn1](https://github.com/dr0nn1)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tanner Dolby ([@tannerdolby](https://github.com/tannerdolby)) -- TrueQAP ([@trueqap](https://github.com/trueqap)) -- Vishruta Patil ([@Vishruta-Patil](https://github.com/Vishruta-Patil)) -- [@biplavmz](https://github.com/biplavmz) - -## 2.3.1 (2023-02-03) - -#### :bug: Bug Fix - -- `docusaurus-theme-common` - - [#8628](https://github.com/facebook/docusaurus/pull/8628) fix(theme-common): fix issue in tab scroll position restoration on tab click ([@slorber](https://github.com/slorber)) - - [#8619](https://github.com/facebook/docusaurus/pull/8619) fix(theme-common): localStorage utils dispatch too many storage events leading to infinite loop ([@slorber](https://github.com/slorber)) - - [#8618](https://github.com/facebook/docusaurus/pull/8618) fix(theme-common): prepare usage of useSyncExternalStore compatibility with React 18 ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#8593](https://github.com/facebook/docusaurus/pull/8593) fix(theme-classic): allow rendering single tab item ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-utils` - - [#8606](https://github.com/facebook/docusaurus/pull/8606) fix(utils): handle CRLF when parsing MDX imports ([@scastiel](https://github.com/scastiel)) -- `docusaurus-preset-classic` - - [#8597](https://github.com/facebook/docusaurus/pull/8597) fix(preset-classic): install the right plugin for googleTagManager ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :nail_care: Polish - -- `docusaurus-theme-translations` - - [#8614](https://github.com/facebook/docusaurus/pull/8614) chore(theme-translations): complete zh translations ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :robot: Dependencies - -- `docusaurus-plugin-client-redirects`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#8610](https://github.com/facebook/docusaurus/pull/8610) chore(deps): bump eta from 1.12.3 to 2.0.0 ([@dependabot[bot]](https://github.com/apps/dependabot)) - -#### Committers: 3 - -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Sébastien Castiel ([@scastiel](https://github.com/scastiel)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) - -## 2.3.0 (2023-01-26) - -#### :rocket: New Feature - -- `docusaurus-theme-translations` - - [#8541](https://github.com/facebook/docusaurus/pull/8541) feat(theme-translations): default translations for Slovenian (sl-SI) ([@MatijaSi](https://github.com/MatijaSi)) -- `docusaurus-plugin-content-blog` - - [#8378](https://github.com/facebook/docusaurus/pull/8378) feat(blog): add options.createFeedItems to filter/limit/transform feed items ([@johnnyreilly](https://github.com/johnnyreilly)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus` - - [#8225](https://github.com/facebook/docusaurus/pull/8225) feat(theme-classic): store selected tab in query string. ([@mturoci](https://github.com/mturoci)) -- `docusaurus` - - [#8397](https://github.com/facebook/docusaurus/pull/8397) feat(core): deploy CLI - add support for git url "insteadOf": use 'remote get-url' to determine source repo url ([@friederbluemle](https://github.com/friederbluemle)) -- `docusaurus-theme-search-algolia` - - [#8428](https://github.com/facebook/docusaurus/pull/8428) feat(theme-algolia): add option.replaceSearchResultPathname to process/replaceAll search result urls -- `docusaurus-plugin-google-tag-manager` - - [#8470](https://github.com/facebook/docusaurus/pull/8470) feat(plugin-google-tag-manager): add new google-tag-manager plugin + deprecate google-analytics plugin ([@lanegoolsby](https://github.com/lanegoolsby)) - -#### :bug: Bug Fix - -- `docusaurus-mdx-loader` - - [#8303](https://github.com/facebook/docusaurus/pull/8303) fix(mdx-loader): support nested admonitions - - [#8282](https://github.com/facebook/docusaurus/pull/8282) fix(mermaid): fix Mermaid integration for v9.2 release -- `docusaurus-theme-common` - - [#8539](https://github.com/facebook/docusaurus/pull/8539) fix(algolia): make search footer respect searchPagePath ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#8538](https://github.com/facebook/docusaurus/pull/8538) fix(core): avoid hash collision when generating chunk names ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#8481](https://github.com/facebook/docusaurus/pull/8481) fix(core): explicitly define CopyWebpackPlugin toType: 'dir' ([@Thomascogez](https://github.com/Thomascogez)) - - [#8342](https://github.com/facebook/docusaurus/pull/8342) fix(core): normalize input for poll option ([@mhnaeem](https://github.com/mhnaeem)) -- `docusaurus-theme-classic`, `docusaurus` - - [#8445](https://github.com/facebook/docusaurus/pull/8445) fix(theme-classic) extract HomeBreadcrumbItem + fix swizzle bugs ([@3v0k4](https://github.com/3v0k4)) -- `docusaurus-theme-search-algolia` - - [#8462](https://github.com/facebook/docusaurus/pull/8462) fix(search-algolia): pass custom transformItems function to SearchBar ([@mturoci](https://github.com/mturoci)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#8486](https://github.com/facebook/docusaurus/pull/8486) fix(theme): refactor Tabs, make groupId + queryString work fine together ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#8463](https://github.com/facebook/docusaurus/pull/8463) fix(theme-classic): content container grow to take all the available space ([@Djunnni](https://github.com/Djunnni)) - - [#8328](https://github.com/facebook/docusaurus/pull/8328) fix(theme): preserve sidebar height on collapse ([@0916dhkim](https://github.com/0916dhkim)) - - [#8350](https://github.com/facebook/docusaurus/pull/8350) fix(theme): forward className prop in theme-classic's Heading ([@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)) -- `docusaurus-theme-translations` - - [#8424](https://github.com/facebook/docusaurus/pull/8424) fix(translations): typo in lastUpdatedAtBy Vietnamese translation ([@slorber](https://github.com/slorber)) - - [#8289](https://github.com/facebook/docusaurus/pull/8289) fix(theme-translations): complete Turkish theme translations - - [#8406](https://github.com/facebook/docusaurus/pull/8406) fix(translations): complete farsi theme translations - - [#8450](https://github.com/facebook/docusaurus/pull/8450) fix(theme-translations): complete Vietnamese theme translations - - [#8525](https://github.com/facebook/docusaurus/pull/8525) chore(theme-translations): complete pl translations -- `docusaurus-plugin-content-blog` - - [#8381](https://github.com/facebook/docusaurus/pull/8381) fix(content-blog): blog Atom feed id + RSS feed guid should be fully qualified urls ([@johnnyreilly](https://github.com/johnnyreilly)) -- `docusaurus-plugin-content-docs` - - [#8275](https://github.com/facebook/docusaurus/pull/8275) fix(content-docs): add trailing slash to contentDirs, before passing it to isMDXPartial ([@denis-alkhelali](https://github.com/denis-alkhelali)) -- `docusaurus-utils` - - [#8314](https://github.com/facebook/docusaurus/pull/8314) fix(utils): allow partially backticked markdown h1 contentTitles ([@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)) -- `create-docusaurus`, `docusaurus-theme-classic` - - [#8279](https://github.com/facebook/docusaurus/pull/8279) fix(create-docusaurus): improve init template misleading doc + add Docuaurus social card ([@slorber](https://github.com/slorber)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic`, `docusaurus` - - [#8445](https://github.com/facebook/docusaurus/pull/8445) fix(theme-classic) extract HomeBreadcrumbItem + fix swizzle bugs ([@3v0k4](https://github.com/3v0k4)) -- `docusaurus-theme-translations` - - [#8423](https://github.com/facebook/docusaurus/pull/8423) fix(translations): complete Chinese theme translations ([@SJFCS](https://github.com/SJFCS)) - - [#8312](https://github.com/facebook/docusaurus/pull/8312) fix(theme-translations): complete Swedish theme translations ([@stnor](https://github.com/stnor)) -- `eslint-plugin` - - [#8281](https://github.com/facebook/docusaurus/pull/8281) feat(eslint-plugin): add plugin to exported configs ([@lachieh](https://github.com/lachieh)) - -#### Committers: 16 - -- Danny Kim ([@0916dhkim](https://github.com/0916dhkim)) -- Denis Al-Khelali ([@denis-alkhelali](https://github.com/denis-alkhelali)) -- Dongjoon Lee ([@Djunnni](https://github.com/Djunnni)) -- Frieder Bluemle ([@friederbluemle](https://github.com/friederbluemle)) -- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) -- Josh Goldberg ([@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Lachlan Heywood ([@lachieh](https://github.com/lachieh)) -- Lane Goolsby ([@lanegoolsby](https://github.com/lanegoolsby)) -- Matija Sirk ([@MatijaSi](https://github.com/MatijaSi)) -- Muhammad Hammad ([@mhnaeem](https://github.com/mhnaeem)) -- Riccardo ([@3v0k4](https://github.com/3v0k4)) -- Stefan Norberg ([@stnor](https://github.com/stnor)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Thomas.CA ([@Thomascogez](https://github.com/Thomascogez)) -- [@mturoci](https://github.com/mturoci) -- 宋锦丰 ([@SJFCS](https://github.com/SJFCS)) - -## 2.2.0 (2022-10-29) - -#### :rocket: New Feature - -- `docusaurus-plugin-client-redirects` - - [#8227](https://github.com/facebook/docusaurus/pull/8227) feat(plugin-client-redirects): keep the query string + hash ([@Xabilahu](https://github.com/Xabilahu)) -- `docusaurus` - - [#8210](https://github.com/facebook/docusaurus/pull/8210) feat(core): add --config param to swizzle command ([@e-im](https://github.com/e-im)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-mermaid`, `docusaurus-types`, `docusaurus` - - [#7490](https://github.com/facebook/docusaurus/pull/7490) feat: support mermaid code blocks in Markdown ([@sjwall](https://github.com/sjwall)) -- `docusaurus-types`, `docusaurus` - - [#8151](https://github.com/facebook/docusaurus/pull/8151) feat(core): siteConfig.headTags API to render extra tags in document head ([@johnnyreilly](https://github.com/johnnyreilly)) - -#### :bug: Bug Fix - -- `docusaurus-plugin-ideal-image` - - [#8250](https://github.com/facebook/docusaurus/pull/8250) fix(ideal-image): do not pass down `img` prop ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-common` - - [#8246](https://github.com/facebook/docusaurus/pull/8246) fix(mdx-loader): properly unwrap mdxAdmonitionTitle placeholder ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs` - - [#8234](https://github.com/facebook/docusaurus/pull/8234) fix(plugin-content-docs): fix error message context (error cause) when doc processing fails ([@shanpriyan](https://github.com/shanpriyan)) -- `docusaurus-theme-classic`, `docusaurus-theme-translations` - - [#8207](https://github.com/facebook/docusaurus/pull/8207) fix(theme-classic): hamburger menu control navigation by keyboard ([@jeferson-sb](https://github.com/jeferson-sb)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#8204](https://github.com/facebook/docusaurus/pull/8204) fix(theme-classic): fix SkipToContent without JS , refactor, make it public theming API ([@mturoci](https://github.com/mturoci)) - - [#8059](https://github.com/facebook/docusaurus/pull/8059) fix(theme): preserve url ?search#hash on navbar version/locale dropdowns navigations ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#8192](https://github.com/facebook/docusaurus/pull/8192) fix(core): throw error for invalid URL in config file ([@forgeRW](https://github.com/forgeRW)) -- `docusaurus-theme-classic` - - [#8174](https://github.com/facebook/docusaurus/pull/8174) fix(theme): announce theme switches ([@mturoci](https://github.com/mturoci)) - - [#8190](https://github.com/facebook/docusaurus/pull/8190) fix(theme): add more tag names to inline code element set ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#8163](https://github.com/facebook/docusaurus/pull/8163) fix(theme): mobile navbar & skipToContent should cover announcementBar ([@adnanhashmi09](https://github.com/adnanhashmi09)) - - [#8068](https://github.com/facebook/docusaurus/pull/8068) fix(theme): preserve line breaks when copying code with showLineNumbers in Firefox ([@LittleboyHarry](https://github.com/LittleboyHarry)) -- `docusaurus-utils` - - [#8137](https://github.com/facebook/docusaurus/pull/8137) fix(utils): remove non-ASCII limitation for path normalization ([@birjj](https://github.com/birjj)) - - [#8158](https://github.com/facebook/docusaurus/pull/8158) fix(content-blog): make RSS feed generation work with slugs with .html extension ([@Pranav2612000](https://github.com/Pranav2612000)) -- `docusaurus-theme-translations` - - [#8105](https://github.com/facebook/docusaurus/pull/8105) fix(theme-translations): complete turkish theme default translations ([@ramazansancar](https://github.com/ramazansancar)) - - [#8087](https://github.com/facebook/docusaurus/pull/8087) fix(theme-translations): remove extra vi translations ([@namnguyenthanhwork](https://github.com/namnguyenthanhwork)) -- `docusaurus-plugin-client-redirects` - - [#8067](https://github.com/facebook/docusaurus/pull/8067) fix(redirect): tolerate trailing slash difference if config is undefined ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :nail_care: Polish - -- `docusaurus-theme-translations` - - [#8253](https://github.com/facebook/docusaurus/pull/8253) chore(theme-translations): complete ru translations ([@lex111](https://github.com/lex111)) - - [#8243](https://github.com/facebook/docusaurus/pull/8243) chore(theme-translations): complete French translations ([@forresst](https://github.com/forresst)) - - [#8075](https://github.com/facebook/docusaurus/pull/8075) fix(theme-translation): complete Japanese theme default translation ([@pasora](https://github.com/pasora)) -- `docusaurus` - - [#8159](https://github.com/facebook/docusaurus/pull/8159) fix(core): throw error for invalid URL in config file ([@forgeRW](https://github.com/forgeRW)) - - [#8109](https://github.com/facebook/docusaurus/pull/8109) feat(core): prefetch on mobile touchstart ([@sanjaiyan-dev](https://github.com/sanjaiyan-dev)) -- `docusaurus-theme-classic` - - [#8161](https://github.com/facebook/docusaurus/pull/8161) fix(theme): do not show tab content when tabbing over it; show after selection only ([@mturoci](https://github.com/mturoci)) - - [#8062](https://github.com/facebook/docusaurus/pull/8062) refactor(theme): remove hard-coded tag border-radius ([@homotechsual](https://github.com/homotechsual)) -- `docusaurus-utils-validation`, `docusaurus` - - [#8066](https://github.com/facebook/docusaurus/pull/8066) fix(core): normalize slashes for url/baseUrl instead of throwing ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### Committers: 22 - -- Adnan Hashmi ([@adnanhashmi09](https://github.com/adnanhashmi09)) -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Forresst ([@forresst](https://github.com/forresst)) -- Jan Peer Stöcklmair ([@JPeer264](https://github.com/JPeer264)) -- Jeferson S. Brito ([@jeferson-sb](https://github.com/jeferson-sb)) -- Johan Fagerberg ([@birjj](https://github.com/birjj)) -- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- LittleboyHarry ([@LittleboyHarry](https://github.com/LittleboyHarry)) -- Masahiko Hara ([@pasora](https://github.com/pasora)) -- Mikey O'Toole ([@homotechsual](https://github.com/homotechsual)) -- Nguyễn Thành Nam ([@namnguyenthanhwork](https://github.com/namnguyenthanhwork)) -- Pranav Joglekar ([@Pranav2612000](https://github.com/Pranav2612000)) -- Ramazan SANCAR ([@ramazansancar](https://github.com/ramazansancar)) -- Sam Wall ([@sjwall](https://github.com/sjwall)) -- Sanjaiyan Parthipan ([@sanjaiyan-dev](https://github.com/sanjaiyan-dev)) -- Shanmughapriyan S ([@shanpriyan](https://github.com/shanpriyan)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Xabier Lahuerta Vazquez ([@Xabilahu](https://github.com/Xabilahu)) -- [@forgeRW](https://github.com/forgeRW) -- [@mturoci](https://github.com/mturoci) -- evan ([@e-im](https://github.com/e-im)) - -## 2.1.0 (2022-09-01) - -#### :rocket: New Feature - -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#8008](https://github.com/facebook/docusaurus/pull/8008) feat(theme): ability to use `` without items prop, on any doc page ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#7963](https://github.com/facebook/docusaurus/pull/7963) feat(docs): allow to configure noIndex per doc version ([@slorber](https://github.com/slorber)) - - [#7949](https://github.com/facebook/docusaurus/pull/7949) feat(plugin-docs): docs sidebar item link: support "autoAddBaseUrl" attribute ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-translations` - - [#7953](https://github.com/facebook/docusaurus/pull/7953) feat(theme): adds Ukrainian default theme translations ([@b-ovsepian](https://github.com/b-ovsepian)) - -#### :bug: Bug Fix - -- `create-docusaurus` - - [#8032](https://github.com/facebook/docusaurus/pull/8032) fix(create-docusaurus): tutorial and init template improvements ([@slorber](https://github.com/slorber)) -- `docusaurus-preset-classic` - - [#8029](https://github.com/facebook/docusaurus/pull/8029) fix(preset-classic): broken link in "unrecognized keys" error message ([@mdubus](https://github.com/mdubus)) -- `docusaurus` - - [#7977](https://github.com/facebook/docusaurus/pull/7977) fix(core): preload should support encoded page links ([@adventure-yunfei](https://github.com/adventure-yunfei)) - - [#7996](https://github.com/facebook/docusaurus/pull/7996) fix(core): CLI command write-translations should extract translations from @docu… ([@slorber](https://github.com/slorber)) - - [#7952](https://github.com/facebook/docusaurus/pull/7952) fix(core): allow overriding ssr/dev template meta tags ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-sitemap` - - [#7964](https://github.com/facebook/docusaurus/pull/7964) fix(sitemap): filter all routes with robots meta containing noindex ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#7910](https://github.com/facebook/docusaurus/pull/7910) fix(theme-classic): code block line number display with line wrapping ([@yzhe819](https://github.com/yzhe819)) - - [#7786](https://github.com/facebook/docusaurus/pull/7786) fix: collapse siblings when first category is selected ([@whiteand](https://github.com/whiteand)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#7982](https://github.com/facebook/docusaurus/pull/7982) fix(theme): add aria-label to skip to content link region ([@YoniChechik](https://github.com/YoniChechik)) - - [#7940](https://github.com/facebook/docusaurus/pull/7940) refactor(theme-classic): split AnnouncementBar, increase z-index, use shadow ([@slorber](https://github.com/slorber)) - - [#7876](https://github.com/facebook/docusaurus/pull/7876) refactor(theme-classic): make tag text visually certered ([@Kosai106](https://github.com/Kosai106)) -- `docusaurus-utils` - - [#7941](https://github.com/facebook/docusaurus/pull/7941) feat(core): add new Webpack file-loader extensions: avif, mov, mkv, mpg, avi... ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-types` - - [#7942](https://github.com/facebook/docusaurus/pull/7942) feat(theme-classic): use lang attribute in navbar locale dropdown items ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-translations` - - [#7928](https://github.com/facebook/docusaurus/pull/7928) chore(theme-translations): complete vi translations ([@datlechin](https://github.com/datlechin)) - -#### :memo: Documentation - -- `create-docusaurus` - - [#8032](https://github.com/facebook/docusaurus/pull/8032) fix(create-docusaurus): tutorial and init template improvements ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic` - - [#7905](https://github.com/facebook/docusaurus/pull/7905) docs: remove mention of beta ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### Committers: 10 - -- Bagdasar Ovsepyan ([@b-ovsepian](https://github.com/b-ovsepian)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Kevin Østerkilde ([@Kosai106](https://github.com/Kosai106)) -- Morgane Dubus ([@mdubus](https://github.com/mdubus)) -- Ngô Quốc Đạt ([@datlechin](https://github.com/datlechin)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Yoni Chechik ([@YoniChechik](https://github.com/YoniChechik)) -- [@whiteand](https://github.com/whiteand) -- [@yzhe819](https://github.com/yzhe819) -- adventure-yunfei ([@adventure-yunfei](https://github.com/adventure-yunfei)) - -## 2.0.1 (2022-08-01) - -Fix bad npm publish of 2.0.0 - -#### Committers: 1 - -- Sébastien Lorber ([@slorber](https://github.com/slorber)) - -## 2.0.0 (2022-08-01) - -Bad npm publish, please use 2.0.1 - -#### :nail_care: Polish - -- `docusaurus` - - [#7781](https://github.com/facebook/docusaurus/pull/7781) refactor(core): log Docusaurus & Node version before exiting ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### Committers: 2 - -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) - -## 2.0.0-rc.1 (2022-07-14) - -#### :bug: Bug Fix - -- `docusaurus` - - [#7776](https://github.com/facebook/docusaurus/pull/7776) fix(core): swizzle --eject js should not copy theme .d.ts files ([@slorber](https://github.com/slorber)) - - [#7750](https://github.com/facebook/docusaurus/pull/7750) fix(deploy): revert "feat(deploy): copy local git config to tmp repo (#7702)" ([@ghostsquad](https://github.com/ghostsquad)) -- `docusaurus-plugin-sitemap` - - [#7774](https://github.com/facebook/docusaurus/pull/7774) fix(sitemap): complete gracefully when all pages have noIndex meta ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#7771](https://github.com/facebook/docusaurus/pull/7771) chore: bump Infima to 0.2.0-alpha.42, fix a:hover link bug ([@slorber](https://github.com/slorber)) - - [#7755](https://github.com/facebook/docusaurus/pull/7755) fix(theme-classic): validate options properly ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7752](https://github.com/facebook/docusaurus/pull/7752) fix(theme-classic): fix Layout theme height CSS ([@LichLord91](https://github.com/LichLord91)) -- `docusaurus-migrate` - - [#7766](https://github.com/facebook/docusaurus/pull/7766) fix(migrate): import siteConfig with file extension ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-search-algolia` - - [#7761](https://github.com/facebook/docusaurus/pull/7761) fix(algolia-search): test for canUseIntersectionObserver ([@RoiArthurB](https://github.com/RoiArthurB)) - -#### :nail_care: Polish - -- `docusaurus-theme-translations` - - [#7762](https://github.com/facebook/docusaurus/pull/7762) chore(theme-translations): complete ko translations ([@anaclumos](https://github.com/anaclumos)) - -#### :memo: Documentation - -- `docusaurus-plugin-content-docs` - - [#7706](https://github.com/facebook/docusaurus/pull/7706) docs: release process, versioning, breaking changes, public API surface ([@slorber](https://github.com/slorber)) - -#### :wrench: Maintenance - -- `docusaurus-theme-classic` - - [#7777](https://github.com/facebook/docusaurus/pull/7777) refactor(theme): fix duplicate page metadata usage ([@slorber](https://github.com/slorber)) - - [#7771](https://github.com/facebook/docusaurus/pull/7771) chore: bump Infima to 0.2.0-alpha.42, fix a:hover link bug ([@slorber](https://github.com/slorber)) - -#### Committers: 11 - -- Arthur Brugière ([@RoiArthurB](https://github.com/RoiArthurB)) -- Bruce Song ([@recallwei](https://github.com/recallwei)) -- Evan ([@DigiPie](https://github.com/DigiPie)) -- Jeffrey Aven ([@jeffreyaven](https://github.com/jeffreyaven)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Sunghyun Cho ([@anaclumos](https://github.com/anaclumos)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- The Nguyen ([@treoden](https://github.com/treoden)) -- Wes McNamee ([@ghostsquad](https://github.com/ghostsquad)) -- [@LichLord91](https://github.com/LichLord91) -- 凱恩 Kane ([@Gary50613](https://github.com/Gary50613)) - -## 2.0.0-beta.22 (2022-07-08) - -#### :boom: Breaking Change - -- `docusaurus-theme-classic` - - [#7740](https://github.com/facebook/docusaurus/pull/7740) refactor(theme): nest theme icons under subfolder @theme/Icon/\* ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#7716](https://github.com/facebook/docusaurus/pull/7716) refactor(theme): split BlogPostItem into smaller theme subcomponents ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia` - - [#7660](https://github.com/facebook/docusaurus/pull/7660) refactor(theme-common): split package into public/internal API entrypoints ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#7644](https://github.com/facebook/docusaurus/pull/7644) refactor(docs,theme): split DocItem comp, useDoc hook ([@slorber](https://github.com/slorber)) -- `docusaurus-logger`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` - - [#7642](https://github.com/facebook/docusaurus/pull/7642) refactor: remove "error" reporting level, move reportMessage to logger ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-utils-validation`, `docusaurus` - - [#7152](https://github.com/facebook/docusaurus/pull/7152) refactor: handle all admonitions via JSX component ([@lex111](https://github.com/lex111)) - -#### :rocket: New Feature - -- `docusaurus-theme-translations` - - [#7732](https://github.com/facebook/docusaurus/pull/7732) feat(theme-translations): Dutch translation ([@reinvanhaaren](https://github.com/reinvanhaaren)) - - [#7715](https://github.com/facebook/docusaurus/pull/7715) feat(theme-translations): Swedish translation ([@johnie](https://github.com/johnie)) -- `docusaurus-theme-search-algolia`, `docusaurus-theme-translations` - - [#7666](https://github.com/facebook/docusaurus/pull/7666) feat(algolia-search): allow translating search modal ([@forresst](https://github.com/forresst)) -- `create-docusaurus`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#7643](https://github.com/facebook/docusaurus/pull/7643) feat(theme-classic): themeConfig navbar/footer logos accept className/style + update Meta Open-Source Logo ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects` - - [#7649](https://github.com/facebook/docusaurus/pull/7649) feat(client-redirects): make plugin respect onDuplicateRoutes config ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` - - [#7624](https://github.com/facebook/docusaurus/pull/7624) feat: allow customizing localization path of each locale ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#7581](https://github.com/facebook/docusaurus/pull/7581) feat(core): allow opting out of HTML minification ([@alexandernst](https://github.com/alexandernst)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#7557](https://github.com/facebook/docusaurus/pull/7557) feat: allow specifying custom target for FooterLogo ([@vannyle](https://github.com/vannyle)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-translations` - - [#7556](https://github.com/facebook/docusaurus/pull/7556) feat: add admonition type title translations ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` - - [#7386](https://github.com/facebook/docusaurus/pull/7386) feat(core): allow customizing the i18n directory path ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-live-codeblock` - - [#7514](https://github.com/facebook/docusaurus/pull/7514) feat(live-codeblock): add support for noInline to interactive code blocks ([@jpdriver](https://github.com/jpdriver)) -- `docusaurus-plugin-content-docs` - - [#7461](https://github.com/facebook/docusaurus/pull/7461) feat(content-docs): last_update front matter ([@dpang314](https://github.com/dpang314)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#7727](https://github.com/facebook/docusaurus/pull/7727) fix(theme): show blog post edit link even when no tag & not truncated ([@anaclumos](https://github.com/anaclumos)) - - [#7659](https://github.com/facebook/docusaurus/pull/7659) fix(theme-classic): expose empty string alt text in navbar logos ([@BenDMyers](https://github.com/BenDMyers)) - - [#7595](https://github.com/facebook/docusaurus/pull/7595) fix(content-pages): add article wrapper around MDXContent ([@matkoch](https://github.com/matkoch)) -- `docusaurus-theme-translations` - - [#7694](https://github.com/facebook/docusaurus/pull/7694) fix(theme-translations): typo in vi locale ([@saosangmo](https://github.com/saosangmo)) -- `docusaurus-plugin-content-docs` - - [#7638](https://github.com/facebook/docusaurus/pull/7638) fix(docs): forward doc frontMatter.sidebar_custom_props to linking sidebar category ([@slorber](https://github.com/slorber)) - - [#7634](https://github.com/facebook/docusaurus/pull/7634) fix(content-docs): allow translating doc labels in sidebars.js ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-utils` - - [#7604](https://github.com/facebook/docusaurus/pull/7604) fix(utils): allow any non-boundary characters in Markdown heading ID ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-cssnano-preset` - - [#7593](https://github.com/facebook/docusaurus/pull/7593) fix(cssnano-preset): disable z-index minification ([@dpang314](https://github.com/dpang314)) -- `docusaurus-theme-common` - - [#7551](https://github.com/facebook/docusaurus/pull/7551) fix(theme-classic): code block wrap mode should allow wrapping in the middle of a word ([@slorber](https://github.com/slorber)) - - [#7485](https://github.com/facebook/docusaurus/pull/7485) fix(theme-classic): inconsistent code block wrapping ([@dpang314](https://github.com/dpang314)) -- `docusaurus-mdx-loader`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils` - - [#7521](https://github.com/facebook/docusaurus/pull/7521) fix: make type-checking work in Yarn PnP ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :nail_care: Polish - -- `docusaurus-theme-translations` - - [#7696](https://github.com/facebook/docusaurus/pull/7696) fix(theme-translations): improve grammar of zh translation ([@AkagiYui](https://github.com/AkagiYui)) - - [#7691](https://github.com/facebook/docusaurus/pull/7691) chore(theme-translations): complete vi translations ([@datlechin](https://github.com/datlechin)) - - [#7683](https://github.com/facebook/docusaurus/pull/7683) chore(theme-translations): complete ar translations ([@Altomy](https://github.com/Altomy)) - - [#7633](https://github.com/facebook/docusaurus/pull/7633) chore(theme-translations): complete ko translations ([@HyunseungLee-Travis](https://github.com/HyunseungLee-Travis)) -- `docusaurus` - - [#7702](https://github.com/facebook/docusaurus/pull/7702) feat(deploy): copy local git config to tmp repo ([@ghostsquad](https://github.com/ghostsquad)) - - [#7600](https://github.com/facebook/docusaurus/pull/7600) fix: force refresh on chunk preload error ([@yangshun](https://github.com/yangshun)) -- `docusaurus-plugin-content-docs` - - [#7673](https://github.com/facebook/docusaurus/pull/7673) fix(content-docs): format last update date as "Jun 19, 2020" ([@sigwinch28](https://github.com/sigwinch28)) -- `docusaurus-theme-common`, `docusaurus-theme-search-algolia` - - [#7671](https://github.com/facebook/docusaurus/pull/7671) refactor(theme-common): rename useDynamicCallback to useEvent ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-common` - - [#7648](https://github.com/facebook/docusaurus/pull/7648) fix(theme-common): make useShallowMemoObject key-order-insensitive ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus` - - [#7639](https://github.com/facebook/docusaurus/pull/7639) chore(create): update the facebook template with current assets ([@zpao](https://github.com/zpao)) - - [#7520](https://github.com/facebook/docusaurus/pull/7520) feat: add engines field to templates' package.json ([@johnnyreilly](https://github.com/johnnyreilly)) -- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus` - - [#7579](https://github.com/facebook/docusaurus/pull/7579) refactor(pwa): simplify registerSW code, fix ESLint errors ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag` - - [#7545](https://github.com/facebook/docusaurus/pull/7545) feat(analytics): allow query/hash changes to be sent to GA ([@lanegoolsby](https://github.com/lanegoolsby)) - -#### :memo: Documentation - -- Other - - [#7739](https://github.com/facebook/docusaurus/pull/7739) docs: swizzle react-live with eject ([@SheetJSDev](https://github.com/SheetJSDev)) - - [#7723](https://github.com/facebook/docusaurus/pull/7723) docs: add GitHub pages deployment troubleshooting guide ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7705](https://github.com/facebook/docusaurus/pull/7705) docs: mention MDXContent ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7675](https://github.com/facebook/docusaurus/pull/7675) docs: add docusaurus-openapi-docs to resources ([@sserrata](https://github.com/sserrata)) - - [#7677](https://github.com/facebook/docusaurus/pull/7677) docs: add more info on github cross repo deployment ([@bcabanes](https://github.com/bcabanes)) - - [#7563](https://github.com/facebook/docusaurus/pull/7563) docs: add awesome-docusaurus resource ([@webbertakken](https://github.com/webbertakken)) - - [#7665](https://github.com/facebook/docusaurus/pull/7665) docs: add link from every category index page to the guide page ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7519](https://github.com/facebook/docusaurus/pull/7519) docs: multiple documentation elaborations ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7518](https://github.com/facebook/docusaurus/pull/7518) docs: remove useless front matter ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7512](https://github.com/facebook/docusaurus/pull/7512) docs: update Kent C. Dodds Twitter avatar ([@DharsanB](https://github.com/DharsanB)) -- `create-docusaurus` - - [#7611](https://github.com/facebook/docusaurus/pull/7611) docs: advise using Node 18 in deployment ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7582](https://github.com/facebook/docusaurus/pull/7582) docs: make localhost links clickable ([@dht](https://github.com/dht)) -- `docusaurus-plugin-client-redirects` - - [#7607](https://github.com/facebook/docusaurus/pull/7607) refactor(client-redirects): elaborate documentation, minor refactor ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :wrench: Maintenance - -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#7676](https://github.com/facebook/docusaurus/pull/7676) refactor(theme): move LayoutProviders to Layout/Provider; composeProviders util ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#7674](https://github.com/facebook/docusaurus/pull/7674) chore: prevent importing theme components with relative paths ([@slorber](https://github.com/slorber)) - - [#7664](https://github.com/facebook/docusaurus/pull/7664) chore: upgrade Infima to alpha.40 ([@slorber](https://github.com/slorber)) -- Other - - [#7663](https://github.com/facebook/docusaurus/pull/7663) misc: share .vscode/extensions.json ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#7583](https://github.com/facebook/docusaurus/pull/7583) refactor(cli): make the CLI an even thinner wrapper around command functions ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7547](https://github.com/facebook/docusaurus/pull/7547) chore: update static-site-generator-webpack-plugin ([@slorber](https://github.com/slorber)) -- `create-docusaurus`, `docusaurus-cssnano-preset`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `eslint-plugin`, `lqip-loader`, `stylelint-copyright` - - [#7586](https://github.com/facebook/docusaurus/pull/7586) chore: upgrade to TS 4.7, compile with NodeNext ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### Committers: 51 - -- 7Wate ([@7Wate](https://github.com/7Wate)) -- Ahmed Altomy ([@Altomy](https://github.com/Altomy)) -- Alexander Nestorov ([@alexandernst](https://github.com/alexandernst)) -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Ben Myers ([@BenDMyers](https://github.com/BenDMyers)) -- Benjamin Cabanes ([@bcabanes](https://github.com/bcabanes)) -- Boulet ([@Boulet-](https://github.com/Boulet-)) -- Charles Ancheta ([@cbebe](https://github.com/cbebe)) -- Clemie McCartney ([@clemiee](https://github.com/clemiee)) -- DOLLE ([@JeremyDolle](https://github.com/JeremyDolle)) -- Dharsan B ([@DharsanB](https://github.com/DharsanB)) -- Diego França ([@difranca](https://github.com/difranca)) -- Dima Grossman ([@scopsy](https://github.com/scopsy)) -- Dzung Do ([@saosangmo](https://github.com/saosangmo)) -- Flávio Silva ([@201flaviosilva](https://github.com/201flaviosilva)) -- Forresst ([@forresst](https://github.com/forresst)) -- Huy Nguyen ([@Smilefounder](https://github.com/Smilefounder)) -- Hyunseung Lee ([@HyunseungLee-Travis](https://github.com/HyunseungLee-Travis)) -- JP ([@jpdriver](https://github.com/jpdriver)) -- Joe Harrison ([@sigwinch28](https://github.com/sigwinch28)) -- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) -- Johnie Hjelm ([@johnie](https://github.com/johnie)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Joshua Schmitt ([@jqshuv](https://github.com/jqshuv)) -- Kürşat Şimşek ([@kursatsmsek](https://github.com/kursatsmsek)) -- Lane Goolsby ([@lanegoolsby](https://github.com/lanegoolsby)) -- Le Thi Van ([@vannyle](https://github.com/vannyle)) -- Matthias Koch ([@matkoch](https://github.com/matkoch)) -- Ngô Quốc Đạt ([@datlechin](https://github.com/datlechin)) -- Paul O’Shannessy ([@zpao](https://github.com/zpao)) -- Redcamel ([@redcamel](https://github.com/redcamel)) -- Rein van Haaren ([@reinvanhaaren](https://github.com/reinvanhaaren)) -- Rudra Sen ([@RudraSen2](https://github.com/RudraSen2)) -- Steven Serrata ([@sserrata](https://github.com/sserrata)) -- Sunghyun Cho ([@anaclumos](https://github.com/anaclumos)) -- Szilárd Dóró ([@szilarddoro](https://github.com/szilarddoro)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tom Mrazauskas ([@mrazauskas](https://github.com/mrazauskas)) -- Webber Takken ([@webbertakken](https://github.com/webbertakken)) -- Wes McNamee ([@ghostsquad](https://github.com/ghostsquad)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) -- [@SheetJSDev](https://github.com/SheetJSDev) -- [@alewolf](https://github.com/alewolf) -- [@dpang314](https://github.com/dpang314) -- dht ([@dht](https://github.com/dht)) -- emattia ([@emattia](https://github.com/emattia)) -- pincman ([@pincman](https://github.com/pincman)) -- sado ([@sado0823](https://github.com/sado0823)) -- 凱恩 Kane ([@Gary50613](https://github.com/Gary50613)) -- 李小雨 ([@metal-young](https://github.com/metal-young)) -- 赤城结衣 ([@AkagiYui](https://github.com/AkagiYui)) - -## 2.0.0-beta.21 (2022-05-27) - -#### :boom: Breaking Change - -- `docusaurus-plugin-pwa` - - [#7422](https://github.com/facebook/docusaurus/pull/7422) refactor(pwa): remove reloadPopup option in favor of swizzling ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-cssnano-preset`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `eslint-plugin`, `lqip-loader` - - [#7501](https://github.com/facebook/docusaurus/pull/7501) chore: require Node 16.14 ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :rocket: New Feature - -- `docusaurus-plugin-sitemap` - - [#7469](https://github.com/facebook/docusaurus/pull/7469) feat(sitemap): allow customizing the output name ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-utils`, `docusaurus` - - [#7371](https://github.com/facebook/docusaurus/pull/7371) feat(core): support docusaurus.config.cjs as default file name ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#7500](https://github.com/facebook/docusaurus/pull/7500) feat: make docusaurus serve automatically open in browser ([@Zamiell](https://github.com/Zamiell)) - - [#7452](https://github.com/facebook/docusaurus/pull/7452) feat: add --no-minify flag to docusaurus start ([@lanegoolsby](https://github.com/lanegoolsby)) -- `docusaurus-theme-classic` - - [#7357](https://github.com/facebook/docusaurus/pull/7357) feat(theme-classic): allow className as option for type: "search" ([@JPeer264](https://github.com/JPeer264)) - -#### :bug: Bug Fix - -- `docusaurus` - - [#7362](https://github.com/facebook/docusaurus/pull/7362) fix: always emit SEO title + og:title meta ([@charleskorn](https://github.com/charleskorn)) - - [#7453](https://github.com/facebook/docusaurus/pull/7453) fix(core): avoid using logger and fs.readJSON in SSR ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7369](https://github.com/facebook/docusaurus/pull/7369) fix(cli): output correct path when swizzling bare-file component in subfolder ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7360](https://github.com/facebook/docusaurus/pull/7360) fix(core): allow githubPort in config validation ([@mhughes2k](https://github.com/mhughes2k)) -- `docusaurus-plugin-google-gtag` - - [#7424](https://github.com/facebook/docusaurus/pull/7424) fix(gtag): send the newly rendered page's title instead of the old one's ([@ori-shalom](https://github.com/ori-shalom)) -- `create-docusaurus`, `docusaurus-utils` - - [#7507](https://github.com/facebook/docusaurus/pull/7507) fix(create-docusaurus): potential security issue with command injection ([@slorber](https://github.com/slorber)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus` - - [#7492](https://github.com/facebook/docusaurus/pull/7492) fix(core): always treat error boundary fallback as a callback ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#7438](https://github.com/facebook/docusaurus/pull/7438) fix(theme-classic): allow nested task lists to preserve the indent ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7430](https://github.com/facebook/docusaurus/pull/7430) fix(theme-classic): consistently apply the right active class name for all navbar items ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7411](https://github.com/facebook/docusaurus/pull/7411) fix(theme-classic): autocollapse sidebar categories when navigating with paginator ([@pranabdas](https://github.com/pranabdas)) - - [#7363](https://github.com/facebook/docusaurus/pull/7363) fix(theme-classic): resolve customCss from site dir ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-utils` - - [#7464](https://github.com/facebook/docusaurus/pull/7464) fix(utils): fix Markdown link replacement when link text is same as href ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7458](https://github.com/facebook/docusaurus/pull/7458) fix(utils): avoid replacing Markdown links missing the directly next link ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader` - - [#7392](https://github.com/facebook/docusaurus/pull/7392) fix(mdx-loader): use React.Fragment as fragment factory ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs` - - [#7385](https://github.com/facebook/docusaurus/pull/7385) fix(content-docs): restore functionality when a category only has index page ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :nail_care: Polish - -- `docusaurus-theme-translations` - - [#7493](https://github.com/facebook/docusaurus/pull/7493) chore(theme-translations): complete French translations ([@forresst](https://github.com/forresst)) - - [#7474](https://github.com/facebook/docusaurus/pull/7474) chore(theme-translations): complete zh translations ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7400](https://github.com/facebook/docusaurus/pull/7400) chore(theme-translations): complete Farsi translations ([@massoudmaboudi](https://github.com/massoudmaboudi)) -- `docusaurus` - - [#7499](https://github.com/facebook/docusaurus/pull/7499) fix: avoid printing period after localhost URL ([@Zamiell](https://github.com/Zamiell)) -- `create-docusaurus` - - [#7374](https://github.com/facebook/docusaurus/pull/7374) refactor(create): clean up logic when prompting for unspecified arguments ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :memo: Documentation - -- [#7503](https://github.com/facebook/docusaurus/pull/7503) docs: document MDXComponents scope ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#7497](https://github.com/facebook/docusaurus/pull/7497) docs: link every reference of types in API table to the type definition ([@Zamiell](https://github.com/Zamiell)) -- [#7407](https://github.com/facebook/docusaurus/pull/7407) docs: add Azure SWA as deployment option ([@nitya](https://github.com/nitya)) -- [#7390](https://github.com/facebook/docusaurus/pull/7390) fix(website): use react-lite-youtube-embed for lazy YouTube video ([@matkoch](https://github.com/matkoch)) - -#### :wrench: Maintenance - -- `create-docusaurus`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` - - [#7477](https://github.com/facebook/docusaurus/pull/7477) refactor: fix a lot of errors in type-aware linting ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-translations` - - [#7447](https://github.com/facebook/docusaurus/pull/7447) refactor(theme-classic): migrate to tsc for build ([@Josh-Cena](https://github.com/Josh-Cena)) -- `stylelint-copyright` - - [#7441](https://github.com/facebook/docusaurus/pull/7441) refactor(stylelint-copyright): migrate to TS ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-cssnano-preset` - - [#7440](https://github.com/facebook/docusaurus/pull/7440) refactor(cssnano-preset): migrate to TS ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `eslint-plugin`, `lqip-loader` - - [#7437](https://github.com/facebook/docusaurus/pull/7437) refactor: use TS project references instead of running tsc multiple times ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-pwa` - - [#7421](https://github.com/facebook/docusaurus/pull/7421) refactor(pwa): migrate client modules to TS ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#7415](https://github.com/facebook/docusaurus/pull/7415) refactor(theme-classic): always collocate stylesheets with components in one folder ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#7405](https://github.com/facebook/docusaurus/pull/7405) refactor(core): properly code-split NotFound page ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### Committers: 23 - -- Akara ([@Messiahhh](https://github.com/Messiahhh)) -- Benjamin Diolez ([@BenDz](https://github.com/BenDz)) -- Charles Korn ([@charleskorn](https://github.com/charleskorn)) -- Designatory ([@Designatory](https://github.com/Designatory)) -- Forresst ([@forresst](https://github.com/forresst)) -- Ggicci ([@ggicci](https://github.com/ggicci)) -- James ([@Zamiell](https://github.com/Zamiell)) -- Jan Peer Stöcklmair ([@JPeer264](https://github.com/JPeer264)) -- Jeremy ([@jrmyw92](https://github.com/jrmyw92)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Junjie ([@junjieweb](https://github.com/junjieweb)) -- Lane Goolsby ([@lanegoolsby](https://github.com/lanegoolsby)) -- Massoud Maboudi ([@massoudmaboudi](https://github.com/massoudmaboudi)) -- Matthias Koch ([@matkoch](https://github.com/matkoch)) -- Michael Hughes ([@mhughes2k](https://github.com/mhughes2k)) -- Ngô Quốc Đạt ([@datlechin](https://github.com/datlechin)) -- Nitya Narasimhan ([@nitya](https://github.com/nitya)) -- Oluwatobi Sofela ([@oluwatobiss](https://github.com/oluwatobiss)) -- Ori Shalom ([@ori-shalom](https://github.com/ori-shalom)) -- Pranab Das ([@pranabdas](https://github.com/pranabdas)) -- Rui Peres ([@RuiAAPeres](https://github.com/RuiAAPeres)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- 凱恩 Kane ([@Gary50613](https://github.com/Gary50613)) - -## 2.0.0-beta.20 (2022-05-05) - -#### :bug: Bug Fix - -- `docusaurus` - - [#7342](https://github.com/facebook/docusaurus/pull/7342) fix: avoid flash of page scrolling to top on refresh ([@slorber](https://github.com/slorber)) - - [#7329](https://github.com/facebook/docusaurus/pull/7329) fix(core): inject docusaurus version into SSR as local ([@RDIL](https://github.com/RDIL)) -- `docusaurus-theme-classic` - - [#7341](https://github.com/facebook/docusaurus/pull/7341) fix(theme-classic): properly highlight code block line numbers ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :memo: Documentation - -- [#7334](https://github.com/facebook/docusaurus/pull/7334) feat(website): make canary release page display actual canary version name ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#7343](https://github.com/facebook/docusaurus/pull/7343) docs: add page for create-docusaurus API documentation ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#7340](https://github.com/facebook/docusaurus/pull/7340) docs: add Yandex Metrika plugin to community plugins ([@sgromkov](https://github.com/sgromkov)) -- [#7336](https://github.com/facebook/docusaurus/pull/7336) fix(website): fix multiple accessibility issues around color contrast ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#7327](https://github.com/facebook/docusaurus/pull/7327) docs: add clarity to versioning behavior ([@pepopowitz](https://github.com/pepopowitz)) - -#### Committers: 6 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Reece Dunham ([@RDIL](https://github.com/RDIL)) -- Sergey Gromkov ([@sgromkov](https://github.com/sgromkov)) -- Steven Hicks ([@pepopowitz](https://github.com/pepopowitz)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) - -## 2.0.0-beta.19 (2022-05-04) - -#### :rocket: New Feature - -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#7178](https://github.com/facebook/docusaurus/pull/7178) feat(theme-classic): extensible code block magic comment system ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7007](https://github.com/facebook/docusaurus/pull/7007) feat(theme-classic): code block showLineNumbers ([@lex111](https://github.com/lex111)) - - [#7012](https://github.com/facebook/docusaurus/pull/7012) feat(theme-classic): show blog sidebar on mobile ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus`, `eslint-plugin` - - [#7206](https://github.com/facebook/docusaurus/pull/7206) feat: Docusaurus ESLint plugin to enforce best Docusaurus practices ([@elias-pap](https://github.com/elias-pap)) -- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#6732](https://github.com/facebook/docusaurus/pull/6732) feat(core): rework client modules lifecycles, officially make API public ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#7231](https://github.com/facebook/docusaurus/pull/7231) feat: allow custom navbarItem types to pass through validation ([@slorber](https://github.com/slorber)) - - [#7058](https://github.com/facebook/docusaurus/pull/7058) feat(theme-classic): new 'html' type navbar item ([@lex111](https://github.com/lex111)) - - [#7079](https://github.com/facebook/docusaurus/pull/7079) feat: allow using pure HTML as label in navbar links ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-translations` - - [#7036](https://github.com/facebook/docusaurus/pull/7036) feat(theme-classic): toggle code wrap button ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6457](https://github.com/facebook/docusaurus/pull/6457) feat(content-docs): draft docs excluded from build & sidebars ([@jodyheavener](https://github.com/jodyheavener)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` - - [#6430](https://github.com/facebook/docusaurus/pull/6430) feat: allow setting calendar for i18n date formatting ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` - - [#7083](https://github.com/facebook/docusaurus/pull/7083) feat(core): fail-safe global data fetching ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs` - - [#7106](https://github.com/facebook/docusaurus/pull/7106) feat(content-docs): make docs:version command work on localized docs ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-types`, `docusaurus` - - [#7082](https://github.com/facebook/docusaurus/pull/7082) feat(core): allow plugins to declare custom route context ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7124](https://github.com/facebook/docusaurus/pull/7124) feat(core): allow plugin/preset config to contain false/null ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-sitemap`, `docusaurus-utils` - - [#6979](https://github.com/facebook/docusaurus/pull/6979) feat(sitemap): add ignorePatterns option ([@ApsarasX](https://github.com/ApsarasX)) - -#### :boom: Breaking Change - -- `docusaurus-types`, `docusaurus` - - [#7257](https://github.com/facebook/docusaurus/pull/7257) refactor: remove long-deprecated routesLoaded lifecycle ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#7277](https://github.com/facebook/docusaurus/pull/7277) refactor(theme-classic): move all sidebar-related config under themeConfig.docs.sidebar ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#6732](https://github.com/facebook/docusaurus/pull/6732) feat(core): rework client modules lifecycles, officially make API public ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-theme-classic` - - [#7176](https://github.com/facebook/docusaurus/pull/7176) refactor: customize code block line highlight color via CSS var ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils` - - [#7117](https://github.com/facebook/docusaurus/pull/7117) refactor(content-{blog,docs}): unify handling of tags ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#7027](https://github.com/facebook/docusaurus/pull/7027) refactor(content-docs): deduplicate types, JSDoc for some APIs ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#7304](https://github.com/facebook/docusaurus/pull/7304) fix(theme-classic): remove breadcrumb items without href from microdata ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7179](https://github.com/facebook/docusaurus/pull/7179) fix(theme-classic): do not add microdata item prop to trailing breadcrumb ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7173](https://github.com/facebook/docusaurus/pull/7173) fix(theme-classic): admonition title: disable text-transform on inline code blocks ([@chelproc](https://github.com/chelproc)) - - [#7048](https://github.com/facebook/docusaurus/pull/7048) fix(theme-classic): add caret for dropdown on mobile ([@lex111](https://github.com/lex111)) - - [#7025](https://github.com/facebook/docusaurus/pull/7025) fix: make docs page wrapper take full height ([@lex111](https://github.com/lex111)) - - [#7013](https://github.com/facebook/docusaurus/pull/7013) fix(theme-classic): adjust shadow on code block ([@chernodub](https://github.com/chernodub)) - - [#7015](https://github.com/facebook/docusaurus/pull/7015) fix(theme-classic): do not add caret for non-collapsible categories ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic` - - [#7294](https://github.com/facebook/docusaurus/pull/7294) fix(\*): make TypeScript realize that each plugin package has a default export ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#7285](https://github.com/facebook/docusaurus/pull/7285) fix(core): allow empty static directories ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7180](https://github.com/facebook/docusaurus/pull/7180) fix: pass pollOptions to webpack ([@JohnnyMcWeed](https://github.com/JohnnyMcWeed)) - - [#7184](https://github.com/facebook/docusaurus/pull/7184) fix(core): prevent 404 when accessing /page.html ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7225](https://github.com/facebook/docusaurus/pull/7225) fix: allow swizzling a component's parent folder ([@slorber](https://github.com/slorber)) - - [#7066](https://github.com/facebook/docusaurus/pull/7066) fix(core): all plugin lifecycles should receive translated content ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs` - - [#7233](https://github.com/facebook/docusaurus/pull/7233) fix(content-docs): make category index text translatable ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-common` - - [#7200](https://github.com/facebook/docusaurus/pull/7200) fix(theme-common): do not persist color mode for OS-triggered changes ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7057](https://github.com/facebook/docusaurus/pull/7057) fix(theme-common): use native scrolling when smooth behavior set in CSS ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7033](https://github.com/facebook/docusaurus/pull/7033) fix(theme): only parse HTML- and JSX-style comments in MD code ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog` - - [#7212](https://github.com/facebook/docusaurus/pull/7212) fix(content-blog): make footnote reference DOM ID unique on post listing page ([@AkiraVoid](https://github.com/AkiraVoid)) -- `docusaurus-utils`, `docusaurus` - - [#7187](https://github.com/facebook/docusaurus/pull/7187) fix(core): handle case where package.json is not available at CWD ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-translations` - - [#7222](https://github.com/facebook/docusaurus/pull/7222) fix(theme-translations): fix invalid pluralization in cs ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7166](https://github.com/facebook/docusaurus/pull/7166) fix(theme-translations): always try all possible locale resolutions ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#7164](https://github.com/facebook/docusaurus/pull/7164) fix: adjust spacing for custom search properly ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-debug`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-types`, `docusaurus` - - [#7143](https://github.com/facebook/docusaurus/pull/7143) fix(sitemap): exclude pages with robots noindex from sitemap ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-types` - - [#7078](https://github.com/facebook/docusaurus/pull/7078) fix(create): install types for JS template as well ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-utils` - - [#7043](https://github.com/facebook/docusaurus/pull/7043) fix(utils): parse Markdown headings with CRLF line break ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils`, `docusaurus` - - [#7023](https://github.com/facebook/docusaurus/pull/7023) refactor: fix a few places of path handling ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-types` - - [#7014](https://github.com/facebook/docusaurus/pull/7014) fix(types): declare history and react-loadable as dependencies ([@sulu5890](https://github.com/sulu5890)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic`, `docusaurus-theme-translations` - - [#7299](https://github.com/facebook/docusaurus/pull/7299) refactor: minor improvements for breadcrumbs ([@lex111](https://github.com/lex111)) -- `create-docusaurus` - - [#7290](https://github.com/facebook/docusaurus/pull/7290) refactor(create): add i18n config in init template ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7286](https://github.com/facebook/docusaurus/pull/7286) refactor(create): update screenshots in quick start tutorial ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7223](https://github.com/facebook/docusaurus/pull/7223) refactor: use generated-index in init templates ([@slorber](https://github.com/slorber)) - - [#7118](https://github.com/facebook/docusaurus/pull/7118) refactor(create): mention that the edit links can be removed ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-debug`, `docusaurus-theme-classic` - - [#7306](https://github.com/facebook/docusaurus/pull/7306) chore: upgrade Infima to alpha.39 ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-debug`, `docusaurus-types`, `docusaurus` - - [#7291](https://github.com/facebook/docusaurus/pull/7291) feat(types): JSDoc for docusaurus config fields ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#7267](https://github.com/facebook/docusaurus/pull/7267) fix(theme-common): allow details to not provide a summary ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7172](https://github.com/facebook/docusaurus/pull/7172) refactor: control base styling of code blocks via CSS vars ([@lex111](https://github.com/lex111)) - - [#7129](https://github.com/facebook/docusaurus/pull/7129) refactor(theme-classic): fix a few margin inconsistencies ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs`, `docusaurus-utils` - - [#7248](https://github.com/facebook/docusaurus/pull/7248) refactor: normalize Markdown linkification behavior, elaborate in documentation ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#7244](https://github.com/facebook/docusaurus/pull/7244) refactor: semantic markup improvement, fix validation warnings ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7183](https://github.com/facebook/docusaurus/pull/7183) refactor: use SVG icon for home breadcrumb ([@Dr-Electron](https://github.com/Dr-Electron)) - - [#7139](https://github.com/facebook/docusaurus/pull/7139) fix: proper spacing between generated card items on mobiles ([@lex111](https://github.com/lex111)) - - [#7134](https://github.com/facebook/docusaurus/pull/7134) fix(theme-classic): fix docs sidebar layout shifts when expanding categories ([@slorber](https://github.com/slorber)) - - [#7068](https://github.com/facebook/docusaurus/pull/7068) refactor(theme-classic): blog mobile secondary menu use consistent styles ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7004](https://github.com/facebook/docusaurus/pull/7004) fix(theme-classic): shrink title size on mobile ([@Pierre-Gilles](https://github.com/Pierre-Gilles)) -- `docusaurus-theme-translations` - - [#7214](https://github.com/facebook/docusaurus/pull/7214) chore(theme-translations): complete Polish translations ([@rev4324](https://github.com/rev4324)) - - [#7031](https://github.com/facebook/docusaurus/pull/7031) chore(theme-translations): complete German translations ([@deployn](https://github.com/deployn)) -- `create-docusaurus`, `docusaurus-theme-classic` - - [#7176](https://github.com/facebook/docusaurus/pull/7176) refactor: customize code block line highlight color via CSS var ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#7218](https://github.com/facebook/docusaurus/pull/7218) fix(cli): always show error stack to unhandled rejection ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7142](https://github.com/facebook/docusaurus/pull/7142) refactor(core): lower timeout before rendering progress bar to 200ms ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7103](https://github.com/facebook/docusaurus/pull/7103) fix(core): preserve Interpolate children semantics ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7029](https://github.com/facebook/docusaurus/pull/7029) refactor: console output improvements ([@lex111](https://github.com/lex111)) - - [#7017](https://github.com/facebook/docusaurus/pull/7017) refactor: remove copyright comment from swizzled components ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs`, `docusaurus-preset-classic`, `docusaurus-theme-classic` - - [#7148](https://github.com/facebook/docusaurus/pull/7148) feat(preset-classic, content-docs/client): JSDoc ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-debug`, `docusaurus-preset-classic` - - [#7122](https://github.com/facebook/docusaurus/pull/7122) feat(preset-classic): exclude debug plugin routes from sitemap ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` - - [#7113](https://github.com/facebook/docusaurus/pull/7113) test: improve test coverage ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus` - - [#7080](https://github.com/facebook/docusaurus/pull/7080) refactor: replace non-prop interface with type; allow plugin lifecycles to have sync type ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-logger`, `docusaurus-plugin-content-docs`, `docusaurus` - - [#7019](https://github.com/facebook/docusaurus/pull/7019) feat(logger): new "url" format, add double quotes around paths ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#7006](https://github.com/facebook/docusaurus/pull/7006) refactor: split and cleanup theme/DocPage ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#7005](https://github.com/facebook/docusaurus/pull/7005) refactor: split DocSidebarItem by item type ([@slorber](https://github.com/slorber)) - -#### :memo: Documentation - -- `docusaurus-logger` - - [#7305](https://github.com/facebook/docusaurus/pull/7305) docs: update docs for logger, add API docs to website ([@Josh-Cena](https://github.com/Josh-Cena)) -- Other - - [#7284](https://github.com/facebook/docusaurus/pull/7284) docs: add a paragraph about SSR as an optimization technique ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7278](https://github.com/facebook/docusaurus/pull/7278) docs: enhance docs about Markdown TOC and metadata ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7271](https://github.com/facebook/docusaurus/pull/7271) docs: specify Node version requirement to a minor ([@DanRoscigno](https://github.com/DanRoscigno)) - - [#7252](https://github.com/facebook/docusaurus/pull/7252) docs: update gtag docs to reflect what a GA4 tag looks like ([@johnnyreilly](https://github.com/johnnyreilly)) - - [#7240](https://github.com/facebook/docusaurus/pull/7240) docs: add PCC Archive site to showcase ([@CuratorCat](https://github.com/CuratorCat)) - - [#7239](https://github.com/facebook/docusaurus/pull/7239) docs: add Chaos mesh site to showcase ([@cwen0](https://github.com/cwen0)) - - [#7235](https://github.com/facebook/docusaurus/pull/7235) docs: add TiDB community books to showcase ([@shczhen](https://github.com/shczhen)) - - [#7236](https://github.com/facebook/docusaurus/pull/7236) docs: add documentation about pluralization ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7230](https://github.com/facebook/docusaurus/pull/7230) docs: add OSS Insight to showcase ([@sykp241095](https://github.com/sykp241095)) - - [#7208](https://github.com/facebook/docusaurus/pull/7208) docs: remove mention of "template" from README installation guide ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7159](https://github.com/facebook/docusaurus/pull/7159) docs: explain more clearly the purpose of a ref sidebar type ([@andrewnicols](https://github.com/andrewnicols)) - - [#7126](https://github.com/facebook/docusaurus/pull/7126) docs: multiple documentation improvements ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7123](https://github.com/facebook/docusaurus/pull/7123) refactor(showcase): enforce descriptions with maximum length of 120 characters ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7026](https://github.com/facebook/docusaurus/pull/7026) docs: correct plugin example filename ([@mxhdx](https://github.com/mxhdx)) - - [#7110](https://github.com/facebook/docusaurus/pull/7110) docs: add a note about additional languages needing to be Prism component names ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6746](https://github.com/facebook/docusaurus/pull/6746) fix(website): lazy-load YT iframe ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7061](https://github.com/facebook/docusaurus/pull/7061) docs: add docusaurus-plugin-typedoc to resources ([@nartc](https://github.com/nartc)) - - [#7059](https://github.com/facebook/docusaurus/pull/7059) docs: add firelordjs to showcase ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7050](https://github.com/facebook/docusaurus/pull/7050) docs: add import React statement in JSX file example ([@kaycebasques](https://github.com/kaycebasques)) - - [#7022](https://github.com/facebook/docusaurus/pull/7022) docs: add Easypanel to showcase ([@deiucanta](https://github.com/deiucanta)) - - [#7016](https://github.com/facebook/docusaurus/pull/7016) docs: consistently use sidebars.js filename ([@leedom92](https://github.com/leedom92)) - - [#7020](https://github.com/facebook/docusaurus/pull/7020) docs: add Divine WSF and Ghostly to showcase ([@LeviticusMB](https://github.com/LeviticusMB)) - - [#7000](https://github.com/facebook/docusaurus/pull/7000) docs: remove unnecessary semicolon ([@imsingh](https://github.com/imsingh)) -- `docusaurus-plugin-content-docs`, `docusaurus-utils` - - [#7248](https://github.com/facebook/docusaurus/pull/7248) refactor: normalize Markdown linkification behavior, elaborate in documentation ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils` - - [#7081](https://github.com/facebook/docusaurus/pull/7081) docs: fix some casing inconsistencies ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :wrench: Maintenance - -- Other - - [#7309](https://github.com/facebook/docusaurus/pull/7309) chore: use "Maintenance" instead of "Internal" in changelog ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7300](https://github.com/facebook/docusaurus/pull/7300) misc: check doc page by Lighthouse CI ([@lex111](https://github.com/lex111)) - - [#7266](https://github.com/facebook/docusaurus/pull/7266) misc: add links section to PR template ([@slorber](https://github.com/slorber)) - - [#7224](https://github.com/facebook/docusaurus/pull/7224) chore: GitHub Actions cancel-in-progress ([@slorber](https://github.com/slorber)) - - [#7216](https://github.com/facebook/docusaurus/pull/7216) chore: remove netlify-cli from devDependencies ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7211](https://github.com/facebook/docusaurus/pull/7211) chore: replace node 17 with 18 in CI matrix ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7168](https://github.com/facebook/docusaurus/pull/7168) misc: add CI actions/dependency-review-action for security ([@slorber](https://github.com/slorber)) - - [#6984](https://github.com/facebook/docusaurus/pull/6984) misc: pin actions to a full-length commit SHA ([@naveensrinivasan](https://github.com/naveensrinivasan)) - - [#7002](https://github.com/facebook/docusaurus/pull/7002) chore: regen examples for 2.0 beta.18 ([@slorber](https://github.com/slorber)) -- `docusaurus-logger`, `docusaurus-remark-plugin-npm2yarn` - - [#7295](https://github.com/facebook/docusaurus/pull/7295) refactor: use export = syntax for Node utility packages ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#7293](https://github.com/facebook/docusaurus/pull/7293) refactor(types): move non-core, non-public types out of the types package ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-types`, `docusaurus` - - [#7292](https://github.com/facebook/docusaurus/pull/7292) refactor(core): collocate CLI commands and their option types ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7084](https://github.com/facebook/docusaurus/pull/7084) refactor(core): code cleanup ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus` - - [#7282](https://github.com/facebook/docusaurus/pull/7282) refactor(core): prefetch/preload refactor ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#7273](https://github.com/facebook/docusaurus/pull/7273) refactor(theme-classic): multiple re-arrangements ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7268](https://github.com/facebook/docusaurus/pull/7268) refactor(theme-classic): DocPage theme refactors polish ([@slorber](https://github.com/slorber)) - - [#7269](https://github.com/facebook/docusaurus/pull/7269) refactor: extract useSkipToContent() ([@slorber](https://github.com/slorber)) - - [#7175](https://github.com/facebook/docusaurus/pull/7175) refactor(theme-classic): split CodeBlock ([@slorber](https://github.com/slorber)) - - [#7067](https://github.com/facebook/docusaurus/pull/7067) refactor(theme-classic): extract doc-related navbar items' logic to theme-common ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7021](https://github.com/facebook/docusaurus/pull/7021) refactor(theme): extract plumbing code of BTT button into theme-common ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#7270](https://github.com/facebook/docusaurus/pull/7270) refactor(theme-classic): refactor TOC-related theme components ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#7220](https://github.com/facebook/docusaurus/pull/7220) refactor(cli): normalize the application of default option values ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7141](https://github.com/facebook/docusaurus/pull/7141) refactor(core): minor PendingNavigation refactor ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs` - - [#7243](https://github.com/facebook/docusaurus/pull/7243) chore: upgrade Jest to 28; add GitHub-actions reporter ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#7140](https://github.com/facebook/docusaurus/pull/7140) refactor(content-docs): split version handling into several files ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-live-codeblock`, `docusaurus` - - [#7194](https://github.com/facebook/docusaurus/pull/7194) fix: fix a few internal declaration semantic errors ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-migrate`, `docusaurus-theme-translations`, `docusaurus` - - [#7186](https://github.com/facebook/docusaurus/pull/7186) refactor: prefer fs.readJSON over readFile.then(JSON.parse) ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages` - - [#7145](https://github.com/facebook/docusaurus/pull/7145) refactor: unify how MDX content types are represented ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#7138](https://github.com/facebook/docusaurus/pull/7138) chore: upgrade dependencies + upgrade React types ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#7131](https://github.com/facebook/docusaurus/pull/7131) chore: disable string escaping in snapshots ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` - - [#7054](https://github.com/facebook/docusaurus/pull/7054) refactor(core): refactor routes generation logic ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-types`, `docusaurus` - - [#7042](https://github.com/facebook/docusaurus/pull/7042) refactor(core): reorganize files ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs`, `docusaurus-utils`, `docusaurus` - - [#7037](https://github.com/facebook/docusaurus/pull/7037) refactor(core): reorganize functions ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#7027](https://github.com/facebook/docusaurus/pull/7027) refactor(content-docs): deduplicate types, JSDoc for some APIs ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :running_woman: Performance - -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils-common` - - [#7085](https://github.com/facebook/docusaurus/pull/7085) refactor: mark a few client-side packages as side-effect-free ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-remark-plugin-npm2yarn` - - [#4997](https://github.com/facebook/docusaurus/pull/4997) perf(mdx-loader): cache mdx/remark compiler instances ([@phryneas](https://github.com/phryneas)) - -#### Committers: 47 - -- Aaron Nwabuoku ([@aerovulpe](https://github.com/aerovulpe)) -- AkiraVoid ([@AkiraVoid](https://github.com/AkiraVoid)) -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Andrei Canta ([@deiucanta](https://github.com/deiucanta)) -- Andrew Lyons ([@andrewnicols](https://github.com/andrewnicols)) -- ApsarasX ([@ApsarasX](https://github.com/ApsarasX)) -- Chau Tran ([@nartc](https://github.com/nartc)) -- Chinazaekpere Ngubo ([@dr-ngubo](https://github.com/dr-ngubo)) -- Cwen Yin ([@cwen0](https://github.com/cwen0)) -- Dan Roscigno ([@DanRoscigno](https://github.com/DanRoscigno)) -- Elias Papavasileiou ([@elias-pap](https://github.com/elias-pap)) -- Evan ([@sulu5890](https://github.com/sulu5890)) -- Fusang❀ ([@cxOrz](https://github.com/cxOrz)) -- Indermohan Singh ([@imsingh](https://github.com/imsingh)) -- JMW ([@JohnnyMcWeed](https://github.com/JohnnyMcWeed)) -- Jeffrey Aven ([@jeffreyaven](https://github.com/jeffreyaven)) -- Jody Heavener ([@jodyheavener](https://github.com/jodyheavener)) -- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Karl Ward ([@mjau-mjau](https://github.com/mjau-mjau)) -- Kayce Basques ([@kaycebasques](https://github.com/kaycebasques)) -- Leedom ([@leedom92](https://github.com/leedom92)) -- Lenz Weber-Tronic ([@phryneas](https://github.com/phryneas)) -- Lukas Bach ([@lukasbach](https://github.com/lukasbach)) -- Martin Blom ([@LeviticusMB](https://github.com/LeviticusMB)) -- Naveen ([@naveensrinivasan](https://github.com/naveensrinivasan)) -- Pablo Cordon ([@pcordon](https://github.com/pcordon)) -- Pierre-Gilles Leymarie ([@Pierre-Gilles](https://github.com/Pierre-Gilles)) -- Qi Zhang ([@zzzhangqi](https://github.com/zzzhangqi)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Viktor Chernodub ([@chernodub](https://github.com/chernodub)) -- Zac A ([@sandypockets](https://github.com/sandypockets)) -- [@Dr-Electron](https://github.com/Dr-Electron) -- [@chelproc](https://github.com/chelproc) -- [@deployn](https://github.com/deployn) -- [@duanwilliam](https://github.com/duanwilliam) -- [@kgolubic](https://github.com/kgolubic) -- [@redhat123456](https://github.com/redhat123456) -- [@surendran82](https://github.com/surendran82) -- [@svix-ken](https://github.com/svix-ken) -- apq ([@AntonPalmqvist](https://github.com/AntonPalmqvist)) -- curatorcat.pcc.eth ([@CuratorCat](https://github.com/CuratorCat)) -- czhen ([@shczhen](https://github.com/shczhen)) -- loic ([@layerzzzio](https://github.com/layerzzzio)) -- mehdim ([@mxhdx](https://github.com/mxhdx)) -- rev ([@rev4324](https://github.com/rev4324)) -- sykp241095 ([@sykp241095](https://github.com/sykp241095)) - -## 2.0.0-beta.18 (2022-03-25) - -#### :rocket: New Feature - -- `docusaurus-mdx-loader`, `docusaurus-theme-classic` - - [#6990](https://github.com/facebook/docusaurus/pull/6990) feat: lazy-load external images + ability to customize image display ([@slorber](https://github.com/slorber)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus` - - [#6933](https://github.com/facebook/docusaurus/pull/6933) feat(core,theme): useRouteContext + HtmlClassNameProvider ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus` - - [#6921](https://github.com/facebook/docusaurus/pull/6921) feat(core): allow plugin lifecycles to return relative paths ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#6697](https://github.com/facebook/docusaurus/pull/6697) feat: add SEO microdata for doc breadcrumbs ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6842](https://github.com/facebook/docusaurus/pull/6842) feat(theme-classic): MDXContent wrapper component ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs` - - [#6780](https://github.com/facebook/docusaurus/pull/6780) feat(content-docs): allow custom props through _category_.json ([@taejs](https://github.com/taejs)) - -#### :boom: Breaking Change - -- `docusaurus-plugin-content-docs` - - [#6859](https://github.com/facebook/docusaurus/pull/6859) feat(content-docs): autogenerate category with linked doc metadata as fallback ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#6989](https://github.com/facebook/docusaurus/pull/6989) refactor: extract MDX components ([@slorber](https://github.com/slorber)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#6925](https://github.com/facebook/docusaurus/pull/6925) refactor(theme-{classic,common}): refactor site/page/search metadata + apply className on html element ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6895](https://github.com/facebook/docusaurus/pull/6895) refactor(theme-{classic,common}): split navbar into smaller components + cleanup + swizzle config ([@slorber](https://github.com/slorber)) - - [#6930](https://github.com/facebook/docusaurus/pull/6930) refactor(theme-{classic,common}): refactor ColorModeToggle + useColorMode() hook ([@lex111](https://github.com/lex111)) - -#### :bug: Bug Fix - -- `docusaurus` - - [#6993](https://github.com/facebook/docusaurus/pull/6993) fix(core): prevent useBaseUrl returning /base/base when on /base ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6936](https://github.com/facebook/docusaurus/pull/6936) fix: remove semicolon from HTML output ([@lex111](https://github.com/lex111)) - - [#6849](https://github.com/facebook/docusaurus/pull/6849) fix(cli): write-heading-id should not generate colliding slugs when not overwriting ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#6983](https://github.com/facebook/docusaurus/pull/6983) fix(search): bump Infima, fix search issue due to broken CSS selector ([@slorber](https://github.com/slorber)) -- `docusaurus-utils-validation` - - [#6977](https://github.com/facebook/docusaurus/pull/6977) fix(validation): allow non-object params to remark/rehype plugins ([@aloisklink](https://github.com/aloisklink)) -- `docusaurus-plugin-content-docs`, `docusaurus-utils` - - [#6973](https://github.com/facebook/docusaurus/pull/6973) fix(content-docs): suppress git error on multiple occurrences ([@felipecrs](https://github.com/felipecrs)) -- `docusaurus-plugin-content-blog` - - [#6947](https://github.com/facebook/docusaurus/pull/6947) fix(content-blog): only create archive route if there are blog posts ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6918](https://github.com/facebook/docusaurus/pull/6918) fix(content-blog): remove double leading slash in blog-only paginated view ([@heowc](https://github.com/heowc)) -- `docusaurus-theme-search-algolia` - - [#6888](https://github.com/facebook/docusaurus/pull/6888) fix(theme-algolia): declare content-docs as dependency ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-translations` - - [#6847](https://github.com/facebook/docusaurus/pull/6847) fix: minor Chinese translation fixes ([@rccttwd](https://github.com/rccttwd)) - -#### :nail_care: Polish - -- `docusaurus-plugin-content-docs` - - [#6859](https://github.com/facebook/docusaurus/pull/6859) feat(content-docs): autogenerate category with linked doc metadata as fallback ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6887](https://github.com/facebook/docusaurus/pull/6887) fix(content-docs): give context about sidebar loading failure ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs`, `docusaurus-utils-validation`, `docusaurus` - - [#6997](https://github.com/facebook/docusaurus/pull/6997) fix(validation): improve error messages for a few schemas ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#6971](https://github.com/facebook/docusaurus/pull/6971) refactor: improve a11y of dropdown menu ([@lex111](https://github.com/lex111)) - - [#6987](https://github.com/facebook/docusaurus/pull/6987) refactor(theme-classic): cleanup of code blocks ([@lex111](https://github.com/lex111)) - - [#6950](https://github.com/facebook/docusaurus/pull/6950) refactor(theme-classic): clean up CSS of doc cards ([@lex111](https://github.com/lex111)) - - [#6994](https://github.com/facebook/docusaurus/pull/6994) refactor: better external link icon positioning ([@lex111](https://github.com/lex111)) - - [#6989](https://github.com/facebook/docusaurus/pull/6989) refactor: extract MDX components ([@slorber](https://github.com/slorber)) - - [#6985](https://github.com/facebook/docusaurus/pull/6985) refactor(theme-classic): remove span wrappers from layout links ([@lex111](https://github.com/lex111)) - - [#6986](https://github.com/facebook/docusaurus/pull/6986) fix(theme-classic): minor code copy button improvements ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6964](https://github.com/facebook/docusaurus/pull/6964) refactor: replace text-based copy code button with icons ([@lex111](https://github.com/lex111)) - - [#6932](https://github.com/facebook/docusaurus/pull/6932) refactor(theme-classic): little breadcrumbs improvements ([@lex111](https://github.com/lex111)) - - [#6914](https://github.com/facebook/docusaurus/pull/6914) feat(theme-classic): set aria-expanded on expandable sidebar categories ([@pkowaluk](https://github.com/pkowaluk)) - - [#6844](https://github.com/facebook/docusaurus/pull/6844) refactor(theme-classic): split sidebar into smaller parts ([@slorber](https://github.com/slorber)) - - [#6846](https://github.com/facebook/docusaurus/pull/6846) refactor(theme-classic): consistently add span wrapper for layout links ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#6980](https://github.com/facebook/docusaurus/pull/6980) feat(utils): JSDoc for all APIs ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-common` - - [#6974](https://github.com/facebook/docusaurus/pull/6974) feat(theme-common): JSDoc for all APIs ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#6784](https://github.com/facebook/docusaurus/pull/6784) feat(core): allow configureWebpack to return undefined ([@yorkie](https://github.com/yorkie)) - - [#6941](https://github.com/facebook/docusaurus/pull/6941) refactor(core): improve error message when a page has no default-export ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6878](https://github.com/facebook/docusaurus/pull/6878) fix(core): ensure stable webpack theme aliases sorting ([@jrvidal](https://github.com/jrvidal)) - - [#6854](https://github.com/facebook/docusaurus/pull/6854) fix(core): fix swizzle legend typo ([@DigiPie](https://github.com/DigiPie)) - - [#6850](https://github.com/facebook/docusaurus/pull/6850) fix(core): make plugin lifecycles consistently bound to the plugin instance ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils` - - [#6937](https://github.com/facebook/docusaurus/pull/6937) fix(content-docs): warn when files are not tracked ([@felipecrs](https://github.com/felipecrs)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#6925](https://github.com/facebook/docusaurus/pull/6925) refactor(theme-{classic,common}): refactor site/page/search metadata + apply className on html element ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6895](https://github.com/facebook/docusaurus/pull/6895) refactor(theme-{classic,common}): split navbar into smaller components + cleanup + swizzle config ([@slorber](https://github.com/slorber)) - - [#6930](https://github.com/facebook/docusaurus/pull/6930) refactor(theme-{classic,common}): refactor ColorModeToggle + useColorMode() hook ([@lex111](https://github.com/lex111)) - - [#6894](https://github.com/facebook/docusaurus/pull/6894) refactor(theme-classic): split theme footer into smaller components + swizzle config ([@slorber](https://github.com/slorber)) -- `docusaurus-types`, `docusaurus` - - [#6929](https://github.com/facebook/docusaurus/pull/6929) refactor(core): minor routes type improvement ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap` - - [#6928](https://github.com/facebook/docusaurus/pull/6928) chore(pwa, sitemap, client-redirects, ideal-image): JSDoc for types ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic`, `docusaurus-utils` - - [#6922](https://github.com/facebook/docusaurus/pull/6922) refactor(content-blog): clean up type definitions; in-code documentation ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-translations` - - [#6781](https://github.com/facebook/docusaurus/pull/6781) feat(theme-translations): complete Russian translations ([@dragomano](https://github.com/dragomano)) - - [#6877](https://github.com/facebook/docusaurus/pull/6877) chore(theme-translations): complete Vietnamese translations ([@datlechin](https://github.com/datlechin)) -- `docusaurus-plugin-content-blog` - - [#6909](https://github.com/facebook/docusaurus/pull/6909) refactor(content-blog): improve error message of authors map validation ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus` - - [#6860](https://github.com/facebook/docusaurus/pull/6860) fix(create): load entry file after node version checking ([@taejs](https://github.com/taejs)) - -#### :memo: Documentation - -- Other - - [#6988](https://github.com/facebook/docusaurus/pull/6988) docs: fix example admonition syntax ([@kaycebasques](https://github.com/kaycebasques)) - - [#6978](https://github.com/facebook/docusaurus/pull/6978) docs: npm run tsc -> npx tsc ([@jadonn](https://github.com/jadonn)) - - [#6952](https://github.com/facebook/docusaurus/pull/6952) docs: add K3ai to showcase ([@alefesta](https://github.com/alefesta)) - - [#6948](https://github.com/facebook/docusaurus/pull/6948) docs: add pdfme docs to showcase ([@hand-dot](https://github.com/hand-dot)) - - [#6943](https://github.com/facebook/docusaurus/pull/6943) docs: add SeaORM docs to showcase ([@billy1624](https://github.com/billy1624)) - - [#6926](https://github.com/facebook/docusaurus/pull/6926) docs: clarify the usage of slug ([@kaycebasques](https://github.com/kaycebasques)) - - [#6911](https://github.com/facebook/docusaurus/pull/6911) docs: add Reactive Button site to showcase ([@arifszn](https://github.com/arifszn)) - - [#6904](https://github.com/facebook/docusaurus/pull/6904) docs: update image for digital support services ([@PatelN123](https://github.com/PatelN123)) - - [#6892](https://github.com/facebook/docusaurus/pull/6892) docs: add EduLinks site to showcase ([@odarpi](https://github.com/odarpi)) - - [#6889](https://github.com/facebook/docusaurus/pull/6889) docs: editorial fixes ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6883](https://github.com/facebook/docusaurus/pull/6883) docs(cli): add info about development on github codespaces ([@vedantmgoyal2009](https://github.com/vedantmgoyal2009)) - - [#6856](https://github.com/facebook/docusaurus/pull/6856) docs: add Reddit Image Fetcher site to showcase ([@arifszn](https://github.com/arifszn)) - - [#6875](https://github.com/facebook/docusaurus/pull/6875) docs: update TRPG Engine showcase ([@moonrailgun](https://github.com/moonrailgun)) - - [#6871](https://github.com/facebook/docusaurus/pull/6871) docs: mark clutch and gulp as open-source ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6862](https://github.com/facebook/docusaurus/pull/6862) docs: update showcase data ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6837](https://github.com/facebook/docusaurus/pull/6837) docs: add PcapPlusPlus to showcase ([@seladb](https://github.com/seladb)) - - [#6832](https://github.com/facebook/docusaurus/pull/6832) docs: add Spicetify site to showcase ([@afonsojramos](https://github.com/afonsojramos)) - - [#6830](https://github.com/facebook/docusaurus/pull/6830) docs: simplify imported code blocks syntax ([@nathan-contino-mongo](https://github.com/nathan-contino-mongo)) -- `docusaurus-types` - - [#6881](https://github.com/facebook/docusaurus/pull/6881) docs: mention configureWebpack devServer return value ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus` - - [#6833](https://github.com/facebook/docusaurus/pull/6833) docs: make tutorial code block directly copyable ([@samgutentag](https://github.com/samgutentag)) - -#### :house: Internal - -- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#6995](https://github.com/facebook/docusaurus/pull/6995) refactor: ensure all types are using index signature instead of Record ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-cssnano-preset`, `docusaurus-plugin-pwa`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#6991](https://github.com/facebook/docusaurus/pull/6991) chore: upgrade dependencies ([@Josh-Cena](https://github.com/Josh-Cena)) -- `lqip-loader` - - [#6992](https://github.com/facebook/docusaurus/pull/6992) refactor(lqip-loader): remove unused palette option ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#6975](https://github.com/facebook/docusaurus/pull/6975) chore: update static-site-generator-webpack-plugin ([@slorber](https://github.com/slorber)) -- `stylelint-copyright` - - [#6967](https://github.com/facebook/docusaurus/pull/6967) chore: publish stylelint-copyright again ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus` - - [#6961](https://github.com/facebook/docusaurus/pull/6961) refactor: unify how validateOptions is handled ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-types` - - [#6957](https://github.com/facebook/docusaurus/pull/6957) chore(types): remove querystring from dependencies ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-common`, `docusaurus` - - [#6956](https://github.com/facebook/docusaurus/pull/6956) test: improve test coverage; reorder theme-common files ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6955](https://github.com/facebook/docusaurus/pull/6955) refactor(core): move browserContext and docusaurusContext out of client exports ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6944](https://github.com/facebook/docusaurus/pull/6944) chore: migrate Jest and website to SWC ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-utils` - - [#6951](https://github.com/facebook/docusaurus/pull/6951) test: fix Windows test for gitUtils ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` - - [#6931](https://github.com/facebook/docusaurus/pull/6931) chore: tighten ESLint config ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects` - - [#6924](https://github.com/facebook/docusaurus/pull/6924) refactor(client-redirects): migrate validation to validateOptions lifecycle ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-cssnano-preset`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#6916](https://github.com/facebook/docusaurus/pull/6916) chore: upgrade dependencies ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-plugin-content-docs`, `docusaurus-theme-translations`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` - - [#6912](https://github.com/facebook/docusaurus/pull/6912) test: improve test coverage; multiple internal refactors ([@Josh-Cena](https://github.com/Josh-Cena)) -- Other - - [#6910](https://github.com/facebook/docusaurus/pull/6910) refactor: convert Jest infrastructure to TS ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6838](https://github.com/facebook/docusaurus/pull/6838) fix(website): changelog plugin leads to CI bugs on release ([@slorber](https://github.com/slorber)) -- `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` - - [#6908](https://github.com/facebook/docusaurus/pull/6908) chore: do not print prototype in jest snapshot ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#6906](https://github.com/facebook/docusaurus/pull/6906) refactor: install eslint-plugin-regexp ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus` - - [#6905](https://github.com/facebook/docusaurus/pull/6905) test: improve test coverage; properly test core client APIs ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-sitemap`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus` - - [#6903](https://github.com/facebook/docusaurus/pull/6903) chore: spell-check test files ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#6902](https://github.com/facebook/docusaurus/pull/6902) test(theme-common): improve test coverage ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-cssnano-preset`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` - - [#6900](https://github.com/facebook/docusaurus/pull/6900) test: enable a few jest eslint rules ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#6898](https://github.com/facebook/docusaurus/pull/6898) refactor: import jest as global; unify import style of some modules ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6891](https://github.com/facebook/docusaurus/pull/6891) refactor(theme-classic): avoid using clsx class dict with CSS modules ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus` - - [#6880](https://github.com/facebook/docusaurus/pull/6880) refactor: prefer fs.outputFile to ensureDir + writeFile ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-pwa`, `docusaurus-types`, `docusaurus` - - [#6866](https://github.com/facebook/docusaurus/pull/6866) refactor: improve types ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus`, `lqip-loader` - - [#6864](https://github.com/facebook/docusaurus/pull/6864) refactor: remove unnecessary default values normalized during validation ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-migrate`, `docusaurus` - - [#6861](https://github.com/facebook/docusaurus/pull/6861) refactor: make JS executables included in the tsconfig for editor hints ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` - - [#6857](https://github.com/facebook/docusaurus/pull/6857) test: improve test coverage ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#6852](https://github.com/facebook/docusaurus/pull/6852) refactor: enable a few TS flags ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### Committers: 28 - -- Afonso Jorge Ramos ([@afonsojramos](https://github.com/afonsojramos)) -- Alessandro Festa ([@alefesta](https://github.com/alefesta)) -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Alois Klink ([@aloisklink](https://github.com/aloisklink)) -- Ariful Alam ([@arifszn](https://github.com/arifszn)) -- Begula ([@vedantmgoyal2009](https://github.com/vedantmgoyal2009)) -- Billy Chan ([@billy1624](https://github.com/billy1624)) -- Bugo ([@dragomano](https://github.com/dragomano)) -- Evan ([@DigiPie](https://github.com/DigiPie)) -- Felipe Santos ([@felipecrs](https://github.com/felipecrs)) -- Jadon N ([@jadonn](https://github.com/jadonn)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Kayce Basques ([@kaycebasques](https://github.com/kaycebasques)) -- Kyohei Fukuda ([@hand-dot](https://github.com/hand-dot)) -- Nayan Patel ([@PatelN123](https://github.com/PatelN123)) -- Ngô Quốc Đạt ([@datlechin](https://github.com/datlechin)) -- Odarpi ([@odarpi](https://github.com/odarpi)) -- Pawel Kowaluk ([@pkowaluk](https://github.com/pkowaluk)) -- Roberto Vidal ([@jrvidal](https://github.com/jrvidal)) -- Sam Gutentag ([@samgutentag](https://github.com/samgutentag)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tsz W. TAM ([@rccttwd](https://github.com/rccttwd)) -- WonChul Heo ([@heowc](https://github.com/heowc)) -- Yorkie Liu ([@yorkie](https://github.com/yorkie)) -- [@seladb](https://github.com/seladb) -- moonrailgun ([@moonrailgun](https://github.com/moonrailgun)) -- nate contino ([@nathan-contino-mongo](https://github.com/nathan-contino-mongo)) -- tae ([@taejs](https://github.com/taejs)) - -## 2.0.0-beta.17 (2022-03-03) - -#### :rocket: New Feature - -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` - - [#6783](https://github.com/facebook/docusaurus/pull/6783) feat: allow blog authors email ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :boom: Breaking Change - -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6771](https://github.com/facebook/docusaurus/pull/6771) refactor(theme-classic): replace color mode toggle with button; remove switchConfig ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#6827](https://github.com/facebook/docusaurus/pull/6827) fix(theme-classic): restore docusaurus search meta ([@slorber](https://github.com/slorber)) - - [#6767](https://github.com/facebook/docusaurus/pull/6767) fix(theme-classic): allow code tags containing inline elements to stay inline ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-common` - - [#6824](https://github.com/facebook/docusaurus/pull/6824) fix(theme-common): breadcrumbs home bug in docs-only ([@slorber](https://github.com/slorber)) - - [#6816](https://github.com/facebook/docusaurus/pull/6816) fix(theme-common): docs breadcrumbs not working with baseUrl ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs` - - [#6700](https://github.com/facebook/docusaurus/pull/6700) fix(content-docs): always sort autogenerated sidebar items by file/folder name by default ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#6812](https://github.com/facebook/docusaurus/pull/6812) fix(core): remove hash/query when filtering existing files for broken link check ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader` - - [#6779](https://github.com/facebook/docusaurus/pull/6779) fix(mdx-loader): suppress image reading warning in Yarn PnP; log warning instead of error ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus` - - [#6762](https://github.com/facebook/docusaurus/pull/6762) fix(create): update broken SVG paths in templates ([@anicholls](https://github.com/anicholls)) - -#### :nail_care: Polish - -- `docusaurus-theme-common` - - [#6826](https://github.com/facebook/docusaurus/pull/6826) refactor(theme-common): unify missing context errors ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6771](https://github.com/facebook/docusaurus/pull/6771) refactor(theme-classic): replace color mode toggle with button; remove switchConfig ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#6769](https://github.com/facebook/docusaurus/pull/6769) refactor(theme-classic): use Material icon for language dropdown ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader` - - [#6792](https://github.com/facebook/docusaurus/pull/6792) fix(mdx-loader): allow image paths to be URL encoded ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :memo: Documentation - -- Other - - [#6825](https://github.com/facebook/docusaurus/pull/6825) docs: Adds Netlify one click deploy to README ([@PatelN123](https://github.com/PatelN123)) - - [#6818](https://github.com/facebook/docusaurus/pull/6818) docs: add deploy with vercel button to README ([@PatelN123](https://github.com/PatelN123)) - - [#6817](https://github.com/facebook/docusaurus/pull/6817) docs: fix broken links ([@PatelN123](https://github.com/PatelN123)) - - [#6811](https://github.com/facebook/docusaurus/pull/6811) docs: add homepage banner in support of Ukraine ([@dmitryvinn](https://github.com/dmitryvinn)) - - [#6813](https://github.com/facebook/docusaurus/pull/6813) docs: mark dyte as opensource in showcase ([@vaibhavshn](https://github.com/vaibhavshn)) - - [#6776](https://github.com/facebook/docusaurus/pull/6776) docs: make GitHub actions explanation aligned with the code ([@arifszn](https://github.com/arifszn)) - - [#6772](https://github.com/facebook/docusaurus/pull/6772) docs: add basic documentation about client modules ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus` - - [#6815](https://github.com/facebook/docusaurus/pull/6815) fix: consistently use `max-width: 996px` in media queries ([@dstotijn](https://github.com/dstotijn)) - -#### :house: Internal - -- `docusaurus-plugin-content-docs` - - [#6821](https://github.com/facebook/docusaurus/pull/6821) test(content-docs): refactor navigation test snapshot ([@Josh-Cena](https://github.com/Josh-Cena)) -- Other - - [#6768](https://github.com/facebook/docusaurus/pull/6768) test: add TypeScript template to E2E test matrix ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-utils` - - [#6773](https://github.com/facebook/docusaurus/pull/6773) refactor(utils): categorize functions into separate files ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate` - - [#6761](https://github.com/facebook/docusaurus/pull/6761) chore: various internal fixes ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### Committers: 8 - -- Alex Nicholls ([@anicholls](https://github.com/anicholls)) -- Ariful Alam ([@arifszn](https://github.com/arifszn)) -- David Stotijn ([@dstotijn](https://github.com/dstotijn)) -- Dmitry Vinnik ([@dmitryvinn](https://github.com/dmitryvinn)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Nayan Patel ([@PatelN123](https://github.com/PatelN123)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Vaibhav Shinde ([@vaibhavshn](https://github.com/vaibhavshn)) - -## 2.0.0-beta.16 (2022-02-25) - -#### :rocket: New Feature - -- `docusaurus-logger`, `docusaurus-module-type-aliases`, `docusaurus-plugin-debug`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus` - - [#6243](https://github.com/facebook/docusaurus/pull/6243) feat(core): brand new swizzle CLI experience ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus` - - [#6750](https://github.com/facebook/docusaurus/pull/6750) feat(create): new --package-manager option; interactive package manager selection ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6610](https://github.com/facebook/docusaurus/pull/6610) feat(create): allow specifying a git clone strategy ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6723](https://github.com/facebook/docusaurus/pull/6723) feat: sync color mode between browser tabs ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-search-algolia` - - [#6692](https://github.com/facebook/docusaurus/pull/6692) feat(search-algolia): allow disabling search page and configuring path ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6517](https://github.com/facebook/docusaurus/pull/6517) feat(docs,theme-classic): docs breadcrumbs ([@jodyheavener](https://github.com/jodyheavener)) - - [#6519](https://github.com/facebook/docusaurus/pull/6519) feat(content-docs): sidebar item type "html" for rendering pure markup ([@jodyheavener](https://github.com/jodyheavener)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils` - - [#6593](https://github.com/facebook/docusaurus/pull/6593) feat(content-blog): infer blog post date from git history ([@felipecrs](https://github.com/felipecrs)) -- `docusaurus-plugin-content-docs` - - [#6619](https://github.com/facebook/docusaurus/pull/6619) feat(content-docs): add custom props front matter ([@TheCatLady](https://github.com/TheCatLady)) - - [#6452](https://github.com/facebook/docusaurus/pull/6452) feat(content-docs): allow explicitly disabling index page for generated category ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog` - - [#6603](https://github.com/facebook/docusaurus/pull/6603) feat(content-blog): allow customizing blog archive component through option ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` - - [#6221](https://github.com/facebook/docusaurus/pull/6221) feat(content-blog): Allow pagination for BlogTagsPostsPage ([@redhoyasa](https://github.com/redhoyasa)) - -#### :boom: Breaking Change - -- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` - - [#6752](https://github.com/facebook/docusaurus/pull/6752) chore: upgrade docsearch-react to v3 stable, bump dependencies ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types` - - [#6729](https://github.com/facebook/docusaurus/pull/6729) refactor: make MDX export a flat TOC list instead of tree ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus` - - [#6740](https://github.com/facebook/docusaurus/pull/6740) refactor: remove deprecated Webpack utils & validation escape hatch ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#6707](https://github.com/facebook/docusaurus/pull/6707) refactor(theme-classic): bias again search metadata toward Algolia DocSearch ([@slorber](https://github.com/slorber)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-common`, `docusaurus` - - [#6651](https://github.com/facebook/docusaurus/pull/6651) refactor: reduce exported members of docusaurus router ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :bug: Bug Fix - -- `docusaurus-theme-common` - - [#6758](https://github.com/facebook/docusaurus/pull/6758) fix(theme-common): isSamePath should be case-insensitive ([@slorber](https://github.com/slorber)) - - [#6748](https://github.com/facebook/docusaurus/pull/6748) fix(theme-classic): temporarily disable toc heading autoscrolling ([@slorber](https://github.com/slorber)) - - [#6696](https://github.com/facebook/docusaurus/pull/6696) fix(theme-common): do not run useLocationChange when hot reloading ([@lex111](https://github.com/lex111)) - - [#6490](https://github.com/facebook/docusaurus/pull/6490) fix(theme-classic): do not switch color modes when printing ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6749](https://github.com/facebook/docusaurus/pull/6749) fix(theme-classic): fix breadcrumb home link bug with new useHomePageRoute() hook ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs` - - [#6720](https://github.com/facebook/docusaurus/pull/6720) fix(content-docs): create assets for frontmatter images ([@lebalz](https://github.com/lebalz)) - - [#6592](https://github.com/facebook/docusaurus/pull/6592) fix(content-docs): read last update from inner git repositories ([@felipecrs](https://github.com/felipecrs)) - - [#6477](https://github.com/facebook/docusaurus/pull/6477) fix(content-docs): export versioning utils ([@milesj](https://github.com/milesj)) -- `docusaurus-mdx-loader` - - [#6712](https://github.com/facebook/docusaurus/pull/6712) fix(mdx-loader): make headings containing links properly formatted in ToC ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#6701](https://github.com/facebook/docusaurus/pull/6701) fix(cli): disable directory listing in serve ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6607](https://github.com/facebook/docusaurus/pull/6607) fix(cli): log error itself on unhandled rejection ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6500](https://github.com/facebook/docusaurus/pull/6500) fix(cli): allow passing a list of file names to write-heading-ids ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6496](https://github.com/facebook/docusaurus/pull/6496) fix(core): configValidation should allow inline theme functions ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#6652](https://github.com/facebook/docusaurus/pull/6652) fix(theme-classic): minor BTT button fixes ([@lex111](https://github.com/lex111)) - - [#6612](https://github.com/facebook/docusaurus/pull/6612) fix(theme-classic): make Prism additional languages properly server-side rendered ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6599](https://github.com/facebook/docusaurus/pull/6599) fix(theme-classic): add docSidebar as allowed item in dropdown ([@homotechsual](https://github.com/homotechsual)) - - [#6531](https://github.com/facebook/docusaurus/pull/6531) fix(theme-classic): highlight active collapsible doc category properly ([@lex111](https://github.com/lex111)) - - [#6515](https://github.com/facebook/docusaurus/pull/6515) fix(theme-classic): add key prop for SimpleLinks map ([@kgajera](https://github.com/kgajera)) - - [#6508](https://github.com/facebook/docusaurus/pull/6508) fix(theme-classic): apply width/height for footer logos without href ([@kgajera](https://github.com/kgajera)) -- `docusaurus-utils` - - [#6617](https://github.com/facebook/docusaurus/pull/6617) fix(utils): convert Markdown links in reference-style links with multiple spaces ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6489](https://github.com/facebook/docusaurus/pull/6489) fix(utils): do not resolve Markdown paths with @site prefix ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6478](https://github.com/facebook/docusaurus/pull/6478) fix(utils): Markdown linkification match local paths beginning with http ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#6495](https://github.com/facebook/docusaurus/pull/6495) fix(content-docs): render category with no subitems as a normal link ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :nail_care: Polish - -- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#6755](https://github.com/facebook/docusaurus/pull/6755) refactor: unify error handling behavior ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus` - - [#6679](https://github.com/facebook/docusaurus/pull/6679) feat(create): better detection of package manager preference ([@lex111](https://github.com/lex111)) - - [#6481](https://github.com/facebook/docusaurus/pull/6481) refactor(init): promote good practices; use site alias ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs` - - [#6745](https://github.com/facebook/docusaurus/pull/6745) fix(content-docs): improve sidebar shorthand normalization error message ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6602](https://github.com/facebook/docusaurus/pull/6602) feat(content-docs): allow omitting enclosing array consistently for category shorthand ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6596](https://github.com/facebook/docusaurus/pull/6596) refactor(content-docs): clean up sidebars logic; validate generator returns ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6586](https://github.com/facebook/docusaurus/pull/6586) refactor(content-docs): read category metadata files before autogenerating ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus` - - [#6730](https://github.com/facebook/docusaurus/pull/6730) refactor: declare all props as interfaces ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-translations` - - [#6711](https://github.com/facebook/docusaurus/pull/6711) chore(theme-translations): complete Korean translations ([@revi](https://github.com/revi)) - - [#6686](https://github.com/facebook/docusaurus/pull/6686) fix(theme-translations): improve Korean translations ([@winterlood](https://github.com/winterlood)) - - [#6635](https://github.com/facebook/docusaurus/pull/6635) refactor(theme-translation): improve Traditional Chinese translation quality ([@toto6038](https://github.com/toto6038)) -- `docusaurus-theme-classic`, `docusaurus-theme-translations` - - [#6674](https://github.com/facebook/docusaurus/pull/6674) fix(theme-classic): improve aria label of color mode toggle ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-theme-classic` - - [#6668](https://github.com/facebook/docusaurus/pull/6668) refactor: recommend using data-theme without html element selector ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#6622](https://github.com/facebook/docusaurus/pull/6622) refactor(theme-classic): clean up CSS of doc sidebar item ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#6644](https://github.com/facebook/docusaurus/pull/6644) fix(core): forward ref to Link's anchor element ([@koistya](https://github.com/koistya)) - - [#6646](https://github.com/facebook/docusaurus/pull/6646) fix(cli): make docusaurus clear also remove .yarn/.cache folder ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6306](https://github.com/facebook/docusaurus/pull/6306) feat(core): use react-helmet-async ([@seyoon20087](https://github.com/seyoon20087)) -- `docusaurus-utils-validation` - - [#6656](https://github.com/facebook/docusaurus/pull/6656) feat: allow numbers in plugin ID ([@cdemonchy-pro](https://github.com/cdemonchy-pro)) -- `docusaurus-mdx-loader`, `docusaurus-utils`, `lqip-loader` - - [#6650](https://github.com/facebook/docusaurus/pull/6650) refactor(utils): replace hash with contenthash for file loader ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus-utils` - - [#6615](https://github.com/facebook/docusaurus/pull/6615) fix: remove more peer dependency warnings ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader` - - [#6598](https://github.com/facebook/docusaurus/pull/6598) feat: make Markdown images lazy loaded ([@johnnyreilly](https://github.com/johnnyreilly)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6505](https://github.com/facebook/docusaurus/pull/6505) fix(theme-classic): make focused link outlined with JS disabled ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` - - [#6507](https://github.com/facebook/docusaurus/pull/6507) refactor: improve internal typing ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus-utils` - - [#6498](https://github.com/facebook/docusaurus/pull/6498) fix: updating peerDependency fields for yarn berry ([@vidarc](https://github.com/vidarc)) -- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations` - - [#6482](https://github.com/facebook/docusaurus/pull/6482) feat: mark some text labels as translatable ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :memo: Documentation - -- Other - - [#6727](https://github.com/facebook/docusaurus/pull/6727) docs: add Blog Matheus Brunelli site to showcase ([@mrbrunelli](https://github.com/mrbrunelli)) - - [#6721](https://github.com/facebook/docusaurus/pull/6721) docs: add Butterfly Documentation to showcase ([@CodeDoctorDE](https://github.com/CodeDoctorDE)) - - [#6710](https://github.com/facebook/docusaurus/pull/6710) docs(website): Add techharvesting to showcase ([@NaseelNiyas](https://github.com/NaseelNiyas)) - - [#6708](https://github.com/facebook/docusaurus/pull/6708) docs: add doc for generated-index keyword/image metadata ([@slorber](https://github.com/slorber)) - - [#6709](https://github.com/facebook/docusaurus/pull/6709) docs(website): fix video responsiveness ([@lex111](https://github.com/lex111)) - - [#6687](https://github.com/facebook/docusaurus/pull/6687) docs: add deep dive video for Docusaurus ([@dmitryvinn](https://github.com/dmitryvinn)) - - [#6704](https://github.com/facebook/docusaurus/pull/6704) docs(website): search doc typo searchParameters ([@slorber](https://github.com/slorber)) - - [#6682](https://github.com/facebook/docusaurus/pull/6682) docs: add redux-cool site to showcase ([@Ruben-Arushanyan](https://github.com/Ruben-Arushanyan)) - - [#6677](https://github.com/facebook/docusaurus/pull/6677) docs: add Rivalis to showcase ([@kalevski](https://github.com/kalevski)) - - [#6676](https://github.com/facebook/docusaurus/pull/6676) docs: add SmartCookieWeb site to showcase ([@CookieJarApps](https://github.com/CookieJarApps)) - - [#6675](https://github.com/facebook/docusaurus/pull/6675) docs: mention that all official themes are TypeScript-covered ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6673](https://github.com/facebook/docusaurus/pull/6673) docs: mention about blog date in front matter ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6672](https://github.com/facebook/docusaurus/pull/6672) refactor(website): extract homepage data from UI; feature text updates ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6670](https://github.com/facebook/docusaurus/pull/6670) docs: add CyberDrain Improved Partner Portal (CIPP) to showcase ([@homotechsual](https://github.com/homotechsual)) - - [#6667](https://github.com/facebook/docusaurus/pull/6667) fix(website): make YT iframe responsive ([@lex111](https://github.com/lex111)) - - [#6659](https://github.com/facebook/docusaurus/pull/6659) docs: add eli5 video to home page ([@dmitryvinn-fb](https://github.com/dmitryvinn-fb)) - - [#6633](https://github.com/facebook/docusaurus/pull/6633) docs: improve wording of using Markdown file paths ([@BigDataWriter](https://github.com/BigDataWriter)) - - [#6624](https://github.com/facebook/docusaurus/pull/6624) docs: add Resoto & Some Engineering Inc. to showcase ([@TheCatLady](https://github.com/TheCatLady)) - - [#6611](https://github.com/facebook/docusaurus/pull/6611) docs: fix bad anchor link syntax ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6591](https://github.com/facebook/docusaurus/pull/6591) docs: improve GitHub Actions example jobs ([@ebarojas](https://github.com/ebarojas)) - - [#6426](https://github.com/facebook/docusaurus/pull/6426) feat(website): add Tweets section ([@yangshun](https://github.com/yangshun)) - - [#6532](https://github.com/facebook/docusaurus/pull/6532) docs: add SAP Cloud SDK to showcase ([@artemkovalyov](https://github.com/artemkovalyov)) - - [#6513](https://github.com/facebook/docusaurus/pull/6513) docs: clean up CONTRIBUTING ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6501](https://github.com/facebook/docusaurus/pull/6501) docs: add Cloudflare pages deployment guide ([@apidev234](https://github.com/apidev234)) - - [#6499](https://github.com/facebook/docusaurus/pull/6499) docs: mention how env vars can be read ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6492](https://github.com/facebook/docusaurus/pull/6492) docs: mention where to find the sitemap ([@tamalweb](https://github.com/tamalweb)) - - [#6491](https://github.com/facebook/docusaurus/pull/6491) docs: add developers.verida to showcase ([@nick-verida](https://github.com/nick-verida)) - - [#6414](https://github.com/facebook/docusaurus/pull/6414) feat(website): new plugin to load CHANGELOG and render as blog ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6404](https://github.com/facebook/docusaurus/pull/6404) docs: elaborate on Markdown asset linking; document pathname:// protocol ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6484](https://github.com/facebook/docusaurus/pull/6484) docs: remove mention that CDN resources are cached cross-domain ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6429](https://github.com/facebook/docusaurus/pull/6429) refactor: self-host KaTeX assets ([@pranabdas](https://github.com/pranabdas)) - - [#6483](https://github.com/facebook/docusaurus/pull/6483) docs: mark a lot of website texts as translatable ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-preset-classic` - - [#6627](https://github.com/facebook/docusaurus/pull/6627) docs: fix presets documentation link ([@thedanielhanke](https://github.com/thedanielhanke)) - -#### :house: Internal - -- `docusaurus-theme-classic` - - [#6759](https://github.com/facebook/docusaurus/pull/6759) refactor(theme-classic): merge CSS files for Heading ([@slorber](https://github.com/slorber)) - - [#6584](https://github.com/facebook/docusaurus/pull/6584) misc: enable jsx-key eslint rule ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate` - - [#6756](https://github.com/facebook/docusaurus/pull/6756) test: sort migration test FS mock calls ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6609](https://github.com/facebook/docusaurus/pull/6609) refactor(migrate): change internal methods' parameter style ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6476](https://github.com/facebook/docusaurus/pull/6476) chore: fix Stylelint globs for editor support ([@nschonni](https://github.com/nschonni)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#6744](https://github.com/facebook/docusaurus/pull/6744) fix(content-docs): properly display collocated social card image ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-types`, `docusaurus` - - [#6742](https://github.com/facebook/docusaurus/pull/6742) refactor: improve client modules types ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases` - - [#6741](https://github.com/facebook/docusaurus/pull/6741) chore(module-type-aliases): add react as peer dependency ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6658](https://github.com/facebook/docusaurus/pull/6658) refactor(module-aliases): remove react-helmet dependency ([@Josh-Cena](https://github.com/Josh-Cena)) -- Other - - [#6726](https://github.com/facebook/docusaurus/pull/6726) misc: improve bug report template ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6512](https://github.com/facebook/docusaurus/pull/6512) misc: configure linguist behavior to show better language stats ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6487](https://github.com/facebook/docusaurus/pull/6487) chore: fix codesandbox example link + mention npm publish recovery ([@slorber](https://github.com/slorber)) - - [#6486](https://github.com/facebook/docusaurus/pull/6486) chore: update examples for beta.15 ([@slorber](https://github.com/slorber)) - - [#6485](https://github.com/facebook/docusaurus/pull/6485) fix(website): bad translate tags without default translation ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#6716](https://github.com/facebook/docusaurus/pull/6716) refactor: ensure lodash is default-imported ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-logger`, `docusaurus-migrate`, `docusaurus` - - [#6661](https://github.com/facebook/docusaurus/pull/6661) refactor: convert CLI entry points to ESM; migrate create-docusaurus to ESM ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-common`, `docusaurus` - - [#6651](https://github.com/facebook/docusaurus/pull/6651) refactor: reduce exported members of docusaurus router ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#6629](https://github.com/facebook/docusaurus/pull/6629) refactor: move module declarations for non-route components to theme-classic ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-pwa`, `docusaurus-theme-classic` - - [#6614](https://github.com/facebook/docusaurus/pull/6614) refactor: remove Babel plugins that are included in preset-env ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#6605](https://github.com/facebook/docusaurus/pull/6605) chore: fix ESLint warnings, restrict export all syntax ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia` - - [#6583](https://github.com/facebook/docusaurus/pull/6583) refactor(live-codeblock): migrate theme to TS ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#6524](https://github.com/facebook/docusaurus/pull/6524) refactor: enforce named capture groups; clean up regexes ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate`, `docusaurus-plugin-content-docs`, `docusaurus` - - [#6521](https://github.com/facebook/docusaurus/pull/6521) refactor: mark all functions that import external modules as async ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-cssnano-preset`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` - - [#6514](https://github.com/facebook/docusaurus/pull/6514) chore: clean up ESLint config, enable a few rules ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-types`, `docusaurus` - - [#6511](https://github.com/facebook/docusaurus/pull/6511) refactor(core): convert theme-fallback to TS ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-utils` - - [#6506](https://github.com/facebook/docusaurus/pull/6506) test: add test for readOutputHTMLFile ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate`, `docusaurus-theme-common` - - [#6502](https://github.com/facebook/docusaurus/pull/6502) refactor: fix all eslint warnings ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus` - - [#6474](https://github.com/facebook/docusaurus/pull/6474) test: rename 'fixtures' to '**fixtures**' ([@nschonni](https://github.com/nschonni)) - -#### :running_woman: Performance - -- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus` - - [#6725](https://github.com/facebook/docusaurus/pull/6725) refactor: convert all fs methods to async ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### Committers: 38 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Artem Kovalov ([@artemkovalyov](https://github.com/artemkovalyov)) -- Balthasar Hofer ([@lebalz](https://github.com/lebalz)) -- Clement Demonchy ([@cdemonchy-pro](https://github.com/cdemonchy-pro)) -- CodeDoctor ([@CodeDoctorDE](https://github.com/CodeDoctorDE)) -- Daniel Hanke ([@thedanielhanke](https://github.com/thedanielhanke)) -- Daniel Kalevski ([@kalevski](https://github.com/kalevski)) -- Dmitry Vinnik ([@dmitryvinn](https://github.com/dmitryvinn)) -- Dmitry Vinnik | Meta ([@dmitryvinn-fb](https://github.com/dmitryvinn-fb)) -- Erick Zhao ([@erickzhao](https://github.com/erickzhao)) -- Everardo J. Barojas M. ([@ebarojas](https://github.com/ebarojas)) -- Felipe Santos ([@felipecrs](https://github.com/felipecrs)) -- Gaurish ([@apidev234](https://github.com/apidev234)) -- Hong Yongmin ([@revi](https://github.com/revi)) -- Jody Heavener ([@jodyheavener](https://github.com/jodyheavener)) -- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Kishan Gajera ([@kgajera](https://github.com/kgajera)) -- Konstantin Tarkus ([@koistya](https://github.com/koistya)) -- Matheus Ricardo Brunelli ([@mrbrunelli](https://github.com/mrbrunelli)) -- Matthew Ailes ([@vidarc](https://github.com/vidarc)) -- Mikey O'Toole ([@homotechsual](https://github.com/homotechsual)) -- Miles Johnson ([@milesj](https://github.com/milesj)) -- Muhammad Redho Ayassa ([@redhoyasa](https://github.com/redhoyasa)) -- Naseel Niyas ([@NaseelNiyas](https://github.com/NaseelNiyas)) -- Nick Schonning ([@nschonni](https://github.com/nschonni)) -- Pranab Das ([@pranabdas](https://github.com/pranabdas)) -- Ruben Arushanyan ([@Ruben-Arushanyan](https://github.com/Ruben-Arushanyan)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tamal Web ([@tamalweb](https://github.com/tamalweb)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) -- [@BigDataWriter](https://github.com/BigDataWriter) -- [@CookieJarApps](https://github.com/CookieJarApps) -- [@TheCatLady](https://github.com/TheCatLady) -- [@nick-verida](https://github.com/nick-verida) -- [@seyoon20087](https://github.com/seyoon20087) -- [@toto6038](https://github.com/toto6038) -- 이정환 ([@winterlood](https://github.com/winterlood)) - -## 2.0.0-beta.15 (2022-01-26) - -#### :rocket: New Feature - -- `docusaurus-plugin-content-docs` - - [#6451](https://github.com/facebook/docusaurus/pull/6451) feat(content-docs): expose isCategoryIndex matcher to customize conventions ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5782](https://github.com/facebook/docusaurus/pull/5782) feat(content-docs): displayed_sidebar front matter ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6466](https://github.com/facebook/docusaurus/pull/6466) feat(theme-classic): add stable class for DocSidebarContainer ([@homotechsual](https://github.com/homotechsual)) - - [#3811](https://github.com/facebook/docusaurus/pull/3811) feat(theme-classic): auto-collapse sibling categories in doc sidebar ([@josephriosIO](https://github.com/josephriosIO)) - - [#6216](https://github.com/facebook/docusaurus/pull/6216) feat(theme-classic): usable CodeBlock outside markdown ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` - - [#6416](https://github.com/facebook/docusaurus/pull/6416) feat(content-blog): allow authors list to contain images only ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog` - - [#6415](https://github.com/facebook/docusaurus/pull/6415) feat(content-blog): allow disabling generating archive ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6245](https://github.com/facebook/docusaurus/pull/6245) feat(content-blog): parse date from middle of file path ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6388](https://github.com/facebook/docusaurus/pull/6388) feat(content-blog): include tags in feed ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#6371](https://github.com/facebook/docusaurus/pull/6371) feat(core, theme-classic): allow overriding htmlLang ([@noomorph](https://github.com/noomorph)) -- `docusaurus-mdx-loader` - - [#6323](https://github.com/facebook/docusaurus/pull/6323) feat(mdx-loader): preserve hash in image src; support GH themed images ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#6139](https://github.com/facebook/docusaurus/pull/6139) feat(theme-classic): new navbar item linking to a sidebar ([@lmpham1](https://github.com/lmpham1)) - - [#6239](https://github.com/facebook/docusaurus/pull/6239) feat(content-docs): allow SEO metadata for category index pages ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-sitemap` - - [#6248](https://github.com/facebook/docusaurus/pull/6248) feat(sitemap): remove trailingSlash option; respect noIndex config ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-ideal-image`, `docusaurus-theme-translations` - - [#6173](https://github.com/facebook/docusaurus/pull/6173) feat(ideal-image): allow translating status messages ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-ideal-image` - - [#6155](https://github.com/facebook/docusaurus/pull/6155) feat(ideal-image): new option disableInDev ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-translations` - - [#6169](https://github.com/facebook/docusaurus/pull/6169) feat(theme-translations): add Italian translations ([@mcallisto](https://github.com/mcallisto)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-types`, `docusaurus` - - [#6166](https://github.com/facebook/docusaurus/pull/6166) feat: async plugin creator functions ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#6165](https://github.com/facebook/docusaurus/pull/6165) feat(core): async docusaurus.config.js creator function ([@slorber](https://github.com/slorber)) - -#### :boom: Breaking Change - -- `docusaurus-theme-search-algolia` - - [#6407](https://github.com/facebook/docusaurus/pull/6407) feat(search): enable contextual search by default ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia` - - [#6289](https://github.com/facebook/docusaurus/pull/6289) refactor: move @theme/hooks to @docusaurus/theme-common ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#6283](https://github.com/facebook/docusaurus/pull/6283) refactor(theme-classic): apply import/no-named-export eslint rule ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-sitemap` - - [#6248](https://github.com/facebook/docusaurus/pull/6248) feat(sitemap): remove trailingSlash option; respect noIndex config ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :bug: Bug Fix - -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus` - - [#6454](https://github.com/facebook/docusaurus/pull/6454) fix(content-blog): generate feed by reading build output ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus` - - [#6468](https://github.com/facebook/docusaurus/pull/6468) fix(init): cd to correct path when installing ([@gabrielcsapo](https://github.com/gabrielcsapo)) -- `docusaurus-mdx-loader` - - [#4827](https://github.com/facebook/docusaurus/pull/4827) fix: allow links to JSON in .md files to be transformed as asset links ([@antmcc49](https://github.com/antmcc49)) -- `docusaurus-plugin-content-docs` - - [#6435](https://github.com/facebook/docusaurus/pull/6435) fix(content-docs): make getActivePlugin match plugin paths more exactly ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6310](https://github.com/facebook/docusaurus/pull/6310) fix: highlight appropriate navItem when browsing generated category index ([@tapanchudasama](https://github.com/tapanchudasama)) - - [#6202](https://github.com/facebook/docusaurus/pull/6202) fix(content-docs): quotify path when retrieving git history ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#6424](https://github.com/facebook/docusaurus/pull/6424) fix(core): fix css url("image.png"), use css-loader v6 with esModules: false ([@slorber](https://github.com/slorber)) - - [#6378](https://github.com/facebook/docusaurus/pull/6378) fix(core): do not coerce webpack warning to string ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6197](https://github.com/facebook/docusaurus/pull/6197) fix(cli): quotify temp path in deploy command ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6168](https://github.com/facebook/docusaurus/pull/6168) fix(core): update webpack-dev-server + fix deprecation warning ([@slorber](https://github.com/slorber)) -- `docusaurus-logger`, `docusaurus-utils` - - [#6384](https://github.com/facebook/docusaurus/pull/6384) fix(logger): properly stringify objects for logging ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus` - - [#6338](https://github.com/facebook/docusaurus/pull/6338) fix(core): error boundary should allow no children ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#6314](https://github.com/facebook/docusaurus/pull/6314) fix(theme-classic): fix mobile version dropdown label with only one version ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6288](https://github.com/facebook/docusaurus/pull/6288) fix(theme-classic): add missing role=region to SkipToContent ([@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)) - - [#6213](https://github.com/facebook/docusaurus/pull/6213) refactor(theme-classic): extract common PaginatorNavLink component ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6177](https://github.com/facebook/docusaurus/pull/6177) fix(theme-classic): make React elements in pre render correctly ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#6300](https://github.com/facebook/docusaurus/pull/6300) refactor: move exported type definitions to declaration file ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate` - - [#6276](https://github.com/facebook/docusaurus/pull/6276) fix(migrate): migration CLI should correctly migrate gtag options ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog` - - [#6244](https://github.com/facebook/docusaurus/pull/6244) fix(content-blog): always convert front matter date as UTC ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-utils`, `docusaurus` - - [#6190](https://github.com/facebook/docusaurus/pull/6190) fix(utils): properly escape Windows paths ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :nail_care: Polish - -- `docusaurus-module-type-aliases` - - [#6469](https://github.com/facebook/docusaurus/pull/6469) fix(module-type-aliases): fix type def for translate params ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-search-algolia` - - [#6407](https://github.com/facebook/docusaurus/pull/6407) feat(search): enable contextual search by default ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader` - - [#6443](https://github.com/facebook/docusaurus/pull/6443) refactor(mdx-loader): use vfile.path to access Markdown file path ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#6427](https://github.com/facebook/docusaurus/pull/6427) feat(theme-classic): add aria-current to sidebar category link ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6391](https://github.com/facebook/docusaurus/pull/6391) refactor(theme-classic): add comments to Prism setup; minor refactor ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6240](https://github.com/facebook/docusaurus/pull/6240) refactor(theme-classic): use front matter from metadata for BlogPostPage ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#6419](https://github.com/facebook/docusaurus/pull/6419) feat(core): warn users about hand-modifying generated files ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6405](https://github.com/facebook/docusaurus/pull/6405) feat(core): check imported API name when extracting translations ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6291](https://github.com/facebook/docusaurus/pull/6291) feat(core): improve error message for BrowserOnly; better docs ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus` - - [#5822](https://github.com/facebook/docusaurus/pull/5822) feat: update website & init template palette to pass WCAG test; include contrast check in ColorGenerator ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6368](https://github.com/facebook/docusaurus/pull/6368) fix(create-docusaurus): add useBaseUrl for image URLs ([@alias-mac](https://github.com/alias-mac)) -- `docusaurus-plugin-content-pages`, `docusaurus-theme-classic` - - [#6400](https://github.com/facebook/docusaurus/pull/6400) feat(content-pages): front matter validation, include front matter in metadata ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-theme-classic` - - [#6339](https://github.com/facebook/docusaurus/pull/6339) feat(mdx-loader): read image dimensions when processing Markdown ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog` - - [#6388](https://github.com/facebook/docusaurus/pull/6388) feat(content-blog): include tags in feed ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6189](https://github.com/facebook/docusaurus/pull/6189) feat(content-blog): include front matter in loaded content metadata ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-common` - - [#6317](https://github.com/facebook/docusaurus/pull/6317) feat(theme-classic): autoscroll TOC with active link ([@cerkiewny](https://github.com/cerkiewny)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#6303](https://github.com/facebook/docusaurus/pull/6303) test(utils, mdx-loader, core): improve coverage ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-preset-classic` - - [#6284](https://github.com/facebook/docusaurus/pull/6284) fix(preset-classic): throw if preset finds GA options in theme config ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus` - - [#6186](https://github.com/facebook/docusaurus/pull/6186) refactor: print trailing new line when outputting JSON ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :memo: Documentation - -- Other - - [#6296](https://github.com/facebook/docusaurus/pull/6296) docs: add advanced guides ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6459](https://github.com/facebook/docusaurus/pull/6459) docs: add replicad to showcase ([@sgenoud](https://github.com/sgenoud)) - - [#6334](https://github.com/facebook/docusaurus/pull/6334) docs: 2021 recap blog post ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6458](https://github.com/facebook/docusaurus/pull/6458) docs: add Kuizuo's Personal Website to showcase ([@kuizuo](https://github.com/kuizuo)) - - [#6431](https://github.com/facebook/docusaurus/pull/6431) docs: add Koyeb as a deployment option ([@edouardb](https://github.com/edouardb)) - - [#6455](https://github.com/facebook/docusaurus/pull/6455) docs: add Sass Fairy to showcase ([@roydukkey](https://github.com/roydukkey)) - - [#6453](https://github.com/facebook/docusaurus/pull/6453) docs: document embedding generated index in doc page ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6450](https://github.com/facebook/docusaurus/pull/6450) docs: split sidebar documentation into sections ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6449](https://github.com/facebook/docusaurus/pull/6449) docs: multiple doc improvements ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6448](https://github.com/facebook/docusaurus/pull/6448) fix(website): update colors correctly when palette is only customized in one color mode ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6385](https://github.com/facebook/docusaurus/pull/6385) chore: add height/width for front page images ([@nschonni](https://github.com/nschonni)) - - [#6445](https://github.com/facebook/docusaurus/pull/6445) docs: update showcase data of InfraQL ([@jeffreyaven](https://github.com/jeffreyaven)) - - [#6433](https://github.com/facebook/docusaurus/pull/6433) docs: add kube-green to showcase ([@davidebianchi](https://github.com/davidebianchi)) - - [#6428](https://github.com/facebook/docusaurus/pull/6428) docs: elaborate on i18n tutorial ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6422](https://github.com/facebook/docusaurus/pull/6422) docs: add 404Lab wiki to showcase ([@HiChen404](https://github.com/HiChen404)) - - [#6420](https://github.com/facebook/docusaurus/pull/6420) fix(website): restore some site CSS in light mode ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6410](https://github.com/facebook/docusaurus/pull/6410) docs: add SODA for SPARC to showcase ([@megasanjay](https://github.com/megasanjay)) - - [#6417](https://github.com/facebook/docusaurus/pull/6417) docs: fix accessibility of search modal ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6406](https://github.com/facebook/docusaurus/pull/6406) docs(i18n): add docs for htmlLang config ([@noomorph](https://github.com/noomorph)) - - [#6393](https://github.com/facebook/docusaurus/pull/6393) docs: update Algolia docs for new DocSearch infra ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6383](https://github.com/facebook/docusaurus/pull/6383) docs: elaborate on different CSS class names ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6348](https://github.com/facebook/docusaurus/pull/6348) docs: add KaustubhK24's site to showcase ([@kaustubhk24](https://github.com/kaustubhk24)) - - [#6333](https://github.com/facebook/docusaurus/pull/6333) feat(website): search in showcase ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6344](https://github.com/facebook/docusaurus/pull/6344) fix(website): make ColorGenerator functional ([@shwaka](https://github.com/shwaka)) - - [#6340](https://github.com/facebook/docusaurus/pull/6340) docs: minor fix in the sample config for ESM ([@pranabdas](https://github.com/pranabdas)) - - [#6336](https://github.com/facebook/docusaurus/pull/6336) docs: make upgrade guide always show the latest version ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6320](https://github.com/facebook/docusaurus/pull/6320) chore: upgrade rehype-katex with ESM support, update docs ([@pranabdas](https://github.com/pranabdas)) - - [#6335](https://github.com/facebook/docusaurus/pull/6335) docs: add Pglet website to showcase ([@FeodorFitsner](https://github.com/FeodorFitsner)) - - [#6327](https://github.com/facebook/docusaurus/pull/6327) docs: remove typo bracket ([@MorookaKotaro](https://github.com/MorookaKotaro)) - - [#6316](https://github.com/facebook/docusaurus/pull/6316) docs: add bandwidth.com to showcase ([@ajrice6713](https://github.com/ajrice6713)) - - [#6313](https://github.com/facebook/docusaurus/pull/6313) docs: add Refine site to showcase ([@omeraplak](https://github.com/omeraplak)) - - [#6318](https://github.com/facebook/docusaurus/pull/6318) fix(website): various anchor link fixes ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6308](https://github.com/facebook/docusaurus/pull/6308) fix(website): wrap details in mdx-code-block ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6307](https://github.com/facebook/docusaurus/pull/6307) docs: document MD and JSX interoperability issues ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6299](https://github.com/facebook/docusaurus/pull/6299) docs: add icodex to showcase ([@wood3n](https://github.com/wood3n)) - - [#6297](https://github.com/facebook/docusaurus/pull/6297) docs: mention setup in monorepo ([@PatelN123](https://github.com/PatelN123)) - - [#6293](https://github.com/facebook/docusaurus/pull/6293) docs: remove GraphQL mesh from showcase ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6231](https://github.com/facebook/docusaurus/pull/6231) docs: update showcase images; remove GraphQL Code Generator site ([@PatelN123](https://github.com/PatelN123)) - - [#6285](https://github.com/facebook/docusaurus/pull/6285) refactor(website): further optimize showcase images ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6281](https://github.com/facebook/docusaurus/pull/6281) docs: Add kwatch to showcase ([@abahmed](https://github.com/abahmed)) - - [#6280](https://github.com/facebook/docusaurus/pull/6280) docs: elaborate on doc versioning ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6043](https://github.com/facebook/docusaurus/pull/6043) fix(website): resize showcase images, tighten CI check ([@armano2](https://github.com/armano2)) - - [#6274](https://github.com/facebook/docusaurus/pull/6274) docs: add dyte docs to showcase ([@vaibhavshn](https://github.com/vaibhavshn)) - - [#6278](https://github.com/facebook/docusaurus/pull/6278) docs: add Khyron Realm to showcase ([@alexgrigoras](https://github.com/alexgrigoras)) - - [#6271](https://github.com/facebook/docusaurus/pull/6271) docs: add FlatifyCSS to showcase ([@amir2mi](https://github.com/amir2mi)) - - [#6275](https://github.com/facebook/docusaurus/pull/6275) fix(website): fix config-tabs breaking after translation ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6269](https://github.com/facebook/docusaurus/pull/6269) docs: add Ionic to showcase ([@ltm](https://github.com/ltm)) - - [#6272](https://github.com/facebook/docusaurus/pull/6272) docs: make tsconfig work OOTB in typescript guide ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6265](https://github.com/facebook/docusaurus/pull/6265) docs: add Eric JiuRan's blog to showcase ([@1084350607](https://github.com/1084350607)) - - [#6242](https://github.com/facebook/docusaurus/pull/6242) docs(showcase): update oxidizer website url ([@vandreleal](https://github.com/vandreleal)) - - [#6226](https://github.com/facebook/docusaurus/pull/6226) docs: update showcase data for digital support notes ([@PatelN123](https://github.com/PatelN123)) - - [#6224](https://github.com/facebook/docusaurus/pull/6224) docs: add TalentBrick to showcase ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6223](https://github.com/facebook/docusaurus/pull/6223) docs: normalize CodeBlock highlighting ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6214](https://github.com/facebook/docusaurus/pull/6214) feat(website): improve prism themes ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6215](https://github.com/facebook/docusaurus/pull/6215) docs: use BrowserWindow for Markdown demos ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6193](https://github.com/facebook/docusaurus/pull/6193) docs: normalize plugin API documentation ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6209](https://github.com/facebook/docusaurus/pull/6209) docs: elaborate on static asset resolution ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6207](https://github.com/facebook/docusaurus/pull/6207) docs: add default value for BrowserWindow URL field ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6206](https://github.com/facebook/docusaurus/pull/6206) docs: fix highlighting of YAML front matter ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6191](https://github.com/facebook/docusaurus/pull/6191) docs: fix react live scope button color in dark mode ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6188](https://github.com/facebook/docusaurus/pull/6188) docs: add Layer0 to deployment guide ([@rishi-raj-jain](https://github.com/rishi-raj-jain)) - - [#6184](https://github.com/facebook/docusaurus/pull/6184) docs: remove mention of 'UA-' in gtag ([@johnnyreilly](https://github.com/johnnyreilly)) - - [#6181](https://github.com/facebook/docusaurus/pull/6181) docs: add GTFS-to-HTML to showcase ([@brendannee](https://github.com/brendannee)) - - [#6178](https://github.com/facebook/docusaurus/pull/6178) docs: add Digital Support Notes to showcase ([@PatelN123](https://github.com/PatelN123)) - - [#6170](https://github.com/facebook/docusaurus/pull/6170) docs: add LabVIEW coding experience to showcase ([@ruanqizhen](https://github.com/ruanqizhen)) - - [#6164](https://github.com/facebook/docusaurus/pull/6164) docs: fix import module name of theme/Admonition ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6158](https://github.com/facebook/docusaurus/pull/6158) docs: add Astronomer to showcase ([@jwitz](https://github.com/jwitz)) -- `create-docusaurus` - - [#5822](https://github.com/facebook/docusaurus/pull/5822) feat: update website & init template palette to pass WCAG test; include contrast check in ColorGenerator ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6187](https://github.com/facebook/docusaurus/pull/6187) docs: make installation guide more beginner-friendly ([@PatelN123](https://github.com/PatelN123)) -- `docusaurus-utils` - - [#6204](https://github.com/facebook/docusaurus/pull/6204) docs: recommend highlighting with comments than number range ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-theme-classic` - - [#6203](https://github.com/facebook/docusaurus/pull/6203) docs: audit grammar issues ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :house: Internal - -- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#6456](https://github.com/facebook/docusaurus/pull/6456) chore: add cSpell for spell checking ([@nschonni](https://github.com/nschonni)) -- Other - - [#6444](https://github.com/facebook/docusaurus/pull/6444) misc: update nvmrc to 14.17.0 to meet dependency requirements ([@jodyheavener](https://github.com/jodyheavener)) - - [#6441](https://github.com/facebook/docusaurus/pull/6441) misc: fix stylelint erroring when lint-staged passed ignored file ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6421](https://github.com/facebook/docusaurus/pull/6421) chore: fix yarn build:website:fast ([@slorber](https://github.com/slorber)) - - [#6381](https://github.com/facebook/docusaurus/pull/6381) chore(website): set cache-control for static assets ([@nschonni](https://github.com/nschonni)) - - [#6364](https://github.com/facebook/docusaurus/pull/6364) chore: remove Intl polyfills for Jest ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6325](https://github.com/facebook/docusaurus/pull/6325) chore: add Dependabot for dependency updates ([@nschonni](https://github.com/nschonni)) - - [#6328](https://github.com/facebook/docusaurus/pull/6328) chore(ci): upgrade actions/github-script to v5 ([@nschonni](https://github.com/nschonni)) - - [#6332](https://github.com/facebook/docusaurus/pull/6332) chore(deps): bump follow-redirects from 1.14.5 to 1.14.7 ([@dependabot[bot]](https://github.com/apps/dependabot)) - - [#6326](https://github.com/facebook/docusaurus/pull/6326) misc(ci): remove redundant "CI: true" env ([@nschonni](https://github.com/nschonni)) - - [#6304](https://github.com/facebook/docusaurus/pull/6304) chore: upgrade to Husky 7 ([@nschonni](https://github.com/nschonni)) - - [#6222](https://github.com/facebook/docusaurus/pull/6222) test: ensure consistent CSS ordering ([@slorber](https://github.com/slorber)) - - [#6159](https://github.com/facebook/docusaurus/pull/6159) docs: remove useless comment ([@slorber](https://github.com/slorber)) - - [#6148](https://github.com/facebook/docusaurus/pull/6148) chore(examples): update examples to 2.0.0-beta.14 ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-debug`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#6442](https://github.com/facebook/docusaurus/pull/6442) chore: enable stylelint standard config ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus` - - [#6440](https://github.com/facebook/docusaurus/pull/6440) chore: remove some unused dependencies from package.json ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#6436](https://github.com/facebook/docusaurus/pull/6436) refactor(theme-classic): render BlogPostItem as one JSX element ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6283](https://github.com/facebook/docusaurus/pull/6283) refactor(theme-classic): apply import/no-named-export eslint rule ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-pages` - - [#6413](https://github.com/facebook/docusaurus/pull/6413) fix(content-pages): declare hide_table_of_contents as boolean ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus` - - [#6399](https://github.com/facebook/docusaurus/pull/6399) refactor: clean up TODO comments ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-cssnano-preset`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-theme-translations`, `docusaurus` - - [#6387](https://github.com/facebook/docusaurus/pull/6387) test: improve test coverage ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-utils` - - [#6380](https://github.com/facebook/docusaurus/pull/6380) chore: enable a few fixable ESLint rules ([@nschonni](https://github.com/nschonni)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-docs`, `docusaurus-utils`, `docusaurus` - - [#6377](https://github.com/facebook/docusaurus/pull/6377) refactor: use findAsyncSequential in a few places ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` - - [#6375](https://github.com/facebook/docusaurus/pull/6375) chore: enable eslint-plugin-jest ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus` - - [#6373](https://github.com/facebook/docusaurus/pull/6373) chore: enable react/jsx-closing-bracket-location ([@nschonni](https://github.com/nschonni)) -- `docusaurus-theme-classic`, `stylelint-copyright` - - [#6374](https://github.com/facebook/docusaurus/pull/6374) feat(stylelint-copyright): autofix, stricter config ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-cssnano-preset`, `docusaurus-theme-classic` - - [#6372](https://github.com/facebook/docusaurus/pull/6372) chore: add baseline stylelint rules ([@nschonni](https://github.com/nschonni)) -- `create-docusaurus`, `docusaurus-plugin-debug`, `docusaurus-theme-classic` - - [#6369](https://github.com/facebook/docusaurus/pull/6369) chore: upgrade lint-staged and globs ([@nschonni](https://github.com/nschonni)) -- `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus` - - [#6341](https://github.com/facebook/docusaurus/pull/6341) chore: regenerate yarn.lock ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-pages`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus` - - [#6324](https://github.com/facebook/docusaurus/pull/6324) chore: minor typo cleanup ([@nschonni](https://github.com/nschonni)) -- `create-docusaurus`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` - - [#6286](https://github.com/facebook/docusaurus/pull/6286) misc: convert all internal scripts to ESM ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia` - - [#6289](https://github.com/facebook/docusaurus/pull/6289) refactor: move @theme/hooks to @docusaurus/theme-common ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia` - - [#6287](https://github.com/facebook/docusaurus/pull/6287) refactor: new @docusaurus/plugin-content-docs/client interface ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#6279](https://github.com/facebook/docusaurus/pull/6279) refactor(core): use native types from webpack-dev-server ([@RDIL](https://github.com/RDIL)) -- `docusaurus-plugin-content-docs` - - [#6277](https://github.com/facebook/docusaurus/pull/6277) refactor(content-docs): make readVersionsMetadata async ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-types`, `docusaurus` - - [#6237](https://github.com/facebook/docusaurus/pull/6237) refactor(core): convert serverEntry.js to TS ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#6230](https://github.com/facebook/docusaurus/pull/6230) refactor: enforce type import specifiers ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-plugin-content-blog`, `docusaurus-utils`, `docusaurus` - - [#6229](https://github.com/facebook/docusaurus/pull/6229) refactor(utils): reorganize functions; move authors file resolution to utils ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-translations` - - [#6225](https://github.com/facebook/docusaurus/pull/6225) refactor(theme-translations): improve typing for update script ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6174](https://github.com/facebook/docusaurus/pull/6174) misc(theme-translations): multiple improvements to the update CLI ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### Committers: 46 - -- AJ Rice ([@ajrice6713](https://github.com/ajrice6713)) -- Abdelrahman Ahmed ([@abahmed](https://github.com/abahmed)) -- Alexandru Grigoras ([@alexgrigoras](https://github.com/alexgrigoras)) -- Amir M. Mohamadi ([@amir2mi](https://github.com/amir2mi)) -- Anthony McCaigue ([@antmcc49](https://github.com/antmcc49)) -- Armano ([@armano2](https://github.com/armano2)) -- Brendan Nee ([@brendannee](https://github.com/brendannee)) -- Chen ([@HiChen404](https://github.com/HiChen404)) -- Davide Bianchi ([@davidebianchi](https://github.com/davidebianchi)) -- Devtato ([@cerkiewny](https://github.com/cerkiewny)) -- Edouard Bonlieu ([@edouardb](https://github.com/edouardb)) -- Feodor Fitsner ([@FeodorFitsner](https://github.com/FeodorFitsner)) -- Filipe Guerra ([@alias-mac](https://github.com/alias-mac)) -- Gabriel Csapo ([@gabrielcsapo](https://github.com/gabrielcsapo)) -- Jake Witz ([@jwitz](https://github.com/jwitz)) -- Jeffrey Aven ([@jeffreyaven](https://github.com/jeffreyaven)) -- Jody Heavener ([@jodyheavener](https://github.com/jodyheavener)) -- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) -- Joseph ([@josephriosIO](https://github.com/josephriosIO)) -- Josh Goldberg ([@JoshuaKGoldberg](https://github.com/JoshuaKGoldberg)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Kaustubh Kulkarni ([@kaustubhk24](https://github.com/kaustubhk24)) -- Lars Mikkelsen ([@ltm](https://github.com/ltm)) -- Mikey O'Toole ([@homotechsual](https://github.com/homotechsual)) -- Minh Pham ([@lmpham1](https://github.com/lmpham1)) -- Morooka Kotaro ([@MorookaKotaro](https://github.com/MorookaKotaro)) -- Nayan Patel ([@PatelN123](https://github.com/PatelN123)) -- Nick Schonning ([@nschonni](https://github.com/nschonni)) -- Pranab Das ([@pranabdas](https://github.com/pranabdas)) -- Reece Dunham ([@RDIL](https://github.com/RDIL)) -- Rishi Raj Jain ([@rishi-raj-jain](https://github.com/rishi-raj-jain)) -- Sanjay Soundarajan ([@megasanjay](https://github.com/megasanjay)) -- Shun Wakatsuki ([@shwaka](https://github.com/shwaka)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tapan Chudasama ([@tapanchudasama](https://github.com/tapanchudasama)) -- Vaibhav Shinde ([@vaibhavshn](https://github.com/vaibhavshn)) -- Vandré Leal ([@vandreleal](https://github.com/vandreleal)) -- Yaroslav Serhieiev ([@noomorph](https://github.com/noomorph)) -- [@mcallisto](https://github.com/mcallisto) -- [@ruanqizhen](https://github.com/ruanqizhen) -- [@wood3n](https://github.com/wood3n) -- kuizuo ([@kuizuo](https://github.com/kuizuo)) -- sgenoud ([@sgenoud](https://github.com/sgenoud)) -- trent ([@roydukkey](https://github.com/roydukkey)) -- Ömer Faruk APLAK ([@omeraplak](https://github.com/omeraplak)) -- 久染 | JiuRan ([@1084350607](https://github.com/1084350607)) - -## 2.0.0-beta.14 (2021-12-21) - -#### :rocket: New Feature - -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6132](https://github.com/facebook/docusaurus/pull/6132) feat(theme-classic): new configuration syntax for a simple footer ([@christopherklint97](https://github.com/christopherklint97)) - - [#6125](https://github.com/facebook/docusaurus/pull/6125) feat(theme-common): stable classname for code blocks ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#5848](https://github.com/facebook/docusaurus/pull/5848) feat(theme-classic): standalone Admonition component ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6082](https://github.com/facebook/docusaurus/pull/6082) feat(theme-classic): allow passing additional attributes to tab headings ([@Drylozu](https://github.com/Drylozu)) -- `docusaurus-plugin-content-blog` - - [#6126](https://github.com/facebook/docusaurus/pull/6126) feat(content-blog): support json feed ([@notzheng](https://github.com/notzheng)) -- `docusaurus` - - [#6107](https://github.com/facebook/docusaurus/pull/6107) feat(core): allow plugins to customize/override Webpack devServer config ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus-migrate` - - [#6146](https://github.com/facebook/docusaurus/pull/6146) fix(migrate): do not modify non-MD files ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#6128](https://github.com/facebook/docusaurus/pull/6128) fix: do not use aria-hidden in heading anchor links ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs` - - [#6124](https://github.com/facebook/docusaurus/pull/6124) fix(content-docs): restore behavior when pagination front matter is null ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6085](https://github.com/facebook/docusaurus/pull/6085) fix(content-docs): getMainDocId should return doc with both versioned or unversioned id ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-utils-validation` - - [#6097](https://github.com/facebook/docusaurus/pull/6097) fix: declare missing dependencies ([@merceyz](https://github.com/merceyz)) -- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-pwa`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `lqip-loader` - - [#6094](https://github.com/facebook/docusaurus/pull/6094) fix: add missing dependencies on tslib ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-translations` - - [#6088](https://github.com/facebook/docusaurus/pull/6088) fix(theme-translations): publish theme-translation lib, including typedef ([@slorber](https://github.com/slorber)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#6053](https://github.com/facebook/docusaurus/pull/6053) feat(theme-classic): allow stylizing doc paginator arrows ([@noomorph](https://github.com/noomorph)) - - [#6121](https://github.com/facebook/docusaurus/pull/6121) fix(theme-classic): add outline to focused code blocks ([@christopherklint97](https://github.com/christopherklint97)) - - [#6118](https://github.com/facebook/docusaurus/pull/6118) refactor: remove some useless code ([@lex111](https://github.com/lex111)) -- `create-docusaurus`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#5994](https://github.com/facebook/docusaurus/pull/5994) refactor: unify log format with new logger utility ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus` - - [#6119](https://github.com/facebook/docusaurus/pull/6119) fix(create-docusaurus): make initial editUrl functional ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6095](https://github.com/facebook/docusaurus/pull/6095) fix(create-docusaurus): give a clearer message when installation failed ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :memo: Documentation - -- [#6142](https://github.com/facebook/docusaurus/pull/6142) docs: normalize usage of placeholders ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#5918](https://github.com/facebook/docusaurus/pull/5918) docs: refactor & refine lifecycle API docs ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#6138](https://github.com/facebook/docusaurus/pull/6138) docs: add Smart Docs to showcase ([@wowtvds](https://github.com/wowtvds)) -- [#6137](https://github.com/facebook/docusaurus/pull/6137) docs: add ToolJet to showcase ([@withshubh](https://github.com/withshubh)) -- [#6141](https://github.com/facebook/docusaurus/pull/6141) docs: add WoodpeckerCI to showcase ([@6543](https://github.com/6543)) -- [#6135](https://github.com/facebook/docusaurus/pull/6135) docs: mention admonition quirks with Prettier ([@yangshun](https://github.com/yangshun)) -- [#6131](https://github.com/facebook/docusaurus/pull/6131) docs: elaborate on "docs-only" and "blog-only" ([@himanshu007-creator](https://github.com/himanshu007-creator)) -- [#6134](https://github.com/facebook/docusaurus/pull/6134) docs: update link to init template README.md ([@cmpadden](https://github.com/cmpadden)) -- [#6130](https://github.com/facebook/docusaurus/pull/6130) docs: refactor docs sidebar doc ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#6129](https://github.com/facebook/docusaurus/pull/6129) docs: refactor styling/theming docs ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#6112](https://github.com/facebook/docusaurus/pull/6112) docs: mention that SEO through front matter is better than head tag ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#6120](https://github.com/facebook/docusaurus/pull/6120) refactor(website): make deploy preview open next version docs by default ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#6111](https://github.com/facebook/docusaurus/pull/6111) docs: add Molecule website to showcase ([@wewoor](https://github.com/wewoor)) -- [#6089](https://github.com/facebook/docusaurus/pull/6089) docs: add Enarx website to showcase ([@HarshCasper](https://github.com/HarshCasper)) -- [#6090](https://github.com/facebook/docusaurus/pull/6090) docs: add sapphire to showcase ([@favna](https://github.com/favna)) -- [#6091](https://github.com/facebook/docusaurus/pull/6091) docs(showcase): "much more pages" => "many more pages" ([@favna](https://github.com/favna)) - -#### :house: Internal - -- `docusaurus-theme-classic` - - [#6144](https://github.com/facebook/docusaurus/pull/6144) fix(theme-classic): fix translation when footer has no links ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs` - - [#6143](https://github.com/facebook/docusaurus/pull/6143) test: fix async tests resolved in random order ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6123](https://github.com/facebook/docusaurus/pull/6123) test: use snapshots for sidebar tests ([@Josh-Cena](https://github.com/Josh-Cena)) -- Other - - [#6122](https://github.com/facebook/docusaurus/pull/6122) fix(website): fix yarn build:website:fast ([@slorber](https://github.com/slorber)) - - [#6080](https://github.com/facebook/docusaurus/pull/6080) chore: add npm and pnpm to E2E tests ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-cssnano-preset`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#6092](https://github.com/facebook/docusaurus/pull/6092) misc: ignore some files during npm publish ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### Committers: 17 - -- 6543 ([@6543](https://github.com/6543)) -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Christopher Klint ([@christopherklint97](https://github.com/christopherklint97)) -- Harsh Mishra ([@HarshCasper](https://github.com/HarshCasper)) -- Himanshu ([@himanshu007-creator](https://github.com/himanshu007-creator)) -- Jeroen Claassens ([@favna](https://github.com/favna)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Kristoffer K. ([@merceyz](https://github.com/merceyz)) -- Shubhendra Singh Chauhan ([@withshubh](https://github.com/withshubh)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Wout Vandesompele ([@wowtvds](https://github.com/wowtvds)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) -- Yaroslav Serhieiev ([@noomorph](https://github.com/noomorph)) -- Ziv ([@wewoor](https://github.com/wewoor)) -- [@Drylozu](https://github.com/Drylozu) -- colton ([@cmpadden](https://github.com/cmpadden)) -- 不郑 ([@notzheng](https://github.com/notzheng)) - -## 2.0.0-beta.13 (2021-12-10) - -Good npm publish, same code as beta.11 - -## 2.0.0-beta.12 (2021-12-10) - -Bad npm publish, use beta.13 instead - -## 2.0.0-beta.11 (2021-12-10) - -#### :bug: Bug Fix - -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia` - - [#6078](https://github.com/facebook/docusaurus/pull/6078) fix: move docusaurus core back to hard dependencies ([@pranabdas](https://github.com/pranabdas)) - -#### Committers: 2 - -- Pranab Das ([@pranabdas](https://github.com/pranabdas)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) - -## 2.0.0-beta.10 (2021-12-09) - -#### :rocket: New Feature - -- `create-docusaurus`, `docusaurus-types`, `docusaurus` - - [#5930](https://github.com/facebook/docusaurus/pull/5930) feat: shorthands for themes/plugins/presets configuration ([@fsmaia](https://github.com/fsmaia)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus` - - [#5830](https://github.com/facebook/docusaurus/pull/5830) feat(content-docs): sidebar category linking to document or auto-generated index page ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-types`, `docusaurus` - - [#4095](https://github.com/facebook/docusaurus/pull/4095) feat(core): allow sourcing from multiple static directories ([@oriooctopus](https://github.com/oriooctopus)) -- `create-docusaurus` - - [#3458](https://github.com/facebook/docusaurus/pull/3458) feat(create-docusaurus): allow using local folder as template ([@afshinm](https://github.com/afshinm)) -- `docusaurus-plugin-content-blog` - - [#5787](https://github.com/facebook/docusaurus/pull/5787) feat(content-blog): allow sorting posts in ascending order ([@cerkiewny](https://github.com/cerkiewny)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus` - - [#3104](https://github.com/facebook/docusaurus/pull/3104) feat(core): Add React ErrorBoundary component + theme default boundaries ([@spyke01](https://github.com/spyke01)) - -#### :boom: Breaking Change - -- `docusaurus-plugin-content-blog` - - [#6061](https://github.com/facebook/docusaurus/pull/6061) fix(content-blog): make post ID unique ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate`, `docusaurus-plugin-content-docs` - - [#6065](https://github.com/facebook/docusaurus/pull/6065) refactor: remove deprecated docs homePageId option ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs` - - [#6056](https://github.com/facebook/docusaurus/pull/6056) refactor: remove unused metadata field for homepage ([@lex111](https://github.com/lex111)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus` - - [#5830](https://github.com/facebook/docusaurus/pull/5830) feat(content-docs): sidebar category linking to document or auto-generated index page ([@slorber](https://github.com/slorber)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-preset-classic` - - [#5832](https://github.com/facebook/docusaurus/pull/5832) refactor(ganalytics, gtag): move options out of themeConfig ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils` - - [#5871](https://github.com/facebook/docusaurus/pull/5871) misc: replace all "Metadatas" with "Metadata" ([@swalahamani](https://github.com/swalahamani)) - -#### :bug: Bug Fix - -- `docusaurus-theme-common` - - [#6070](https://github.com/facebook/docusaurus/pull/6070) fix(theme-common): useLocationChange fire un-necessarily twice ([@slorber](https://github.com/slorber)) - - [#6040](https://github.com/facebook/docusaurus/pull/6040) fix: browser storage (localStorage) is unreliable: api should fail-safe ([@slorber](https://github.com/slorber)) -- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#6047](https://github.com/facebook/docusaurus/pull/6047) fix: make Docusaurus PnP strict mode compatible ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus` - - [#6052](https://github.com/facebook/docusaurus/pull/6052) fix(core): fix error boundary import disrupting CSS order ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog` - - [#6061](https://github.com/facebook/docusaurus/pull/6061) fix(content-blog): make post ID unique ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#5983](https://github.com/facebook/docusaurus/pull/5983) fix(core): do not apply theme-init alias to user component ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5798](https://github.com/facebook/docusaurus/pull/5798) fix(cli): update notifier should be shown if current is less than latest ([@semoal](https://github.com/semoal)) - - [#5864](https://github.com/facebook/docusaurus/pull/5864) fix: respect base URL when serving content by webpack dev server ([@lex111](https://github.com/lex111)) -- `docusaurus-module-type-aliases` - - [#5945](https://github.com/facebook/docusaurus/pull/5945) fix(module-type-aliases): add svg declaration ([@MisterFISHUP](https://github.com/MisterFISHUP)) -- `docusaurus-theme-classic` - - [#5873](https://github.com/facebook/docusaurus/pull/5873) fix(theme-classic): fix announcementBar css ([@slorber](https://github.com/slorber)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#6003](https://github.com/facebook/docusaurus/pull/6003) fix(theme-classic): make nav dropdowns focusable ([@robinmetral](https://github.com/robinmetral)) - - [#6000](https://github.com/facebook/docusaurus/pull/6000) fix(theme-classic): make hash link in heading not selectable ([@JararvisQ](https://github.com/JararvisQ)) - - [#5944](https://github.com/facebook/docusaurus/pull/5944) fix: translate all remaining english sentence in French ([@StanKocken](https://github.com/StanKocken)) -- `docusaurus-theme-classic`, `docusaurus` - - [#6048](https://github.com/facebook/docusaurus/pull/6048) refactor: capitalize locales when creating i18n config ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-translations` - - [#5976](https://github.com/facebook/docusaurus/pull/5976) feat(theme-translations): add extra Korean translation, fix typo ([@revi](https://github.com/revi)) - - [#6060](https://github.com/facebook/docusaurus/pull/6060) chore(theme-translations): complete Chinese translations ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate`, `docusaurus-plugin-content-docs` - - [#6065](https://github.com/facebook/docusaurus/pull/6065) refactor: remove deprecated docs homePageId option ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs` - - [#6056](https://github.com/facebook/docusaurus/pull/6056) refactor: remove unused metadata field for homepage ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#6049](https://github.com/facebook/docusaurus/pull/6049) refactor: simplify Toggle component ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-types` - - [#5981](https://github.com/facebook/docusaurus/pull/5981) refactor: minor ESLint improvements ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-pwa` - - [#5995](https://github.com/facebook/docusaurus/pull/5995) chore(plugin-pwa): change core-js version in package.json to v3 ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils` - - [#5849](https://github.com/facebook/docusaurus/pull/5849) refactor: define own translations in other themes ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-types` - - [#5959](https://github.com/facebook/docusaurus/pull/5959) refactor(types): correct HtmlTags types ([@armano2](https://github.com/armano2)) -- `docusaurus` - - [#5829](https://github.com/facebook/docusaurus/pull/5829) refactor: optimize clone and checkout in deploy command ([@sivapalan](https://github.com/sivapalan)) - - [#5899](https://github.com/facebook/docusaurus/pull/5899) feat(core): give more hints when plugins have duplicate IDs ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-preset-classic` - - [#5832](https://github.com/facebook/docusaurus/pull/5832) refactor(ganalytics, gtag): move options out of themeConfig ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus` - - [#5840](https://github.com/facebook/docusaurus/pull/5840) feat: allow GIT_USER env var to be unset if SSH is used ([@wpyoga](https://github.com/wpyoga)) -- `create-docusaurus`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-utils` - - [#5871](https://github.com/facebook/docusaurus/pull/5871) misc: replace all "Metadatas" with "Metadata" ([@swalahamani](https://github.com/swalahamani)) - -#### :memo: Documentation - -- Other - - [#6063](https://github.com/facebook/docusaurus/pull/6063) docs: add moja global to showcase ([@sohamsshah](https://github.com/sohamsshah)) - - [#6069](https://github.com/facebook/docusaurus/pull/6069) docs: update CONTRIBUTING for website ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6062](https://github.com/facebook/docusaurus/pull/6062) refactor(website): improve wording in comments of showcase data ([@sohamsshah](https://github.com/sohamsshah)) - - [#6045](https://github.com/facebook/docusaurus/pull/6045) docs: add "discord resources" to showcase ([@dexbiobot](https://github.com/dexbiobot)) - - [#6026](https://github.com/facebook/docusaurus/pull/6026) docs(deployment): add cost-benefit analysis with different options ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5955](https://github.com/facebook/docusaurus/pull/5955) docs: add Pearl UI website to showcase ([@agrawal-rohit](https://github.com/agrawal-rohit)) - - [#5989](https://github.com/facebook/docusaurus/pull/5989) misc: update CONTRIBUTING to reflect status quo ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5845](https://github.com/facebook/docusaurus/pull/5845) docs(admin): update repo testing instructions to reflect v2 ([@wpyoga](https://github.com/wpyoga)) - - [#6019](https://github.com/facebook/docusaurus/pull/6019) docs: update Netlify url config option in deployment instructions ([@rsapkf](https://github.com/rsapkf)) - - [#6015](https://github.com/facebook/docusaurus/pull/6015) docs: add Tremor website to showcase page ([@skoech](https://github.com/skoech)) - - [#5997](https://github.com/facebook/docusaurus/pull/5997) refactor(website): various fixes and improvements on Showcase page ([@lex111](https://github.com/lex111)) - - [#6008](https://github.com/facebook/docusaurus/pull/6008) docs: improve algolia integration instructions ([@shafy](https://github.com/shafy)) - - [#6006](https://github.com/facebook/docusaurus/pull/6006) docs: improve explanation for url config in GH Pages ([@Martinsos](https://github.com/Martinsos)) - - [#6001](https://github.com/facebook/docusaurus/pull/6001) docs: add Dime.Scheduler SDK to showcase ([@hbulens](https://github.com/hbulens)) - - [#5984](https://github.com/facebook/docusaurus/pull/5984) docs: add PREFS website to showcase ([@Patitotective](https://github.com/Patitotective)) - - [#5967](https://github.com/facebook/docusaurus/pull/5967) docs(website): Add docsearch migration blog post ([@slorber](https://github.com/slorber)) - - [#5968](https://github.com/facebook/docusaurus/pull/5968) refactor(website): shadow on showcase toggle ([@dsmmcken](https://github.com/dsmmcken)) - - [#5979](https://github.com/facebook/docusaurus/pull/5979) docs: update links to default translations dir ([@lex111](https://github.com/lex111)) - - [#5969](https://github.com/facebook/docusaurus/pull/5969) refactor(website): polish on Showcase page ([@slorber](https://github.com/slorber)) - - [#5966](https://github.com/facebook/docusaurus/pull/5966) docs: add Darklang to showcase ([@pbiggar](https://github.com/pbiggar)) - - [#5970](https://github.com/facebook/docusaurus/pull/5970) docs: add Remirror to showcase ([@ronnyroeller](https://github.com/ronnyroeller)) - - [#5971](https://github.com/facebook/docusaurus/pull/5971) docs: add Webiny docs to showcase page ([@swapnilmmane](https://github.com/swapnilmmane)) - - [#5953](https://github.com/facebook/docusaurus/pull/5953) docs: fix BrowserOnly return statement ([@MorookaKotaro](https://github.com/MorookaKotaro)) - - [#5949](https://github.com/facebook/docusaurus/pull/5949) docs: update Signoz showcase details ([@pal-sig](https://github.com/pal-sig)) - - [#5948](https://github.com/facebook/docusaurus/pull/5948) fix(website): fix APITable anchor ID having extra hash ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5947](https://github.com/facebook/docusaurus/pull/5947) fix(website): fix APITable anchor link ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5925](https://github.com/facebook/docusaurus/pull/5925) docs: add Froggit site to showcase page ([@cchaudier](https://github.com/cchaudier)) - - [#5928](https://github.com/facebook/docusaurus/pull/5928) docs: Add Shotstack showcase user ([@jeffski](https://github.com/jeffski)) - - [#5934](https://github.com/facebook/docusaurus/pull/5934) docs: fix a typo in CHANGELOG ([@KonstHardy](https://github.com/KonstHardy)) - - [#5921](https://github.com/facebook/docusaurus/pull/5921) docs: add Signoz site to showcase site ([@pal-sig](https://github.com/pal-sig)) - - [#5891](https://github.com/facebook/docusaurus/pull/5891) docs: new APITable comp to render large tables ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5917](https://github.com/facebook/docusaurus/pull/5917) docs: make API sidebar partially autogenerated ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5903](https://github.com/facebook/docusaurus/pull/5903) docs: refer to deployed branch as deployment rather than target ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5902](https://github.com/facebook/docusaurus/pull/5902) fix(website): fix i18n routes for Canny board ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5900](https://github.com/facebook/docusaurus/pull/5900) docs: document global variables in MDX scope ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#4409](https://github.com/facebook/docusaurus/pull/4409) docs: add example for GitHub Pages deployment; rewrite deployment section ([@polarathene](https://github.com/polarathene)) - - [#5888](https://github.com/facebook/docusaurus/pull/5888) docs: update GitHub deployment instructions ([@rootwork](https://github.com/rootwork)) - - [#5895](https://github.com/facebook/docusaurus/pull/5895) docs: Add juffalow.com to Docusaurus showcase ([@juffalow](https://github.com/juffalow)) - - [#5881](https://github.com/facebook/docusaurus/pull/5881) docs: fix wrong code sample in docusaurus-core ([@matthijsgroen](https://github.com/matthijsgroen)) - - [#5875](https://github.com/facebook/docusaurus/pull/5875) docs: add patrikmasiar website showcase ([@patrikmasiar](https://github.com/patrikmasiar)) - - [#5876](https://github.com/facebook/docusaurus/pull/5876) docs: '5 minutes tutorial' -> '5-minute tutorial' ([@molly](https://github.com/molly)) - - [#5759](https://github.com/facebook/docusaurus/pull/5759) docs: create SEO documentation page ([@cerkiewny](https://github.com/cerkiewny)) - - [#5869](https://github.com/facebook/docusaurus/pull/5869) docs: remove duplicated appId property ([@juzhiyuan](https://github.com/juzhiyuan)) - - [#5868](https://github.com/facebook/docusaurus/pull/5868) docs: fix a typo in using-themes.md ([@fishmandev](https://github.com/fishmandev)) - - [#5862](https://github.com/facebook/docusaurus/pull/5862) misc: show only latest archive alpha/beta versions dropdown ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#5742](https://github.com/facebook/docusaurus/pull/5742) feat(website): redesign of showcase page ([@chimailo](https://github.com/chimailo)) - -#### :house: Internal - -- `create-docusaurus`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-common`, `docusaurus-theme-translations`, `docusaurus-utils-validation`, `docusaurus` - - [#6071](https://github.com/facebook/docusaurus/pull/6071) refactor: add blank lines below all copyright headers ([@Josh-Cena](https://github.com/Josh-Cena)) -- Other - - [#6068](https://github.com/facebook/docusaurus/pull/6068) chore: add prefix to needs triage label; separate Windows test workflow ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6031](https://github.com/facebook/docusaurus/pull/6031) chore: upgrade netlify-cli ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6012](https://github.com/facebook/docusaurus/pull/6012) chore(website): enable strict compiler option ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#6002](https://github.com/facebook/docusaurus/pull/6002) chore(ci): add GitHub action for showcase testing ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5977](https://github.com/facebook/docusaurus/pull/5977) chore: generate dogfooding test for long pathname during CI ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5950](https://github.com/facebook/docusaurus/pull/5950) misc(codeowners): add @Josh-Cena to CODEOWNERS ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5919](https://github.com/facebook/docusaurus/pull/5919) misc(workflow): E2E tests should not be run with website changes ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5907](https://github.com/facebook/docusaurus/pull/5907) chore(workflow): merge jobs into one workflow & give each job a name ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5889](https://github.com/facebook/docusaurus/pull/5889) chore(website): enable eslint in website ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5870](https://github.com/facebook/docusaurus/pull/5870) chore(README): fix broken GitHub Actions Workflow Status icon ([@HemantSachdeva](https://github.com/HemantSachdeva)) -- `docusaurus-module-type-aliases`, `docusaurus-types`, `docusaurus` - - [#6064](https://github.com/facebook/docusaurus/pull/6064) refactor(core): fix types for client code ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-translations`, `docusaurus-utils`, `docusaurus` - - [#6055](https://github.com/facebook/docusaurus/pull/6055) chore: clean up dev dependency declarations ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic` - - [#6010](https://github.com/facebook/docusaurus/pull/6010) chore: upgrade prettier; rename prettier scripts as format ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus`, `docusaurus` - - [#5958](https://github.com/facebook/docusaurus/pull/5958) chore: update @svgr/webpack to version 6 ([@ludofischer](https://github.com/ludofischer)) -- `docusaurus` - - [#5998](https://github.com/facebook/docusaurus/pull/5998) chore: upgrade webpack-dev-server to v4.5.0 ([@lex111](https://github.com/lex111)) - - [#5965](https://github.com/facebook/docusaurus/pull/5965) fix(core): apply staticDirectories to base webpack config ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus` - - [#5985](https://github.com/facebook/docusaurus/pull/5985) chore: cleanup dependency declaration in package.json ([@armano2](https://github.com/armano2)) -- `create-docusaurus`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` - - [#5963](https://github.com/facebook/docusaurus/pull/5963) chore: upgrade TypeScript & other ESLint related deps ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs` - - [#5962](https://github.com/facebook/docusaurus/pull/5962) refactor(content-docs): move isCategoriesShorthand to utils ([@armano2](https://github.com/armano2)) - - [#5906](https://github.com/facebook/docusaurus/pull/5906) fix(content-docs): do not echo git history to console ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5905](https://github.com/facebook/docusaurus/pull/5905) misc(plugin-docs): fix Windows test snapshot for git history retrieval ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5904](https://github.com/facebook/docusaurus/pull/5904) refactor(content-docs): use shelljs instead of execa ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-ideal-image` - - [#5940](https://github.com/facebook/docusaurus/pull/5940) refactor(plugin-ideal-image): migrate package to TS ([@armano2](https://github.com/armano2)) -- `docusaurus-plugin-pwa`, `docusaurus-theme-classic` - - [#5941](https://github.com/facebook/docusaurus/pull/5941) refactor(plugin-pwa): migrate package to TS ([@armano2](https://github.com/armano2)) -- `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia` - - [#5935](https://github.com/facebook/docusaurus/pull/5935) refactor(theme-search-algolia): migrate package to TS ([@armano2](https://github.com/armano2)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages` - - [#5946](https://github.com/facebook/docusaurus/pull/5946) refactor: move deps declarations into src ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus` - - [#5914](https://github.com/facebook/docusaurus/pull/5914) refactor: improve setup of type declaration files ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5922](https://github.com/facebook/docusaurus/pull/5922) refactor(theme-classic): move some logic of CodeBlock to theme-common ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-remark-plugin-npm2yarn` - - [#5931](https://github.com/facebook/docusaurus/pull/5931) refactor(remark-plugin-npm2yarn): migrate package to TS ([@duanwilliam](https://github.com/duanwilliam)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils` - - [#5806](https://github.com/facebook/docusaurus/pull/5806) refactor: use js-yaml to parse both JSON and YAML ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### Committers: 48 - -- Afshin Mehrabani ([@afshinm](https://github.com/afshinm)) -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Armano ([@armano2](https://github.com/armano2)) -- Brennan Kinney ([@polarathene](https://github.com/polarathene)) -- Can Olcer ([@shafy](https://github.com/shafy)) -- Christophe Chaudier ([@cchaudier](https://github.com/cchaudier)) -- Devtato ([@cerkiewny](https://github.com/cerkiewny)) -- Dmitriy Fishman ([@fishmandev](https://github.com/fishmandev)) -- Don ([@dsmmcken](https://github.com/dsmmcken)) -- FISH UP ([@MisterFISHUP](https://github.com/MisterFISHUP)) -- Fernando Maia ([@fsmaia](https://github.com/fsmaia)) -- Hemant Sachdeva ([@HemantSachdeva](https://github.com/HemantSachdeva)) -- Hendrik Bulens ([@hbulens](https://github.com/hbulens)) -- Ivan Boothe ([@rootwork](https://github.com/rootwork)) -- Jarar ([@JararvisQ](https://github.com/JararvisQ)) -- Jeff Shillitto ([@jeffski](https://github.com/jeffski)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Konstantin Popov ([@KonstHardy](https://github.com/KonstHardy)) -- Ludovico Fischer ([@ludofischer](https://github.com/ludofischer)) -- Martin Šošić ([@Martinsos](https://github.com/Martinsos)) -- Matej Jellus ([@juffalow](https://github.com/juffalow)) -- Matthijs Groen ([@matthijsgroen](https://github.com/matthijsgroen)) -- Molly White ([@molly](https://github.com/molly)) -- Morooka Kotaro ([@MorookaKotaro](https://github.com/MorookaKotaro)) -- Oliver Ullman ([@oriooctopus](https://github.com/oriooctopus)) -- Paden Clayton ([@spyke01](https://github.com/spyke01)) -- Patitotective ([@Patitotective](https://github.com/Patitotective)) -- Patrik Mäsiar ([@patrikmasiar](https://github.com/patrikmasiar)) -- Paul Biggar ([@pbiggar](https://github.com/pbiggar)) -- Rey ([@rsapkf](https://github.com/rsapkf)) -- Robin Métral ([@robinmetral](https://github.com/robinmetral)) -- Rohit Agrawal ([@agrawal-rohit](https://github.com/agrawal-rohit)) -- Ronny Roeller ([@ronnyroeller](https://github.com/ronnyroeller)) -- Sergio Moreno ([@semoal](https://github.com/semoal)) -- Sharon Koech ([@skoech](https://github.com/skoech)) -- Shoaib Sajid ([@dexbiobot](https://github.com/dexbiobot)) -- Soham Shah ([@sohamsshah](https://github.com/sohamsshah)) -- Stan Kocken ([@StanKocken](https://github.com/StanKocken)) -- Swalah Amani ([@swalahamani](https://github.com/swalahamani)) -- Swapnil M Mane ([@swapnilmmane](https://github.com/swapnilmmane)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Varun Sivapalan ([@sivapalan](https://github.com/sivapalan)) -- William Poetra Yoga ([@wpyoga](https://github.com/wpyoga)) -- Yongmin Hong ([@revi](https://github.com/revi)) -- [@duanwilliam](https://github.com/duanwilliam) -- [@pal-sig](https://github.com/pal-sig) -- chima ilo ([@chimailo](https://github.com/chimailo)) -- 琚致远 ([@juzhiyuan](https://github.com/juzhiyuan)) - -## 2.0.0-beta.9 (2021-11-02) - -#### :rocket: New Feature - -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5770](https://github.com/facebook/docusaurus/pull/5770) feat(theme-classic): allow specifying width/height in logo ([@cerkiewny](https://github.com/cerkiewny)) -- `docusaurus-types`, `docusaurus` - - [#5841](https://github.com/facebook/docusaurus/pull/5841) feat: allow user to specify deploymentBranch property in docusaurus.config.js ([@wpyoga](https://github.com/wpyoga)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia` - - [#5795](https://github.com/facebook/docusaurus/pull/5795) feat(search-algolia): algolia externalUrl regex to navigate with window.href ([@semoal](https://github.com/semoal)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-types`, `docusaurus` - - [#5814](https://github.com/facebook/docusaurus/pull/5814) feat: Support Node 17 ([@slorber](https://github.com/slorber)) - - [#5420](https://github.com/facebook/docusaurus/pull/5420) feat(core): upgrade to webpack-dev-server@4 ([@AviVahl](https://github.com/AviVahl)) -- `docusaurus-theme-classic` - - [#5791](https://github.com/facebook/docusaurus/pull/5791) feat(theme-classic): add Serbian Cyrillic translation ([@utajum](https://github.com/utajum)) - -#### :boom: Breaking Change - -- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#5812](https://github.com/facebook/docusaurus/pull/5812) chore: require Node 14 ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus-plugin-content-blog` - - [#5835](https://github.com/facebook/docusaurus/pull/5835) fix(content-blog): Fix blog feeds not generated ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#5828](https://github.com/facebook/docusaurus/pull/5828) fix: include all branch tips for shallow clone in deploy command ([@sivapalan](https://github.com/sivapalan)) - - [#5824](https://github.com/facebook/docusaurus/pull/5824) fix: baseUrl passed to sortConfig ([@semoal](https://github.com/semoal)) - - [#5813](https://github.com/facebook/docusaurus/pull/5813) fix: handle SIGTERM in build command ([@slorber](https://github.com/slorber)) -- `docusaurus-module-type-aliases`, `docusaurus` - - [#5819](https://github.com/facebook/docusaurus/pull/5819) fix: use @docusaurus/react-loadable as package alias + include types ([@slorber](https://github.com/slorber)) - -#### :nail_care: Polish - -- `docusaurus-preset-classic` - - [#5831](https://github.com/facebook/docusaurus/pull/5831) feat(preset-classic): guard against unknown keys in options ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#5815](https://github.com/facebook/docusaurus/pull/5815) refactor: some improvements for webpack-dev-server ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` - - [#5788](https://github.com/facebook/docusaurus/pull/5788) refactor: fix a few type inconsistencies ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#5781](https://github.com/facebook/docusaurus/pull/5781) refactor: Vietnamese translations ([@datlechin](https://github.com/datlechin)) - -#### :memo: Documentation - -- Other - - [#5853](https://github.com/facebook/docusaurus/pull/5853) docs: Fix a typo in CONTRIBUTING.md ([@fishmandev](https://github.com/fishmandev)) - - [#5852](https://github.com/facebook/docusaurus/pull/5852) docs: Fix a typo in versioning.md ([@fishmandev](https://github.com/fishmandev)) - - [#5847](https://github.com/facebook/docusaurus/pull/5847) docs: add InfraQL product docs website to showcase ([@jeffreyaven](https://github.com/jeffreyaven)) - - [#5843](https://github.com/facebook/docusaurus/pull/5843) docs: fix i18n routes to feature requests ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5766](https://github.com/facebook/docusaurus/pull/5766) docs: elaborate on the usage of MDX plugins ([@cerkiewny](https://github.com/cerkiewny)) - - [#5826](https://github.com/facebook/docusaurus/pull/5826) docs: fix lint issue ([@slorber](https://github.com/slorber)) - - [#5801](https://github.com/facebook/docusaurus/pull/5801) docs: Update Drone Deployment docs ([@gabrielfalcao](https://github.com/gabrielfalcao)) - - [#5821](https://github.com/facebook/docusaurus/pull/5821) docs: include navbar item type in the API table ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5820](https://github.com/facebook/docusaurus/pull/5820) docs: add @Josh-Cena to the team ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5818](https://github.com/facebook/docusaurus/pull/5818) doc: fix typo in "create a doc" ([@dominikmeyersap](https://github.com/dominikmeyersap)) - - [#5797](https://github.com/facebook/docusaurus/pull/5797) docs: use "npx create-docusaurus" for init ([@slorber](https://github.com/slorber)) - - [#5771](https://github.com/facebook/docusaurus/pull/5771) docs: Minor update to grammar in plugins overview page ([@robbieaverill](https://github.com/robbieaverill)) - - [#5774](https://github.com/facebook/docusaurus/pull/5774) docs: update ssrTemplate ([@juzhiyuan](https://github.com/juzhiyuan)) - - [#5784](https://github.com/facebook/docusaurus/pull/5784) docs: fix link for apply to DocSearch program ([@lex111](https://github.com/lex111)) -- `create-docusaurus` - - [#5792](https://github.com/facebook/docusaurus/pull/5792) docs: fix typo ([@wingclover](https://github.com/wingclover)) - -#### :house: Internal - -- Other - - [#5842](https://github.com/facebook/docusaurus/pull/5842) misc: add "name" field for root package.json ([@wpyoga](https://github.com/wpyoga)) - - [#5836](https://github.com/facebook/docusaurus/pull/5836) chore: switch to GitHub issue forms ([@lex111](https://github.com/lex111)) - - [#5834](https://github.com/facebook/docusaurus/pull/5834) chore(issue templ): add "self service" section in templates ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5833](https://github.com/facebook/docusaurus/pull/5833) chore(workflow): remove v2 prefix from titles ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5697](https://github.com/facebook/docusaurus/pull/5697) chore(workflow): add cache to workflows using actions/setup-node ([@oscard0m](https://github.com/oscard0m)) - - [#5825](https://github.com/facebook/docusaurus/pull/5825) chore: fix Crowdin again ([@slorber](https://github.com/slorber)) - - [#5823](https://github.com/facebook/docusaurus/pull/5823) chore: replace doc sample .pdf file by .xlsx to solve Crowdin issue ([@slorber](https://github.com/slorber)) - - [#5763](https://github.com/facebook/docusaurus/pull/5763) chore: update examples for beta.8 ([@slorber](https://github.com/slorber)) -- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#5812](https://github.com/facebook/docusaurus/pull/5812) chore: require Node 14 ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus` - - [#5807](https://github.com/facebook/docusaurus/pull/5807) refactor: remove a few Lodash usages & ESLint enforcement ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` - - [#5808](https://github.com/facebook/docusaurus/pull/5808) refactor: clear a few ESLint warnings ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `lqip-loader` - - [#5779](https://github.com/facebook/docusaurus/pull/5779) refactor: migrate lqip-loader to TS, fix typing for Webpack Loaders ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### Committers: 18 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Avi Vahl ([@AviVahl](https://github.com/AviVahl)) -- Devtato ([@cerkiewny](https://github.com/cerkiewny)) -- Dmitriy Fishman ([@fishmandev](https://github.com/fishmandev)) -- Dominik Meyer ([@dominikmeyersap](https://github.com/dominikmeyersap)) -- Gabriel Falcão ([@gabrielfalcao](https://github.com/gabrielfalcao)) -- Jeffrey Aven ([@jeffreyaven](https://github.com/jeffreyaven)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Ngô Quốc Đạt ([@datlechin](https://github.com/datlechin)) -- Oscar Dominguez ([@oscard0m](https://github.com/oscard0m)) -- Robbie Averill ([@robbieaverill](https://github.com/robbieaverill)) -- Sergio Moreno ([@semoal](https://github.com/semoal)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Varun Sivapalan ([@sivapalan](https://github.com/sivapalan)) -- Vladimir Tasic ([@utajum](https://github.com/utajum)) -- William Poetra Yoga ([@wpyoga](https://github.com/wpyoga)) -- Ying Wang ([@wingclover](https://github.com/wingclover)) -- 琚致远 ([@juzhiyuan](https://github.com/juzhiyuan)) - -## 2.0.0-beta.8 (2021-10-21) - -#### :rocket: New Feature - -- `docusaurus-plugin-content-blog` - - [#5702](https://github.com/facebook/docusaurus/pull/5702) feat(content-blog): new readingTime plugin option ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#5740](https://github.com/facebook/docusaurus/pull/5740) feat(core): write-heading-ids options maintainCasing, overwrite ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs` - - [#5705](https://github.com/facebook/docusaurus/pull/5705) feat(content-docs): new front matter options to customize pagination ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :boom: Breaking Change - -- `docusaurus-theme-search-algolia` - - [#5751](https://github.com/facebook/docusaurus/pull/5751) fix: stable callbacks in useSearchQuery + refactor ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus-plugin-ideal-image` - - [#5760](https://github.com/facebook/docusaurus/pull/5760) fix(ideal-image): fix IdealImage in dev not handling ES import images properly ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#5732](https://github.com/facebook/docusaurus/pull/5732) fix(theme-classic): allow tabs with number as value ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5721](https://github.com/facebook/docusaurus/pull/5721) fix: handle rubber band scrolling in hideable navbar ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-search-algolia` - - [#5751](https://github.com/facebook/docusaurus/pull/5751) fix: stable callbacks in useSearchQuery + refactor ([@slorber](https://github.com/slorber)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#5717](https://github.com/facebook/docusaurus/pull/5717) refactor: Polish de translation ([@philipp985](https://github.com/philipp985)) - - [#5725](https://github.com/facebook/docusaurus/pull/5725) refactor: add missing Turkish translations to theme-classic ([@canercanbaz](https://github.com/canercanbaz)) - - [#5723](https://github.com/facebook/docusaurus/pull/5723) refactor(v2): update Vietnamese translations ([@datlechin](https://github.com/datlechin)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic`, `docusaurus` - - [#5726](https://github.com/facebook/docusaurus/pull/5726) refactor(module-type-aliases): remove fallback aliases ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :memo: Documentation - -- Other - - [#5755](https://github.com/facebook/docusaurus/pull/5755) docs: rename docusaurus.config.js route + redirects cleanup ([@slorber](https://github.com/slorber)) - - [#5750](https://github.com/facebook/docusaurus/pull/5750) docs(v2): Fix typo in using-plugins.md ([@thanasis00](https://github.com/thanasis00)) - - [#5727](https://github.com/facebook/docusaurus/pull/5727) docs(v2): Add Fenghua Frontend Developer site to showcase page ([@zxuqian](https://github.com/zxuqian)) - - [#5746](https://github.com/facebook/docusaurus/pull/5746) docs: Add plugin-image-zoom ([@ataft](https://github.com/ataft)) - - [#5728](https://github.com/facebook/docusaurus/pull/5728) docs: add h4 into toc on certain pages ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5737](https://github.com/facebook/docusaurus/pull/5737) docs: Add Apex FP to showcase ([@ipavlic](https://github.com/ipavlic)) -- `docusaurus-plugin-content-blog` - - [#5753](https://github.com/facebook/docusaurus/pull/5753) fix(content-blog): temporarily swallow feed mdxToHtml errors + feed refactor ([@slorber](https://github.com/slorber)) - -#### :house: Internal - -- `docusaurus` - - [#5761](https://github.com/facebook/docusaurus/pull/5761) chore: upgrade html-webpack-plugin, remove terser 4 ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#5714](https://github.com/facebook/docusaurus/pull/5714) chore: Enable ESLint rules of hooks + fix new lint errors ([@slorber](https://github.com/slorber)) -- Other - - [#5722](https://github.com/facebook/docusaurus/pull/5722) chore: fix gen script to support TS template ([@lex111](https://github.com/lex111)) - - [#5730](https://github.com/facebook/docusaurus/pull/5730) chore: fix typos / casing in issue template ([@johnnyreilly](https://github.com/johnnyreilly)) - - [#5720](https://github.com/facebook/docusaurus/pull/5720) chore: regenerate beta.7 examples ([@lex111](https://github.com/lex111)) - - [#5719](https://github.com/facebook/docusaurus/pull/5719) chore: remove beta.5 docs ([@lex111](https://github.com/lex111)) - -#### :running_woman: Performance - -- `docusaurus` - - [#5748](https://github.com/facebook/docusaurus/pull/5748) refactor: perform shallow clone during deploy ([@nlfurniss](https://github.com/nlfurniss)) - -#### Committers: 13 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Andrew Taft ([@ataft](https://github.com/ataft)) -- Caner Canbaz ([@canercanbaz](https://github.com/canercanbaz)) -- Dimi Mikadze ([@DimiMikadze](https://github.com/DimiMikadze)) -- Ilija Pavlic ([@ipavlic](https://github.com/ipavlic)) -- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Nathaniel Furniss ([@nlfurniss](https://github.com/nlfurniss)) -- Ngô Quốc Đạt ([@datlechin](https://github.com/datlechin)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Thanasis Katsadas ([@thanasis00](https://github.com/thanasis00)) -- Xuqian ([@zxuqian](https://github.com/zxuqian)) -- [@philipp985](https://github.com/philipp985) - -## 2.0.0-beta.7 (2021-10-15) - -#### :rocket: New Feature - -- `docusaurus-module-type-aliases`, `docusaurus` - - [#5683](https://github.com/facebook/docusaurus/pull/5683) feat: make Translate children optional ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5674](https://github.com/facebook/docusaurus/pull/5674) polish(theme-classic): guard against potential definition mistakes in Tabs ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5618](https://github.com/facebook/docusaurus/pull/5618) feat: maintain page position for clicked grouped tabs ([@Shrugsy](https://github.com/Shrugsy)) -- `docusaurus-plugin-content-blog`, `docusaurus-utils` - - [#4330](https://github.com/facebook/docusaurus/pull/4330) feat(content-blog): add full blog post html into RSS/Atom feeds ([@moonrailgun](https://github.com/moonrailgun)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5642](https://github.com/facebook/docusaurus/pull/5642) feat(theme-classic, plugin-docs): sidebar item level-specific className + allow customization ([@Josh-Cena](https://github.com/Josh-Cena)) -- `create-docusaurus` - - [#5635](https://github.com/facebook/docusaurus/pull/5635) feat: npm init docusaurus, yarn create docusaurus ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types` - - [#5589](https://github.com/facebook/docusaurus/pull/5589) feat: properly type-check the Docusaurus config of new sites ([@bmiddha](https://github.com/bmiddha)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-validation` - - [#5578](https://github.com/facebook/docusaurus/pull/5578) feat(v2): allow specifying TOC max depth (themeConfig + frontMatter) ([@erickzhao](https://github.com/erickzhao)) -- `docusaurus` - - [#5498](https://github.com/facebook/docusaurus/pull/5498) feat: make Webpack url-loader limit configurable (env variable) ([@stnor](https://github.com/stnor)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` - - [#5545](https://github.com/facebook/docusaurus/pull/5545) feat: make tags route path configurable ([@lex111](https://github.com/lex111)) - -#### :boom: Breaking Change - -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5674](https://github.com/facebook/docusaurus/pull/5674) polish(theme-classic): guard against potential definition mistakes in Tabs ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5618](https://github.com/facebook/docusaurus/pull/5618) feat: maintain page position for clicked grouped tabs ([@Shrugsy](https://github.com/Shrugsy)) -- `docusaurus-init`, `docusaurus-preset-bootstrap`, `docusaurus-theme-bootstrap` - - [#5634](https://github.com/facebook/docusaurus/pull/5634) chore: remove unused Bootstrap theme ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-validation` - - [#5578](https://github.com/facebook/docusaurus/pull/5578) feat(v2): allow specifying TOC max depth (themeConfig + frontMatter) ([@erickzhao](https://github.com/erickzhao)) -- `docusaurus-theme-classic` - - [#5592](https://github.com/facebook/docusaurus/pull/5592) refactor: use CSS Modules for toggle styles ([@lex111](https://github.com/lex111)) - -#### :bug: Bug Fix - -- `docusaurus-theme-common` - - [#5694](https://github.com/facebook/docusaurus/pull/5694) fix: proper collapsing of long element ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#5684](https://github.com/facebook/docusaurus/pull/5684) fix: use realpath for site dir to resolve symlink ([@lex111](https://github.com/lex111)) - - [#5645](https://github.com/facebook/docusaurus/pull/5645) fix: place root route at the end ([@lex111](https://github.com/lex111)) - - [#5629](https://github.com/facebook/docusaurus/pull/5629) fix: text/link hydration bug ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5699](https://github.com/facebook/docusaurus/pull/5699) fix: apply announcement bar class if only needed ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#5667](https://github.com/facebook/docusaurus/pull/5667) fix: expand tag column on truncated post ([@lex111](https://github.com/lex111)) - - [#5668](https://github.com/facebook/docusaurus/pull/5668) fix: preserve line breaks when copy code in Firefox ([@lex111](https://github.com/lex111)) - - [#5647](https://github.com/facebook/docusaurus/pull/5647) feat(theme-classic): make first tab the default tab ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5652](https://github.com/facebook/docusaurus/pull/5652) fix: restore duplicate Tabs rendering to fix hydration issue ([@slorber](https://github.com/slorber)) - - [#5643](https://github.com/facebook/docusaurus/pull/5643) fix(theme-classic): reset default style for task lists ([@EkaterinaMozheiko](https://github.com/EkaterinaMozheiko)) - - [#5571](https://github.com/facebook/docusaurus/pull/5571) fix: highlight active item in recent post list ([@lex111](https://github.com/lex111)) - - [#5481](https://github.com/facebook/docusaurus/pull/5481) fix: use heading itself as anchor for better crawling ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-live-codeblock` - - [#5677](https://github.com/facebook/docusaurus/pull/5677) fix: Don't ignore options.transforms for buble ([@ntucker](https://github.com/ntucker)) - - [#5556](https://github.com/facebook/docusaurus/pull/5556) fix: pin react-live due to possible mismatch React ([@lex111](https://github.com/lex111)) -- `docusaurus-mdx-loader` - - [#5690](https://github.com/facebook/docusaurus/pull/5690) fix: preserve hash in asset link ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-ideal-image` - - [#5540](https://github.com/facebook/docusaurus/pull/5540) fix: do not use ideal image plugin in dev env ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs` - - [#5606](https://github.com/facebook/docusaurus/pull/5606) fix(docs): create tags route if only tags exists ([@lex111](https://github.com/lex111)) -- `docusaurus-init`, `docusaurus-module-type-aliases`, `docusaurus-types` - - [#5601](https://github.com/facebook/docusaurus/pull/5601) fix(module-type-aliases): move @type packages to dependencies ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-utils` - - [#5495](https://github.com/facebook/docusaurus/pull/5495) fix: ignore code block lines when creating excerpt ([@lex111](https://github.com/lex111)) -- `docusaurus-init` - - [#5490](https://github.com/facebook/docusaurus/pull/5490) fix: install deps for new project via Yarn on Windows properly ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils-validation` - - [#5479](https://github.com/facebook/docusaurus/pull/5479) fix: add docs tag validation to solve #5478 ([@sw-yx](https://github.com/sw-yx)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5709](https://github.com/facebook/docusaurus/pull/5709) refactor: cleanup scroll handlers ([@lex111](https://github.com/lex111)) - - [#5627](https://github.com/facebook/docusaurus/pull/5627) refactor: various TOC improvements ([@lex111](https://github.com/lex111)) - - [#5469](https://github.com/facebook/docusaurus/pull/5469) refactor: Adjust styling of back top top button ([@dsmmcken](https://github.com/dsmmcken)) -- `docusaurus-theme-classic` - - [#5708](https://github.com/facebook/docusaurus/pull/5708) refactor: hide hash link from crawlers ([@lex111](https://github.com/lex111)) - - [#5649](https://github.com/facebook/docusaurus/pull/5649) refactor: improve pt-BR translation for classic theme ([@printf-ana](https://github.com/printf-ana)) - - [#5646](https://github.com/facebook/docusaurus/pull/5646) refactor: complete missing and fix ES translations ([@caleeli](https://github.com/caleeli)) - - [#5640](https://github.com/facebook/docusaurus/pull/5640) style: update Persian language translations ([@MrTechHunter](https://github.com/MrTechHunter)) - - [#5630](https://github.com/facebook/docusaurus/pull/5630) refactor: standardize using media queries ([@lex111](https://github.com/lex111)) - - [#5487](https://github.com/facebook/docusaurus/pull/5487) refactor: use only one close SVG icon ([@lex111](https://github.com/lex111)) - - [#5592](https://github.com/facebook/docusaurus/pull/5592) refactor: use CSS Modules for toggle styles ([@lex111](https://github.com/lex111)) - - [#5485](https://github.com/facebook/docusaurus/pull/5485) polish: prevent pop navigation on back if navbar sidebar is open ([@slorber](https://github.com/slorber)) - - [#5472](https://github.com/facebook/docusaurus/pull/5472) polish(theme-classic): add Chinese translations ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#5636](https://github.com/facebook/docusaurus/pull/5636) refactor: make all Props defined as interface + readonly ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus` - - [#5560](https://github.com/facebook/docusaurus/pull/5560) polish: remove unused eslint-disable ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#5580](https://github.com/facebook/docusaurus/pull/5580) refactor(core): type improvements for `PendingNavigation` ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus` - - [#5496](https://github.com/facebook/docusaurus/pull/5496) refactor: remove deprecated createRequireFromPath ([@lex111](https://github.com/lex111)) - -#### :memo: Documentation - -- [#5681](https://github.com/facebook/docusaurus/pull/5681) docs(v2): Add CountryStateCityAPI site to showcase page ([@dr5hn](https://github.com/dr5hn)) -- [#5661](https://github.com/facebook/docusaurus/pull/5661) docs: updated cloudywithachanceofbigdata.com blog showcase ([@jeffreyaven](https://github.com/jeffreyaven)) -- [#5658](https://github.com/facebook/docusaurus/pull/5658) docs: Algolia plugin must be enabled before crawling the site ([@slorber](https://github.com/slorber)) -- [#5654](https://github.com/facebook/docusaurus/pull/5654) docs: Add Warrant Docs site to showcase page ([@akajla09](https://github.com/akajla09)) -- [#5655](https://github.com/facebook/docusaurus/pull/5655) docs: Added cloudywithachanceofbigdata.com showcase blog ([@jeffreyaven](https://github.com/jeffreyaven)) -- [#5648](https://github.com/facebook/docusaurus/pull/5648) docs: add ory documentation to showcase ([@vinckr](https://github.com/vinckr)) -- [#5644](https://github.com/facebook/docusaurus/pull/5644) docs: add djamaile blog to site showcase ([@djamaile](https://github.com/djamaile)) -- [#5641](https://github.com/facebook/docusaurus/pull/5641) docs: add Lux Algo to showcase ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#5638](https://github.com/facebook/docusaurus/pull/5638) docs: add nanos world docs to showcase ([@gtnardy](https://github.com/gtnardy)) -- [#5610](https://github.com/facebook/docusaurus/pull/5610) docs: Add IOTA wiki to showcase ([@Dr-Electron](https://github.com/Dr-Electron)) -- [#5489](https://github.com/facebook/docusaurus/pull/5489) docs: add additional search options, typesense and local search ([@jasonbosco](https://github.com/jasonbosco)) -- [#5590](https://github.com/facebook/docusaurus/pull/5590) docs(website): document npm2yarn plugin + use new Tabs API everywhere ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#5591](https://github.com/facebook/docusaurus/pull/5591) docs: Add whirl.codes to showcase ([@Whirl21](https://github.com/Whirl21)) -- [#5574](https://github.com/facebook/docusaurus/pull/5574) docs: add Pipeline UI to showcase ([@headline-design](https://github.com/headline-design)) -- [#5585](https://github.com/facebook/docusaurus/pull/5585) docs: fix more references to Discord channels ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#5572](https://github.com/facebook/docusaurus/pull/5572) docs: add Blogasaurus to showcase ([@BattleOfPlassey](https://github.com/BattleOfPlassey)) -- [#5575](https://github.com/facebook/docusaurus/pull/5575) docs: clarify MDX version used ([@lex111](https://github.com/lex111)) -- [#5581](https://github.com/facebook/docusaurus/pull/5581) docs(website): update all Discord links ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#5566](https://github.com/facebook/docusaurus/pull/5566) docs: fix code example ([@ChrisChinchilla](https://github.com/ChrisChinchilla)) -- [#5559](https://github.com/facebook/docusaurus/pull/5559) docs: minor grammatical correction ([@jkhaui](https://github.com/jkhaui)) -- [#5543](https://github.com/facebook/docusaurus/pull/5543) docs: add note about files being ignored when prefixed with an unders… ([@KyrietS](https://github.com/KyrietS)) -- [#5549](https://github.com/facebook/docusaurus/pull/5549) docs: Add Mint Metrics site to the Showcase ([@kingo55](https://github.com/kingo55)) -- [#5546](https://github.com/facebook/docusaurus/pull/5546) docs: add unleash to showcase ([@ivarconr](https://github.com/ivarconr)) -- [#5539](https://github.com/facebook/docusaurus/pull/5539) docs: improve escape pipe in Markdown tables ([@forresst](https://github.com/forresst)) -- [#5486](https://github.com/facebook/docusaurus/pull/5486) docs: mention Netlify ignore build setting ([@slorber](https://github.com/slorber)) -- [#5482](https://github.com/facebook/docusaurus/pull/5482) docs: update docusaurus-plugin-relative-paths description ([@ohkimur](https://github.com/ohkimur)) - -#### :house: Internal - -- `create-docusaurus`, `docusaurus-plugin-content-docs` - - [#5678](https://github.com/facebook/docusaurus/pull/5678) refactor(content-docs): refactor sidebars, Joi validation, generator rework, expose config types ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#5666](https://github.com/facebook/docusaurus/pull/5666) chore: upgrade Infima to alpha.34 ([@lex111](https://github.com/lex111)) - - [#5639](https://github.com/facebook/docusaurus/pull/5639) misc: update base translation + remove extra char ([@lex111](https://github.com/lex111)) -- Other - - [#5669](https://github.com/facebook/docusaurus/pull/5669) fix: allow ColorGenerator to parse colors with prefix `#` ([@Andrewnt219](https://github.com/Andrewnt219)) - - [#5632](https://github.com/facebook/docusaurus/pull/5632) chore: prepare Algolia migration ([@slorber](https://github.com/slorber)) - - [#5628](https://github.com/facebook/docusaurus/pull/5628) chore: fix warning after build ([@lex111](https://github.com/lex111)) - - [#5573](https://github.com/facebook/docusaurus/pull/5573) misc: fix ungrammatical sentence about 5-min tutorial ([@hughlilly](https://github.com/hughlilly)) - - [#5499](https://github.com/facebook/docusaurus/pull/5499) chore: set up CodeQL ([@zpao](https://github.com/zpao)) - - [#5474](https://github.com/facebook/docusaurus/pull/5474) chore: remove beta.4 docs (already archived) ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-preset-bootstrap`, `docusaurus-theme-bootstrap` - - [#5634](https://github.com/facebook/docusaurus/pull/5634) chore: remove unused Bootstrap theme ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#5611](https://github.com/facebook/docusaurus/pull/5611) chore: upgrade Prettier + regenerate lock file ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-pwa`, `docusaurus` - - [#5609](https://github.com/facebook/docusaurus/pull/5609) chore: upgrade Terser-related dependencies ([@lex111](https://github.com/lex111)) -- `docusaurus-cssnano-preset`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#5608](https://github.com/facebook/docusaurus/pull/5608) chore: upgrade dependencies ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#5605](https://github.com/facebook/docusaurus/pull/5605) refactor(core): enforce noImplicitAny ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-preset-classic` - - [#5603](https://github.com/facebook/docusaurus/pull/5603) fix(preset-classic): fix TS build issue ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-preset-classic` - - [#5561](https://github.com/facebook/docusaurus/pull/5561) refactor(plugin-google-gtag, plugin-google-analytics): migrate packages to TS ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic` - - [#5579](https://github.com/facebook/docusaurus/pull/5579) refactor(preset-classic): migrate preset-classic to TypeScript ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-init` - - [#5484](https://github.com/facebook/docusaurus/pull/5484) chore: regenerate beta.6 examples + fix regen script ([@slorber](https://github.com/slorber)) - -#### Committers: 36 - -- Aditya Kajla ([@akajla09](https://github.com/akajla09)) -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Ana Carolina ([@printf-ana](https://github.com/printf-ana)) -- Andrew Nguyen ([@Andrewnt219](https://github.com/Andrewnt219)) -- Bharat Middha ([@bmiddha](https://github.com/bmiddha)) -- Chris Chinchilla ([@ChrisChinchilla](https://github.com/ChrisChinchilla)) -- Daniel Costrasel ([@ohkimur](https://github.com/ohkimur)) -- Darshan Gada ([@dr5hn](https://github.com/dr5hn)) -- David Callizaya ([@caleeli](https://github.com/caleeli)) -- Don ([@dsmmcken](https://github.com/dsmmcken)) -- Ekaterina Mozheiko ([@EkaterinaMozheiko](https://github.com/EkaterinaMozheiko)) -- Erick Zhao ([@erickzhao](https://github.com/erickzhao)) -- Forresst ([@forresst](https://github.com/forresst)) -- Gabriel T. Nardy ([@gtnardy](https://github.com/gtnardy)) -- Hugh Lilly ([@hughlilly](https://github.com/hughlilly)) -- Ivar Conradi Østhus ([@ivarconr](https://github.com/ivarconr)) -- Jason Bosco ([@jasonbosco](https://github.com/jasonbosco)) -- Jeffrey Aven ([@jeffreyaven](https://github.com/jeffreyaven)) -- Jordan Lee ([@jkhaui](https://github.com/jkhaui)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Kyriet ([@KyrietS](https://github.com/KyrietS)) -- Mahdi Hamldar ([@MrTechHunter](https://github.com/MrTechHunter)) -- Nathaniel Tucker ([@ntucker](https://github.com/ntucker)) -- Palash Shrivastava ([@BattleOfPlassey](https://github.com/BattleOfPlassey)) -- Paul O’Shannessy ([@zpao](https://github.com/zpao)) -- Robert Kingston ([@kingo55](https://github.com/kingo55)) -- Stefan Norberg ([@stnor](https://github.com/stnor)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Vincent ([@vinckr](https://github.com/vinckr)) -- Whirl ([@Whirl21](https://github.com/Whirl21)) -- [@Dr-Electron](https://github.com/Dr-Electron) -- [@Shrugsy](https://github.com/Shrugsy) -- [@djamaile](https://github.com/djamaile) -- [@headline-design](https://github.com/headline-design) -- moonrailgun ([@moonrailgun](https://github.com/moonrailgun)) -- swyx ([@sw-yx](https://github.com/sw-yx)) - -## 2.0.0-beta.6 (2021-09-02) - -#### :rocket: New Feature - -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` - - [#5428](https://github.com/facebook/docusaurus/pull/5428) feat: adds blog archive route ([@gabrielcsapo](https://github.com/gabrielcsapo)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5462](https://github.com/facebook/docusaurus/pull/5462) feat: on back navigation, close mobile sidebar ([@slorber](https://github.com/slorber)) - - [#5445](https://github.com/facebook/docusaurus/pull/5445) feat: Add docs-related stable classnames ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#5460](https://github.com/facebook/docusaurus/pull/5460) feat: infima 33 + navbar-sidebar close button ([@slorber](https://github.com/slorber)) - - [#5442](https://github.com/facebook/docusaurus/pull/5442) feat(theme-classic): allow passing tab label and default value through TabItem ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#5454](https://github.com/facebook/docusaurus/pull/5454) feat: new docs options: versions.{badge,className} ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#5444](https://github.com/facebook/docusaurus/pull/5444) fix: fix some theme UI issues (blockquotes, navbar-sidebar font) with Infima alpha.32 ([@slorber](https://github.com/slorber)) - - [#5431](https://github.com/facebook/docusaurus/pull/5431) fix: some beta.5 bugfixes ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#5437](https://github.com/facebook/docusaurus/pull/5437) fix: fix a few TS errors ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :nail_care: Polish - -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#5459](https://github.com/facebook/docusaurus/pull/5459) refactor(theme-classic): completely migrate package to TypeScript ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#5453](https://github.com/facebook/docusaurus/pull/5453) refactor: use SVG for closable button in announcement bar ([@lex111](https://github.com/lex111)) - - [#5430](https://github.com/facebook/docusaurus/pull/5430) refactor: switch to Flexbox in announcement bar ([@lex111](https://github.com/lex111)) - - [#5434](https://github.com/facebook/docusaurus/pull/5434) refactor: update Arabic and Persian translations ([@3alisaki](https://github.com/3alisaki)) - - [#5410](https://github.com/facebook/docusaurus/pull/5410) refactor: add missing translations in fa.json ([@farshidinanloo](https://github.com/farshidinanloo)) - -#### :memo: Documentation - -- [#5471](https://github.com/facebook/docusaurus/pull/5471) docs: Add docusaurus-plugin-relative-paths ([@ohkimur](https://github.com/ohkimur)) -- [#5464](https://github.com/facebook/docusaurus/pull/5464) docs: add mapillary-js to showcase ([@oscarlorentzon](https://github.com/oscarlorentzon)) -- [#5433](https://github.com/facebook/docusaurus/pull/5433) docs: document doc tags + refinements ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#5435](https://github.com/facebook/docusaurus/pull/5435) docs: Add netboot.xyz to site showcase ([@antonym](https://github.com/antonym)) -- [#5436](https://github.com/facebook/docusaurus/pull/5436) docs: add Redocusaurus in community plugin list ([@rohit-gohri](https://github.com/rohit-gohri)) - -#### :house: Internal - -- [#5455](https://github.com/facebook/docusaurus/pull/5455) fix: website bad version name in docusaurus.config.js ([@slorber](https://github.com/slorber)) - -#### Committers: 10 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Ali Saki ([@3alisaki](https://github.com/3alisaki)) -- Antony Messerli ([@antonym](https://github.com/antonym)) -- Daniel Costrasel ([@ohkimur](https://github.com/ohkimur)) -- Gabriel Csapo ([@gabrielcsapo](https://github.com/gabrielcsapo)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Oscar Lorentzon ([@oscarlorentzon](https://github.com/oscarlorentzon)) -- Rohit Gohri ([@rohit-gohri](https://github.com/rohit-gohri)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- farshid ([@farshidinanloo](https://github.com/farshidinanloo)) - -## 2.0.0-beta.5 (2021-08-26) - -#### :rocket: New Feature - -- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-utils-validation` - - [#5396](https://github.com/facebook/docusaurus/pull/5396) feat(plugin-blog): multi-authors support + authors.yml global configuration ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` - - [#5371](https://github.com/facebook/docusaurus/pull/5371) feat: make blog config options and navbar versions dropdown label translatable ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5375](https://github.com/facebook/docusaurus/pull/5375) feat: add metatags support for seo / blogposts #5373 ([@johnnyreilly](https://github.com/johnnyreilly)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-validation`, `docusaurus-utils` - - [#3646](https://github.com/facebook/docusaurus/pull/3646) feat: doc tags (same as blog tags) ([@isaac-philip](https://github.com/isaac-philip)) -- `docusaurus-plugin-content-blog` - - [#5354](https://github.com/facebook/docusaurus/pull/5354) feat(plugin-blog): allow `'ALL'` as `postsPerPage` option value ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#5330](https://github.com/facebook/docusaurus/pull/5330) feat: Markdown page-specific head metadatas ([@slorber](https://github.com/slorber)) - - [#5322](https://github.com/facebook/docusaurus/pull/5322) feat: structured data for blog posts ([@johnnyreilly](https://github.com/johnnyreilly)) - - [#5314](https://github.com/facebook/docusaurus/pull/5314) feat(v2): add cs (Czech) translations for docusaurus-theme-classic ([@michalsanger](https://github.com/michalsanger)) -- `docusaurus-init` - - [#5233](https://github.com/facebook/docusaurus/pull/5233) feat: new init template classic-typescript ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` - - [#5309](https://github.com/facebook/docusaurus/pull/5309) feat: blog posts support /YYYY/MM/DD/blog-post/index.md pattern + blog frontmatter can reference relative images ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader`, `docusaurus` - - [#5299](https://github.com/facebook/docusaurus/pull/5299) feat: mdx loader fallback, allow importing mdx docs from anywhere ([@slorber](https://github.com/slorber)) - -#### :boom: Breaking Change - -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-validation`, `docusaurus-utils` - - [#3646](https://github.com/facebook/docusaurus/pull/3646) feat: doc tags (same as blog tags) ([@isaac-philip](https://github.com/isaac-philip)) -- `docusaurus-init`, `docusaurus-migrate`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus` - - [#5345](https://github.com/facebook/docusaurus/pull/5345) refactor: rename Git master branch to main ([@zpao](https://github.com/zpao)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-types`, `docusaurus` - - [#5349](https://github.com/facebook/docusaurus/pull/5349) refactor(core): replace useDocusaurusContext().isClient by useIsBrowser() ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#5264](https://github.com/facebook/docusaurus/pull/5264) fix: apply proper class for active doc item on mobiles + avoid duplicated classes ([@lex111](https://github.com/lex111)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#5425](https://github.com/facebook/docusaurus/pull/5425) fix: toc does not highlight clicked anchor + use scroll-margin-top ([@slorber](https://github.com/slorber)) - - [#5424](https://github.com/facebook/docusaurus/pull/5424) refactor: make dynamic authors layout via CSS only ([@lex111](https://github.com/lex111)) - - [#5422](https://github.com/facebook/docusaurus/pull/5422) fix: make tags wrapping properly ([@lex111](https://github.com/lex111)) - - [#5419](https://github.com/facebook/docusaurus/pull/5419) fix: various fixes back-to-top button ([@lex111](https://github.com/lex111)) - - [#5361](https://github.com/facebook/docusaurus/pull/5361) fix: refactor TOC highlighting + handle edge cases ([@slorber](https://github.com/slorber)) - - [#5357](https://github.com/facebook/docusaurus/pull/5357) fix: code blocks should scroll in RTL direction ([@slorber](https://github.com/slorber)) - - [#5346](https://github.com/facebook/docusaurus/pull/5346) fix: author/image adjustments in BlogPosting schema ([@lex111](https://github.com/lex111)) - - [#5240](https://github.com/facebook/docusaurus/pull/5240) fix: remove top margin only from directly first element ([@lex111](https://github.com/lex111)) - - [#5317](https://github.com/facebook/docusaurus/pull/5317) fix: make proper highlighting doc link if no sidebar ([@hamzahamidi](https://github.com/hamzahamidi)) - - [#5316](https://github.com/facebook/docusaurus/pull/5316) fix: avoid extra default active class on doc sidebar item ([@lex111](https://github.com/lex111)) - - [#5319](https://github.com/facebook/docusaurus/pull/5319) fix: unbreak highlighting regular navbar links ([@lex111](https://github.com/lex111)) - - [#5264](https://github.com/facebook/docusaurus/pull/5264) fix: apply proper class for active doc item on mobiles + avoid duplicated classes ([@lex111](https://github.com/lex111)) - - [#5275](https://github.com/facebook/docusaurus/pull/5275) fix: improve spanish translation ([@faloi](https://github.com/faloi)) - - [#5262](https://github.com/facebook/docusaurus/pull/5262) fix: show secondary menu if even there is no main one ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#5426](https://github.com/facebook/docusaurus/pull/5426) fix: Make update-notifier fail-safe if no permission to read configStore ([@slorber](https://github.com/slorber)) - - [#5398](https://github.com/facebook/docusaurus/pull/5398) fix: fix write-translations warning for theme-common translations ([@slorber](https://github.com/slorber)) - - [#5381](https://github.com/facebook/docusaurus/pull/5381) fix: canary releases should ignore notifier updates ([@slorber](https://github.com/slorber)) - - [#5339](https://github.com/facebook/docusaurus/pull/5339) fix: add admonitions support to mdx partials loaded through the fallback mdx loader ([@slorber](https://github.com/slorber)) - - [#5311](https://github.com/facebook/docusaurus/pull/5311) fix: docusaurus serve logs wrong port if 3000 is taken ([@wan-nyan-wan](https://github.com/wan-nyan-wan)) - - [#5308](https://github.com/facebook/docusaurus/pull/5308) fix: remove unexpected whitespaces in CSS bundle ([@lex111](https://github.com/lex111)) - - [#5268](https://github.com/facebook/docusaurus/pull/5268) fix: fix wrong regex that removes extra letters from swizzled component names ([@Josh-Cena](https://github.com/Josh-Cena)) -- Other - - [#5399](https://github.com/facebook/docusaurus/pull/5399) fix: fix site unlocalized 404 pages + aggressive Netlify /assets caching ([@slorber](https://github.com/slorber)) - - [#5249](https://github.com/facebook/docusaurus/pull/5249) fix: fix Crowdin mapping for pt-BR ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus` - - [#5383](https://github.com/facebook/docusaurus/pull/5383) fix: fix Locale Dropdown RTL icon + Webpack aliases ordering ([@slorber](https://github.com/slorber)) -- `docusaurus-init` - - [#5370](https://github.com/facebook/docusaurus/pull/5370) fix(init): fix links to feature images in classic-typescript ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-common` - - [#5364](https://github.com/facebook/docusaurus/pull/5364) fix: unbreak Details component ([@lex111](https://github.com/lex111)) - - [#5297](https://github.com/facebook/docusaurus/pull/5297) fix: fix constant value import ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-ideal-image` - - [#5334](https://github.com/facebook/docusaurus/pull/5334) fix: plugin ideal-image should generate filename with a hash even in development ([@Pierre-Gilles](https://github.com/Pierre-Gilles)) -- `docusaurus-theme-search-algolia` - - [#5290](https://github.com/facebook/docusaurus/pull/5290) fix: make successful build if missing favicon ([@lex111](https://github.com/lex111)) -- `docusaurus-utils` - - [#5270](https://github.com/facebook/docusaurus/pull/5270) fix: ability to link md files with relative paths when paths contain space ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-types` - - [#5261](https://github.com/facebook/docusaurus/pull/5261) fix: fix various TS errors ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :nail_care: Polish - -- `docusaurus-theme-common` - - [#5402](https://github.com/facebook/docusaurus/pull/5402) refactor: improve styles of Details component ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#5386](https://github.com/facebook/docusaurus/pull/5386) refactor: various tags improvements ([@lex111](https://github.com/lex111)) - - [#5377](https://github.com/facebook/docusaurus/pull/5377) refactor: make main heading font size changeable via CSS var ([@lex111](https://github.com/lex111)) - - [#5355](https://github.com/facebook/docusaurus/pull/5355) refactor: add blog microdata in markup instead of use JSON-LD ([@lex111](https://github.com/lex111)) - - [#5365](https://github.com/facebook/docusaurus/pull/5365) refactor(v2): improved Farsi default translations ([@massoudmaboudi](https://github.com/massoudmaboudi)) - - [#5280](https://github.com/facebook/docusaurus/pull/5280) refactor(v2): improved Farsi default translations ([@massoudmaboudi](https://github.com/massoudmaboudi)) -- Other - - [#5389](https://github.com/facebook/docusaurus/pull/5389) refactor: clean Canny integration + rename 'Feedback' to 'Feature Requests' + improve TS doc page ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5242](https://github.com/facebook/docusaurus/pull/5242) refactor: reduce ESLint warnings / better typing ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :memo: Documentation - -- [#5423](https://github.com/facebook/docusaurus/pull/5423) docs: clarify using custom attributes for navbar link ([@lex111](https://github.com/lex111)) -- [#5421](https://github.com/facebook/docusaurus/pull/5421) docs: add Indent to showcase ([@fouad](https://github.com/fouad)) -- [#5405](https://github.com/facebook/docusaurus/pull/5405) docs: add Gotenberg to showcase ([@gulien](https://github.com/gulien)) -- [#5406](https://github.com/facebook/docusaurus/pull/5406) docs: specify proper min Node.js version for Travis CI example ([@BattleOfPlassey](https://github.com/BattleOfPlassey)) -- [#5390](https://github.com/facebook/docusaurus/pull/5390) docs(v2): showcase BoxyHQ ([@deepakprabhakara](https://github.com/deepakprabhakara)) -- [#5376](https://github.com/facebook/docusaurus/pull/5376) docs(v2): Update Datagit site to showcase page ([@massoudmaboudi](https://github.com/massoudmaboudi)) -- [#5372](https://github.com/facebook/docusaurus/pull/5372) docs: remove docusaurus-preset-name from preset doc ([@slorber](https://github.com/slorber)) -- [#5366](https://github.com/facebook/docusaurus/pull/5366) docs: Add drayman to showcase ([@jansivans](https://github.com/jansivans)) -- [#5369](https://github.com/facebook/docusaurus/pull/5369) docs(v2): Add Nocalhost website to showcase page ([@neaped](https://github.com/neaped)) -- [#5351](https://github.com/facebook/docusaurus/pull/5351) docs(website): bump announcement bar + include Twitter link + refactor site colors ([@slorber](https://github.com/slorber)) -- [#5352](https://github.com/facebook/docusaurus/pull/5352) docs: update `docusaurus-plugin-sass` instructions ([@erickzhao](https://github.com/erickzhao)) -- [#5332](https://github.com/facebook/docusaurus/pull/5332) docs(v2): add mdx-mermaid to resources ([@sjwall](https://github.com/sjwall)) -- [#5331](https://github.com/facebook/docusaurus/pull/5331) docs: Changelog page should display TOC with releases ([@slorber](https://github.com/slorber)) -- [#5329](https://github.com/facebook/docusaurus/pull/5329) docs: add Haochen to showcase page ([@HaochenQ](https://github.com/HaochenQ)) -- [#5313](https://github.com/facebook/docusaurus/pull/5313) docs: try to make plugin/preset config less confusing ([@slorber](https://github.com/slorber)) -- [#5296](https://github.com/facebook/docusaurus/pull/5296) docs: update canary doc ([@slorber](https://github.com/slorber)) -- [#5219](https://github.com/facebook/docusaurus/pull/5219) docs: refactor API documentation ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#5271](https://github.com/facebook/docusaurus/pull/5271) Add Plausible Analytics docs to showcase page ([@metmarkosaric](https://github.com/metmarkosaric)) -- [#5283](https://github.com/facebook/docusaurus/pull/5283) docs: fix broken link to syncing tab choices section ([@lex111](https://github.com/lex111)) -- [#5259](https://github.com/facebook/docusaurus/pull/5259) docs(v2): update Remotion website picture in showcase ([@JonnyBurger](https://github.com/JonnyBurger)) -- [#5260](https://github.com/facebook/docusaurus/pull/5260) docs(v2): add Dart Code Metrics site to showcase page ([@incendial](https://github.com/incendial)) -- [#5253](https://github.com/facebook/docusaurus/pull/5253) docs: Fix typo `2-resources.md` ([@forresst](https://github.com/forresst)) -- [#5248](https://github.com/facebook/docusaurus/pull/5248) docs(v2): add docusaurus-prince-pdf to resources ([@sparanoid](https://github.com/sparanoid)) -- [#5239](https://github.com/facebook/docusaurus/pull/5239) docs(v2): Add unmand site to showcase page ([@dbseal](https://github.com/dbseal)) - -#### :house: Internal - -- Other - - [#5397](https://github.com/facebook/docusaurus/pull/5397) chore: rename docusaurus-2-website package + refactor scripts ([@slorber](https://github.com/slorber)) - - [#5342](https://github.com/facebook/docusaurus/pull/5342) chore: fix e2e yarn berry tests ([@slorber](https://github.com/slorber)) - - [#5328](https://github.com/facebook/docusaurus/pull/5328) refactor(website): convert website to TypeScript ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5336](https://github.com/facebook/docusaurus/pull/5336) chore: bump url-parse from 1.5.1 to 1.5.3 ([@dependabot[bot]](https://github.com/apps/dependabot)) - - [#5312](https://github.com/facebook/docusaurus/pull/5312) fix: fix changelog page mdx import for i18n ([@slorber](https://github.com/slorber)) - - [#5295](https://github.com/facebook/docusaurus/pull/5295) fix: fix canary release versions ([@slorber](https://github.com/slorber)) - - [#5285](https://github.com/facebook/docusaurus/pull/5285) fix: fix canary version names ([@slorber](https://github.com/slorber)) - - [#5269](https://github.com/facebook/docusaurus/pull/5269) misc: enable pt-BR + archive older versions ([@slorber](https://github.com/slorber)) - - [#5237](https://github.com/facebook/docusaurus/pull/5237) chore: enable pt-BR i18n locale on staging ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-migrate`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus` - - [#5345](https://github.com/facebook/docusaurus/pull/5345) refactor: rename Git master branch to main ([@zpao](https://github.com/zpao)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5341](https://github.com/facebook/docusaurus/pull/5341) polish: bind key listener to light/dark toggle + a11y lint fixes ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus` - - [#5347](https://github.com/facebook/docusaurus/pull/5347) chore(mdx-loader): migrate package to TypeScript ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus` - - [#5335](https://github.com/facebook/docusaurus/pull/5335) refactor: better typing + remove unnecessary eslint-disable ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-blog` - - [#5338](https://github.com/facebook/docusaurus/pull/5338) refactor(plugin-blog): style improvements in blogUtils ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic` - - [#5256](https://github.com/facebook/docusaurus/pull/5256) chore: upgrade Infima to alpha.30 ([@lex111](https://github.com/lex111)) -- `docusaurus-init` - - [#5315](https://github.com/facebook/docusaurus/pull/5315) refactor(init): share common files between templates ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5284](https://github.com/facebook/docusaurus/pull/5284) refactor: properly type docs version ([@Josh-Cena](https://github.com/Josh-Cena)) - -#### :running_woman: Performance - -- `docusaurus-module-type-aliases`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-types`, `docusaurus` - - [#5349](https://github.com/facebook/docusaurus/pull/5349) refactor(core): replace useDocusaurusContext().isClient by useIsBrowser() ([@slorber](https://github.com/slorber)) - -#### Committers: 27 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- David Seal ([@dbseal](https://github.com/dbseal)) -- Deepak Prabhakara ([@deepakprabhakara](https://github.com/deepakprabhakara)) -- Dmitry Zhifarsky ([@incendial](https://github.com/incendial)) -- Erick Zhao ([@erickzhao](https://github.com/erickzhao)) -- Federico Aloi ([@faloi](https://github.com/faloi)) -- Forresst ([@forresst](https://github.com/forresst)) -- Fouad Matin ([@fouad](https://github.com/fouad)) -- Garry ([@neaped](https://github.com/neaped)) -- Hamza Hamidi ([@hamzahamidi](https://github.com/hamzahamidi)) -- Isaac Philip ([@isaac-philip](https://github.com/isaac-philip)) -- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) -- Jonny Burger ([@JonnyBurger](https://github.com/JonnyBurger)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Julien Neuhart ([@gulien](https://github.com/gulien)) -- Marko Saric ([@metmarkosaric](https://github.com/metmarkosaric)) -- Massoud Maboudi ([@massoudmaboudi](https://github.com/massoudmaboudi)) -- Michal Sänger ([@michalsanger](https://github.com/michalsanger)) -- Palash Shrivastava ([@BattleOfPlassey](https://github.com/BattleOfPlassey)) -- Paul O’Shannessy ([@zpao](https://github.com/zpao)) -- Pierre-Gilles Leymarie ([@Pierre-Gilles](https://github.com/Pierre-Gilles)) -- Sam Wall ([@sjwall](https://github.com/sjwall)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tunghsiao Liu ([@sparanoid](https://github.com/sparanoid)) -- Yan Ivan Evdokimov ([@jansivans](https://github.com/jansivans)) -- [@HaochenQ](https://github.com/HaochenQ) -- wan-nyan-wan ([@wan-nyan-wan](https://github.com/wan-nyan-wan)) - -## 2.0.0-beta.4 (2021-07-28) - -#### :rocket: New Feature - -- `docusaurus-theme-classic` - - [#4912](https://github.com/facebook/docusaurus/pull/4912) feat(v2): add back to top button ([@lex111](https://github.com/lex111)) -- `docusaurus-init` - - [#5235](https://github.com/facebook/docusaurus/pull/5235) feat: docusaurus.new + improve StackBlitz playground integration ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5203](https://github.com/facebook/docusaurus/pull/5203) feat: docs plugin options sidebarCollapsible + sidebarCollapsed ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus` - - [#5207](https://github.com/facebook/docusaurus/pull/5207) feat: multiple playground choices ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus` - - [#4273](https://github.com/facebook/docusaurus/pull/4273) feat(v2): redesign mobile UX: inline TOC + doc sidebar in main menu ([@lex111](https://github.com/lex111)) - -#### :boom: Breaking Change - -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5203](https://github.com/facebook/docusaurus/pull/5203) feat: docs plugin options sidebarCollapsible + sidebarCollapsed ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils`, `docusaurus` - - [#5173](https://github.com/facebook/docusaurus/pull/5173) feat(v2): generalize usage of \_ prefix convention to exclude content files/folders ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus` - - [#4273](https://github.com/facebook/docusaurus/pull/4273) feat(v2): redesign mobile UX: inline TOC + doc sidebar in main menu ([@lex111](https://github.com/lex111)) - -#### :bug: Bug Fix - -- `docusaurus-plugin-content-blog` - - [#5232](https://github.com/facebook/docusaurus/pull/5232) fix(v2): blog should parse frontMatter.date even when time is present ([@wenerme](https://github.com/wenerme)) -- `docusaurus-theme-classic` - - [#5230](https://github.com/facebook/docusaurus/pull/5230) fix(v2): remove top margin from first element inside doc article ([@lex111](https://github.com/lex111)) - - [#5229](https://github.com/facebook/docusaurus/pull/5229) fix(v2): keep mobile TOC after hydration ([@lex111](https://github.com/lex111)) - - [#5179](https://github.com/facebook/docusaurus/pull/5179) fix(v2): wrap dropdown item to missing li element + remove extra attributes ([@lex111](https://github.com/lex111)) - - [#5183](https://github.com/facebook/docusaurus/pull/5183) fix(v2): pass all props to CodeBlock component ([@lex111](https://github.com/lex111)) - - [#5176](https://github.com/facebook/docusaurus/pull/5176) fix(v2): Fix type for navlink label ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5172](https://github.com/facebook/docusaurus/pull/5172) fix(v2): hide mobile collapsible doc toc if no headings ([@slorber](https://github.com/slorber)) - - [#5161](https://github.com/facebook/docusaurus/pull/5161) fix(v2): disable default behavior when click on collapsible item ([@lex111](https://github.com/lex111)) - - [#5151](https://github.com/facebook/docusaurus/pull/5151) fix(v2): add missing french translations for mobile ([@forresst](https://github.com/forresst)) - - [#5104](https://github.com/facebook/docusaurus/pull/5104) fix(v2): fix SkipToContent programmatic focus when updating querystring ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-search-algolia` - - [#5214](https://github.com/facebook/docusaurus/pull/5214) fix: upgrade Docsearch to avoid layout shift ([@slorber](https://github.com/slorber)) - - [#5135](https://github.com/facebook/docusaurus/pull/5135) chore(v2): update @docsearch/react ([@shortcuts](https://github.com/shortcuts)) -- `docusaurus` - - [#5204](https://github.com/facebook/docusaurus/pull/5204) fix: cli upgrade helper fail when no `package.dependencies` ([@mweststrate](https://github.com/mweststrate)) - - [#5164](https://github.com/facebook/docusaurus/pull/5164) fix(v2): revert webpack.resolve.symlinks = false ([@slorber](https://github.com/slorber)) - - [#5126](https://github.com/facebook/docusaurus/pull/5126) fix(v2): remove webpackConfig.resolve.symlinks: true ([@slorber](https://github.com/slorber)) - - [#5110](https://github.com/facebook/docusaurus/pull/5110) fix(v2): Fix update-notifier not run at first and not notifying consistently ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils` - - [#5199](https://github.com/facebook/docusaurus/pull/5199) fix(v2): Fix MDX docs being considered as partials when siteDir match the \_ prefix convention ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-pwa` - - [#5185](https://github.com/facebook/docusaurus/pull/5185) fix(v2): add base URL to content attribute of head tags PWA ([@lex111](https://github.com/lex111)) - - [#5169](https://github.com/facebook/docusaurus/pull/5169) refactor(v2): automatically add base URL to PWA head tags ([@lex111](https://github.com/lex111)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils`, `docusaurus` - - [#5173](https://github.com/facebook/docusaurus/pull/5173) feat(v2): generalize usage of \_ prefix convention to exclude content files/folders ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-common` - - [#5159](https://github.com/facebook/docusaurus/pull/5159) fix(v2): Fix Collapsible hydration layout shift ([@slorber](https://github.com/slorber)) - - [#5146](https://github.com/facebook/docusaurus/pull/5146) fix(v2): improve work of useCollapsible hook with multiple clicks ([@lex111](https://github.com/lex111)) -- `docusaurus-types` - - [#5129](https://github.com/facebook/docusaurus/pull/5129) fix(v2): fix d.ts lint error ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5116](https://github.com/facebook/docusaurus/pull/5116) fix(v2): introduce useCollapsible to fix collapsible animation perf issues ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-client-redirects` - - [#5102](https://github.com/facebook/docusaurus/pull/5102) fix(v2): fix redirect plugin when trailingSlash=false for .html extension ([@slorber](https://github.com/slorber)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#5228](https://github.com/facebook/docusaurus/pull/5228) refactor(v2): fix small typo in Russian translation ([@antonvasilev52](https://github.com/antonvasilev52)) - - [#5222](https://github.com/facebook/docusaurus/pull/5222) chore(v2): update Infima to alpha 28 ([@lex111](https://github.com/lex111)) - - [#5224](https://github.com/facebook/docusaurus/pull/5224) refactor(v2): update Russian translation ([@lex111](https://github.com/lex111)) - - [#5217](https://github.com/facebook/docusaurus/pull/5217) refactor(v2): improved Farsi default translations ([@massoudmaboudi](https://github.com/massoudmaboudi)) - - [#5171](https://github.com/facebook/docusaurus/pull/5171) refactor(v2): increase content area if blog sidebar is off ([@lex111](https://github.com/lex111)) - - [#5154](https://github.com/facebook/docusaurus/pull/5154) refactor(v2): Hindi translation for semantic doc sidebar ([@pranabdas](https://github.com/pranabdas)) - - [#5145](https://github.com/facebook/docusaurus/pull/5145) refactor(v2): use Collapsible for mobile nav items ([@lex111](https://github.com/lex111)) - - [#5138](https://github.com/facebook/docusaurus/pull/5138) refactor(v2): Update Hebrew translations ([@nirtamir2](https://github.com/nirtamir2)) - - [#5140](https://github.com/facebook/docusaurus/pull/5140) refactor(v2): bn translation improvements for semantic doc sidebar ([@pranabdas](https://github.com/pranabdas)) - - [#5139](https://github.com/facebook/docusaurus/pull/5139) feat(v2): complete Chinese code translations ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5118](https://github.com/facebook/docusaurus/pull/5118) refactor(v2): pt-BR translations improve semantic doc sidebar and tags ([@marssaljr](https://github.com/marssaljr)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#5215](https://github.com/facebook/docusaurus/pull/5215) refactor: make code block shadows consistent with new admonitions ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic` - - [#5193](https://github.com/facebook/docusaurus/pull/5193) refactor: redesign admonitions/callouts/quotes ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5168](https://github.com/facebook/docusaurus/pull/5168) refactor(v2): mobile dropdown navbar: expand when subitem become active ([@slorber](https://github.com/slorber)) - -#### :memo: Documentation - -- [#5236](https://github.com/facebook/docusaurus/pull/5236) docs: add Verdaccio.org to showcase ([@semoal](https://github.com/semoal)) -- [#5218](https://github.com/facebook/docusaurus/pull/5218) docs(v2): remove vector.dev from showcase ([@lex111](https://github.com/lex111)) -- [#5212](https://github.com/facebook/docusaurus/pull/5212) docs: mention Link can be used for external links ([@slorber](https://github.com/slorber)) -- [#5210](https://github.com/facebook/docusaurus/pull/5210) docs(v2): Elaboration of raw-loader in markdown react component ([@pranabdas](https://github.com/pranabdas)) -- [#5191](https://github.com/facebook/docusaurus/pull/5191) docs: user should restart docusaurus after adding prism additionalLanguage ([@tohidnateghi](https://github.com/tohidnateghi)) -- [#5175](https://github.com/facebook/docusaurus/pull/5175) docs: update API docs on navbar behavior ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#5189](https://github.com/facebook/docusaurus/pull/5189) docs(v2): Add orbitjs site to showcase page ([@dgeb](https://github.com/dgeb)) -- [#5177](https://github.com/facebook/docusaurus/pull/5177) docs(v2): add easyjwt to users ([@dbrrt](https://github.com/dbrrt)) -- [#5187](https://github.com/facebook/docusaurus/pull/5187) docs(v2): Add quickwit to user.js and png. ([@fmassot](https://github.com/fmassot)) -- [#5184](https://github.com/facebook/docusaurus/pull/5184) docs(v2): Add react-complex-tree to users.js ([@lukasbach](https://github.com/lukasbach)) -- [#5178](https://github.com/facebook/docusaurus/pull/5178) docs(v2): Update tutorial link ([@slorber](https://github.com/slorber)) -- [#5158](https://github.com/facebook/docusaurus/pull/5158) docs(v2): Update deploy with Qovery docs for V2 ([@arnaudjnn](https://github.com/arnaudjnn)) -- [#5152](https://github.com/facebook/docusaurus/pull/5152) docs(v2): Indent code example to improve readability ([@rluvaton](https://github.com/rluvaton)) -- [#5133](https://github.com/facebook/docusaurus/pull/5133) docs(v2): GIF format is not suported ([@NazarStreletskyi](https://github.com/NazarStreletskyi)) -- [#5117](https://github.com/facebook/docusaurus/pull/5117) docs(v2): Add Prismatic docs page to showcase. ([@taylorreece](https://github.com/taylorreece)) -- [#5115](https://github.com/facebook/docusaurus/pull/5115) docs(v2): Add LiveKit to showcase ([@davidzhao](https://github.com/davidzhao)) -- [#5114](https://github.com/facebook/docusaurus/pull/5114) docs(v2): add Blink Shell Documentation to Showcase ([@pcho](https://github.com/pcho)) -- [#5112](https://github.com/facebook/docusaurus/pull/5112) docs(v2): clarify how to disable edit links entirely ([@lennartkoopmann](https://github.com/lennartkoopmann)) -- [#5113](https://github.com/facebook/docusaurus/pull/5113) docs(v2): Add CryptoDevHub to Showcase ([@pmuens](https://github.com/pmuens)) - -#### :house: Internal - -- `docusaurus-theme-classic` - - [#5234](https://github.com/facebook/docusaurus/pull/5234) chore: Upgrade infima 29 ([@slorber](https://github.com/slorber)) - - [#5130](https://github.com/facebook/docusaurus/pull/5130) test(v2): dogfooding: add huge sidebar for testing purposes ([@slorber](https://github.com/slorber)) -- Other - - [#5223](https://github.com/facebook/docusaurus/pull/5223) chore: fix iframe background color in dark mode ([@lex111](https://github.com/lex111)) - - [#5206](https://github.com/facebook/docusaurus/pull/5206) misc: add script to keep starters branch/repos up-to-date ([@slorber](https://github.com/slorber)) - - [#5167](https://github.com/facebook/docusaurus/pull/5167) fix(v2): fix website PWA icon hrefs ([@slorber](https://github.com/slorber)) - - [#5166](https://github.com/facebook/docusaurus/pull/5166) fix(v2): fix yarn clear command ([@slorber](https://github.com/slorber)) - - [#5137](https://github.com/facebook/docusaurus/pull/5137) chore: upgrade crowdin ([@slorber](https://github.com/slorber)) - - [#5111](https://github.com/facebook/docusaurus/pull/5111) misc: monitor site global data with build size bot ([@slorber](https://github.com/slorber)) - -#### :running_woman: Performance - -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5136](https://github.com/facebook/docusaurus/pull/5136) perf(v2): lazy sidebar categories / collapsibles, reduce html output / build times ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#5130](https://github.com/facebook/docusaurus/pull/5130) test(v2): dogfooding: add huge sidebar for testing purposes ([@slorber](https://github.com/slorber)) - -#### Committers: 28 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Arijit Kundu ([@covalentbond](https://github.com/covalentbond)) -- Arnaud Jeannin ([@arnaudjnn](https://github.com/arnaudjnn)) -- Christian Flach ([@cmfcmf](https://github.com/cmfcmf)) -- Clément Vannicatte ([@shortcuts](https://github.com/shortcuts)) -- Dan Gebhardt ([@dgeb](https://github.com/dgeb)) -- David Barrat ([@dbrrt](https://github.com/dbrrt)) -- David Zhao ([@davidzhao](https://github.com/davidzhao)) -- Forresst ([@forresst](https://github.com/forresst)) -- François Massot ([@fmassot](https://github.com/fmassot)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Lennart Koopmann ([@lennartkoopmann](https://github.com/lennartkoopmann)) -- Lukas Bach ([@lukasbach](https://github.com/lukasbach)) -- Marçal Junior ([@marssaljr](https://github.com/marssaljr)) -- Massoud Maboudi ([@massoudmaboudi](https://github.com/massoudmaboudi)) -- Michel Weststrate ([@mweststrate](https://github.com/mweststrate)) -- Nazar ([@NazarStreletskyi](https://github.com/NazarStreletskyi)) -- Philipp Muens ([@pmuens](https://github.com/pmuens)) -- Pranab Das ([@pranabdas](https://github.com/pranabdas)) -- Przemysław Chojecki ([@pcho](https://github.com/pcho)) -- Raz Luvaton ([@rluvaton](https://github.com/rluvaton)) -- Sergio Moreno ([@semoal](https://github.com/semoal)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Taylor Reece ([@taylorreece](https://github.com/taylorreece)) -- [@antonvasilev52](https://github.com/antonvasilev52) -- [@nirtamir2](https://github.com/nirtamir2) -- tohid nateghi ([@tohidnateghi](https://github.com/tohidnateghi)) -- 陈杨文 ([@wenerme](https://github.com/wenerme)) - -## 2.0.0-beta.3 (2021-06-30) - -#### :rocket: New Feature - -- `docusaurus-theme-classic` - - [#5092](https://github.com/facebook/docusaurus/pull/5092) feat(v2): add icon to external footer links ([@lex111](https://github.com/lex111)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#5080](https://github.com/facebook/docusaurus/pull/5080) fix(v2): classic theme - semantic correct anchors links ([@AuHau](https://github.com/AuHau)) - - [#5081](https://github.com/facebook/docusaurus/pull/5081) fix(v2): restore previous scroll position on back button click ([@lex111](https://github.com/lex111)) - - [#5063](https://github.com/facebook/docusaurus/pull/5063) fix(v2): restore responsive menu ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#5094](https://github.com/facebook/docusaurus/pull/5094) fix(v2): fix typos in swizzle command ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#5095](https://github.com/facebook/docusaurus/pull/5095) fix(v2): fix swizzle readComponent ([@slorber](https://github.com/slorber)) - - [#5059](https://github.com/facebook/docusaurus/pull/5059) fix(v2): fix webpack SSG plugin error thrown due to new URL() / \_\_filename ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs` - - [#5097](https://github.com/facebook/docusaurus/pull/5097) fix(v2): fix useEffect infinite loop in blogOnly mode ([@slorber](https://github.com/slorber)) - - [#5074](https://github.com/facebook/docusaurus/pull/5074) fix(v2): allow negative sidebar positions ([@kdrag0n](https://github.com/kdrag0n)) -- `docusaurus-plugin-client-redirects` - - [#5093](https://github.com/facebook/docusaurus/pull/5093) fix(v2): redirect from should work with trailingSlash: true ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects`, `docusaurus-utils` - - [#5085](https://github.com/facebook/docusaurus/pull/5085) fix(v2): redirect plugin should emit redirect files with lower precedence than redirect target ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-sitemap`, `docusaurus-types`, `docusaurus-utils-common`, `docusaurus` - - [#5082](https://github.com/facebook/docusaurus/pull/5082) fix(v2): never remove trailing slash from site root like '/baseUrl/' ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-sitemap` - - [#5068](https://github.com/facebook/docusaurus/pull/5068) fix(v2): sitemap should respect the global trailingSlash config option. ([@taylorreece](https://github.com/taylorreece)) -- `docusaurus-types` - - [#5058](https://github.com/facebook/docusaurus/pull/5058) fix(v2): fix bad @docusaurus/types Plugin type generics ([@jsamr](https://github.com/jsamr)) - -#### :memo: Documentation - -- [#5064](https://github.com/facebook/docusaurus/pull/5064) docs(v2): Rewrite markdown images section ([@ramiy](https://github.com/ramiy)) -- [#5086](https://github.com/facebook/docusaurus/pull/5086) docs(v2): Add SQL Frames to the showcase ([@dirslashls](https://github.com/dirslashls)) -- [#5073](https://github.com/facebook/docusaurus/pull/5073) docs(v2): update installation docs ([@iamayushdas](https://github.com/iamayushdas)) -- [#5061](https://github.com/facebook/docusaurus/pull/5061) docs(v2:) Divide `markdown-features/code-blocks` to smaller sections ([@ramiy](https://github.com/ramiy)) -- [#5066](https://github.com/facebook/docusaurus/pull/5066) docs(v2): correct typo ([@bperlmutter](https://github.com/bperlmutter)) - -#### :house: Internal - -- `docusaurus-types` - - [#5067](https://github.com/facebook/docusaurus/pull/5067) chore: unstable yarn.lock ([@slorber](https://github.com/slorber)) -- Other - - [#5057](https://github.com/facebook/docusaurus/pull/5057) chore(v2): upgrade examples to beta.2 ([@slorber](https://github.com/slorber)) - -#### Committers: 11 - -- Adam Uhlíř ([@AuHau](https://github.com/AuHau)) -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Ayush das ([@iamayushdas](https://github.com/iamayushdas)) -- Danny Lin ([@kdrag0n](https://github.com/kdrag0n)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Jules Sam. Randolph ([@jsamr](https://github.com/jsamr)) -- Rami Yushuvaev ([@ramiy](https://github.com/ramiy)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Taylor Reece ([@taylorreece](https://github.com/taylorreece)) -- [@bperlmutter](https://github.com/bperlmutter) -- [@dirslashls](https://github.com/dirslashls) - -## 2.0.0-beta.2 (2021-06-24) - -#### :rocket: New Feature - -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#5052](https://github.com/facebook/docusaurus/pull/5052) feat(v2): docs version banner configuration option ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` - - [#5037](https://github.com/facebook/docusaurus/pull/5037) feat(v2): plugins injectHtmlTags + configureWebpack should receive content loaded ([@slorber](https://github.com/slorber)) - -#### :boom: Breaking Change - -- `docusaurus-plugin-content-docs` - - [#5053](https://github.com/facebook/docusaurus/pull/5053) refactor(v2): remove deprecated docs option excludeNextVersionDocs ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#5052](https://github.com/facebook/docusaurus/pull/5052) feat(v2): docs version banner configuration option ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus-plugin-content-blog`, `docusaurus-types`, `docusaurus` - - [#5054](https://github.com/facebook/docusaurus/pull/5054) fix(v2): allow undefined favicon ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs` - - [#5048](https://github.com/facebook/docusaurus/pull/5048) fix(v2): read last update from inner git repositories ([@felipecrs](https://github.com/felipecrs)) -- `docusaurus-theme-classic` - - [#5050](https://github.com/facebook/docusaurus/pull/5050) fix(v2): add shadow to skip link on focus only ([@lex111](https://github.com/lex111)) - - [#5035](https://github.com/facebook/docusaurus/pull/5035) fix(v2): fix some docs container/sidebar layout issues ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` - - [#5047](https://github.com/facebook/docusaurus/pull/5047) fix(v2): Fix Webpack persistent caching (evict on swizzle/alias/config change) ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5040](https://github.com/facebook/docusaurus/pull/5040) fix(v2): Fix announcementBar layout shifts ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#5034](https://github.com/facebook/docusaurus/pull/5034) fix(v2): dev css modules classnames should include filename ([@slorber](https://github.com/slorber)) - - [#5016](https://github.com/facebook/docusaurus/pull/5016) fix(v2): add missing quote in build command output ([@manuelmeurer](https://github.com/manuelmeurer)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#5023](https://github.com/facebook/docusaurus/pull/5023) fix(v2): ignore hash changes in useChangeRoute hook ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils-validation` - - [#5032](https://github.com/facebook/docusaurus/pull/5032) fix(v2): less strict blog/docs uri frontmatter validation ([@slorber](https://github.com/slorber)) - -#### :nail_care: Polish - -- `docusaurus-plugin-content-docs` - - [#5053](https://github.com/facebook/docusaurus/pull/5053) refactor(v2): remove deprecated docs option excludeNextVersionDocs ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#4993](https://github.com/facebook/docusaurus/pull/4993) style(v2): reduce number of ESLint warnings ([@Josh-Cena](https://github.com/Josh-Cena)) -- Other - - [#5017](https://github.com/facebook/docusaurus/pull/5017) chore(v2): remove badge for v1 tests ([@loozhengyuan](https://github.com/loozhengyuan)) - -#### :memo: Documentation - -- Other - - [#5049](https://github.com/facebook/docusaurus/pull/5049) docs(v2): Fix Gatsby theme name for docs site - Docz ([@ramiy](https://github.com/ramiy)) - - [#5030](https://github.com/facebook/docusaurus/pull/5030) docs(v2): typo in deployment.mdx ([@eshantri](https://github.com/eshantri)) - - [#5022](https://github.com/facebook/docusaurus/pull/5022) docs(v2): Add React Native Render HTML site to showcase page ([@jsamr](https://github.com/jsamr)) - - [#5027](https://github.com/facebook/docusaurus/pull/5027) docs(v2): Add Buddy to deployment doc ([@tomekpapiernik](https://github.com/tomekpapiernik)) - - [#5021](https://github.com/facebook/docusaurus/pull/5021) docs(v2): fix incorrect anchor links in website ([@teikjun](https://github.com/teikjun)) - - [#5007](https://github.com/facebook/docusaurus/pull/5007) docs(v2): wrap mdx usage in mdx-code-block ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#5033](https://github.com/facebook/docusaurus/pull/5033) docs(v2): GH pages: recommend using trailingSlash ([@slorber](https://github.com/slorber)) - -#### :house: Internal - -- [#5005](https://github.com/facebook/docusaurus/pull/5005) chore: add archived versions system + archive alpha.73-75 ([@slorber](https://github.com/slorber)) - -#### Committers: 11 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Eshan Tripathi ([@eshantri](https://github.com/eshantri)) -- Felipe Santos ([@felipecrs](https://github.com/felipecrs)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Jules Sam. Randolph ([@jsamr](https://github.com/jsamr)) -- Manuel Meurer ([@manuelmeurer](https://github.com/manuelmeurer)) -- Rami Yushuvaev ([@ramiy](https://github.com/ramiy)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Teik Jun ([@teikjun](https://github.com/teikjun)) -- Tomasz Papiernik ([@tomekpapiernik](https://github.com/tomekpapiernik)) -- ZhengYuan Loo ([@loozhengyuan](https://github.com/loozhengyuan)) - -## 2.0.0-beta.1 (2021-06-18) - -#### :rocket: New Feature - -- `docusaurus-plugin-content-docs` - - [#4982](https://github.com/facebook/docusaurus/pull/4982) feat(v2): add docs pagination_label frontmatter ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#4949](https://github.com/facebook/docusaurus/pull/4949) feat(v2): add icon to external navbar links ([@lex111](https://github.com/lex111)) - - [#4939](https://github.com/facebook/docusaurus/pull/4939) feat(v2): theme default translations Bengali ([@Neilblaze](https://github.com/Neilblaze)) - - [#4811](https://github.com/facebook/docusaurus/pull/4811) feat(v2): Add hebrew translations ([@slorber](https://github.com/slorber)) - - [#4798](https://github.com/facebook/docusaurus/pull/4798) feat(v2): add theme Danish translation ([@PsychTechApS](https://github.com/PsychTechApS)) -- `docusaurus-init` - - [#4968](https://github.com/facebook/docusaurus/pull/4968) feat(v2): add code block theming in init template ([@Josh-Cena](https://github.com/Josh-Cena)) -- `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#4908](https://github.com/facebook/docusaurus/pull/4908) feat(v2): add trailingSlash config option ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` - - [#4796](https://github.com/facebook/docusaurus/pull/4796) feat(v2): exhaustive docs frontmatter schema ([@nam-hle](https://github.com/nam-hle)) -- `docusaurus-types`, `docusaurus` - - [#4618](https://github.com/facebook/docusaurus/pull/4618) feat(v2): allow config plugins as functions or [function,options] ([@besemuna](https://github.com/besemuna)) -- `docusaurus-plugin-content-blog`, `docusaurus-utils-validation` - - [#4759](https://github.com/facebook/docusaurus/pull/4759) feat(v2): exhaustive BlogPostFrontMatter schema validation ([@nam-hle](https://github.com/nam-hle)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#5001](https://github.com/facebook/docusaurus/pull/5001) chore(v2): update Infima to alpha 26 ([@lex111](https://github.com/lex111)) - - [#4986](https://github.com/facebook/docusaurus/pull/4986) fix(v2): fix UX for docsVersionDropdown on mobile for single version ([@slorber](https://github.com/slorber)) - - [#4980](https://github.com/facebook/docusaurus/pull/4980) fix(v2): make proper data type for prependBaseUrlToHref field ([@lex111](https://github.com/lex111)) - - [#4943](https://github.com/facebook/docusaurus/pull/4943) fix(v2): improve accessibility of code blocks ([@lex111](https://github.com/lex111)) - - [#4917](https://github.com/facebook/docusaurus/pull/4917) fix(v2): tidy up Markdown page layout ([@lex111](https://github.com/lex111)) - - [#4906](https://github.com/facebook/docusaurus/pull/4906) fix(v2): fix minor a11y issues ([@lex111](https://github.com/lex111)) - - [#4900](https://github.com/facebook/docusaurus/pull/4900) fix(v2): adjust margin after content title ([@lex111](https://github.com/lex111)) - - [#4855](https://github.com/facebook/docusaurus/pull/4855) chore(v2): update infima to alpha 24 ([@lex111](https://github.com/lex111)) - - [#4819](https://github.com/facebook/docusaurus/pull/4819) fix(v2): Amend Hebrew translations ([@liorheber](https://github.com/liorheber)) - - [#4815](https://github.com/facebook/docusaurus/pull/4815) fix(v2): Fix Hebrew translations ([@nirtamir2](https://github.com/nirtamir2)) - - [#4792](https://github.com/facebook/docusaurus/pull/4792) fix(v2): fix minor a11y issue with headings ([@lex111](https://github.com/lex111)) - - [#4793](https://github.com/facebook/docusaurus/pull/4793) fix(v2): unbreak enhanced width of doc item wrapper ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-utils-common` - - [#5000](https://github.com/facebook/docusaurus/pull/5000) fix(v2): fix theme array deduplication bug ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects`, `docusaurus-utils-common`, `docusaurus-utils`, `docusaurus` - - [#4988](https://github.com/facebook/docusaurus/pull/4988) fix(v2): redirect plugin should use siteConfig.trailingSlash ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-blog` - - [#4983](https://github.com/facebook/docusaurus/pull/4983) fix(v2): always use UTC when dealing with blog dates ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#4962](https://github.com/facebook/docusaurus/pull/4962) fix(v2): respect base url in RSS feeds ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#4985](https://github.com/facebook/docusaurus/pull/4985) fix(v2): navbar doc item fallback: search doc in lastVersion ([@slorber](https://github.com/slorber)) -- `docusaurus-remark-plugin-npm2yarn` - - [#4964](https://github.com/facebook/docusaurus/pull/4964) fix(v2): avoid duplicated imports in npm2yarn plugin ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs` - - [#4970](https://github.com/facebook/docusaurus/pull/4970) fix(v2): sidebar_label should be used to compute next/previous button labels ([@slorber](https://github.com/slorber)) - - [#4861](https://github.com/facebook/docusaurus/pull/4861) fix(v2): allow relative sidebar path resolution in docs:version command ([@lex111](https://github.com/lex111)) - - [#4859](https://github.com/facebook/docusaurus/pull/4859) fix(v2): use frontmatter title at first for paginated links ([@lex111](https://github.com/lex111)) - - [#4775](https://github.com/facebook/docusaurus/pull/4775) fix(v2): improve dx sidebar config, ability to have no sidebars file ([@nam-hle](https://github.com/nam-hle)) -- `docusaurus-plugin-sitemap`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#4950](https://github.com/facebook/docusaurus/pull/4950) fix(v2): sitemap plugin should handle siteConfig.trailingSlash automatically ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#4924](https://github.com/facebook/docusaurus/pull/4924) fix(v2): respect baseUrl in serving command ([@lex111](https://github.com/lex111)) - - [#4935](https://github.com/facebook/docusaurus/pull/4935) fix(v2): render children in BrowserOnly after client is ready ([@lex111](https://github.com/lex111)) - - [#4894](https://github.com/facebook/docusaurus/pull/4894) fix(v2): escape HTML entities in user tags attributes ([@lex111](https://github.com/lex111)) - - [#4789](https://github.com/facebook/docusaurus/pull/4789) fix(v2): transpile libs with too recent syntax with babel ([@slorber](https://github.com/slorber)) - - [#4784](https://github.com/facebook/docusaurus/pull/4784) fix(v2): update notifier should never suggest to downgrade ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-utils` - - [#4882](https://github.com/facebook/docusaurus/pull/4882) fix(v2): fix contentTitle issues when markdown h1 title contains code blocks ([@slorber](https://github.com/slorber)) -- `docusaurus-utils` - - [#4862](https://github.com/facebook/docusaurus/pull/4862) fix(v2): remove Markdown heading id from excerpt ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#4871](https://github.com/facebook/docusaurus/pull/4871) fix(v2): unbreak adding of custom HTML metadatas ([@lex111](https://github.com/lex111)) - - [#4797](https://github.com/facebook/docusaurus/pull/4797) fix(v2): do not focus on skip link if page refreshed ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#4856](https://github.com/facebook/docusaurus/pull/4856) fix(v2): adjust padding when custom search box location ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock` - - [#4830](https://github.com/facebook/docusaurus/pull/4830) fix(v2): pin prism-react-renderer version to 1.1.1 ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-ideal-image`, `lqip-loader` - - [#4806](https://github.com/facebook/docusaurus/pull/4806) chore(v2): update sharp to 0.28.2 ([@lex111](https://github.com/lex111)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#4995](https://github.com/facebook/docusaurus/pull/4995) refactor(v2): reduce top padding in doc content container ([@lex111](https://github.com/lex111)) - - [#4918](https://github.com/facebook/docusaurus/pull/4918) refactor(v2): readjust footer of blog item ([@lex111](https://github.com/lex111)) - - [#4959](https://github.com/facebook/docusaurus/pull/4959) refactor(v2): minor cleanups ([@lex111](https://github.com/lex111)) - - [#4945](https://github.com/facebook/docusaurus/pull/4945) refactor(v2): remove extra padding from doc item container ([@lex111](https://github.com/lex111)) - - [#4940](https://github.com/facebook/docusaurus/pull/4940) refactor(v2): improve semantic doc sidebar markup ([@lex111](https://github.com/lex111)) - - [#4961](https://github.com/facebook/docusaurus/pull/4961) refactor(v2): improve semantic blog sidebar markup ([@lex111](https://github.com/lex111)) - - [#4903](https://github.com/facebook/docusaurus/pull/4903) refactor(v2): make doc item layout more semantic ([@lex111](https://github.com/lex111)) - - [#4877](https://github.com/facebook/docusaurus/pull/4877) refactor(v2): reduce vertical space in doc content container ([@lex111](https://github.com/lex111)) - - [#4914](https://github.com/facebook/docusaurus/pull/4914) refactor(v2): use SVG for external link icon ([@lex111](https://github.com/lex111)) - - [#4916](https://github.com/facebook/docusaurus/pull/4916) refactor(v2): replace strong with b in UI components ([@lex111](https://github.com/lex111)) - - [#4926](https://github.com/facebook/docusaurus/pull/4926) refactor(v2): hide decorative SVGs from screen readers ([@lex111](https://github.com/lex111)) - - [#4865](https://github.com/facebook/docusaurus/pull/4865) refactor(v2): make little better doc update block UI ([@lex111](https://github.com/lex111)) - - [#4795](https://github.com/facebook/docusaurus/pull/4795) refactor(v2): remove transition on body element ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` - - [#4989](https://github.com/facebook/docusaurus/pull/4989) refactor(v2): blog/docs: add more context in error messages ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#4979](https://github.com/facebook/docusaurus/pull/4979) refactor(v2): cleanup console output ([@lex111](https://github.com/lex111)) -- `docusaurus-utils-validation`, `docusaurus` - - [#4977](https://github.com/facebook/docusaurus/pull/4977) polish(v2): url-subpath config validation warning ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs` - - [#4969](https://github.com/facebook/docusaurus/pull/4969) refactor(v2): include path in error about non-existent ids ([@lex111](https://github.com/lex111)) - - [#4863](https://github.com/facebook/docusaurus/pull/4863) refactor(v2): remove sidebar_label filed from doc metadata file ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus` - - [#4907](https://github.com/facebook/docusaurus/pull/4907) refactor(v2): remove type attribute from link and script tags ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-search-algolia` - - [#4919](https://github.com/facebook/docusaurus/pull/4919) refactor(v2): improve markup and styling on search page ([@lex111](https://github.com/lex111)) - - [#4867](https://github.com/facebook/docusaurus/pull/4867) chore(v2): update @docsearch/react ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog` - - [#4905](https://github.com/facebook/docusaurus/pull/4905) refactor(v2): do not generate RSS files for empty feed ([@lex111](https://github.com/lex111)) - - [#4860](https://github.com/facebook/docusaurus/pull/4860) refactor(v2): use aliased path for blog list sidebar file ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#4870](https://github.com/facebook/docusaurus/pull/4870) refactor(v2): add exception handling if external command is fails ([@lex111](https://github.com/lex111)) - - [#4875](https://github.com/facebook/docusaurus/pull/4875) refactor(v2): make even better SSR error notify and add tip ([@lex111](https://github.com/lex111)) - - [#4866](https://github.com/facebook/docusaurus/pull/4866) refactor(v2): output URL to console only if it has changed ([@lex111](https://github.com/lex111)) -- `docusaurus-utils` - - [#4814](https://github.com/facebook/docusaurus/pull/4814) refactor(v2): purify normalizeUrl ([@nam-hle](https://github.com/nam-hle)) - -#### :memo: Documentation - -- Other - - [#4987](https://github.com/facebook/docusaurus/pull/4987) docs(v2): document canary releases ([@slorber](https://github.com/slorber)) - - [#4981](https://github.com/facebook/docusaurus/pull/4981) docs(v2): minor tweaks ([@lex111](https://github.com/lex111)) - - [#4976](https://github.com/facebook/docusaurus/pull/4976) docs(v2): mention to install the algolia package in search doc ([@slorber](https://github.com/slorber)) - - [#4953](https://github.com/facebook/docusaurus/pull/4953) docs(v2): add Flagsmith to showcase ([@dabeeeenster](https://github.com/dabeeeenster)) - - [#4942](https://github.com/facebook/docusaurus/pull/4942) docs(v2): add info about `DefaultValue` prop in `Tabs` ([@ArtFlag](https://github.com/ArtFlag)) - - [#4898](https://github.com/facebook/docusaurus/pull/4898) docs(v2): add ClarityChallenge to showcase ([@jonbarker68](https://github.com/jonbarker68)) - - [#4896](https://github.com/facebook/docusaurus/pull/4896) docs(v2): fix incorrect link to plugin-ideal-image ([@phwt](https://github.com/phwt)) - - [#4893](https://github.com/facebook/docusaurus/pull/4893) docs(v2): presets: fix typo in bootstrap preset ([@silva-nick](https://github.com/silva-nick)) - - [#4887](https://github.com/facebook/docusaurus/pull/4887) docs(v2): Add Aide Jeune website to Docusaurus site showcase ([@l0u1sg](https://github.com/l0u1sg)) - - [#4821](https://github.com/facebook/docusaurus/pull/4821) docs(v2): New doc page for math equations ([@pranabdas](https://github.com/pranabdas)) - - [#4885](https://github.com/facebook/docusaurus/pull/4885) docs(v2): v2 migration guide: mention Algolia config update ([@slorber](https://github.com/slorber)) - - [#4876](https://github.com/facebook/docusaurus/pull/4876) docs(v2): update steps in the github-actions section ([@wise-introvert](https://github.com/wise-introvert)) - - [#4880](https://github.com/facebook/docusaurus/pull/4880) docs(v2): grammar typo in migration-overview.md ([@jmazin](https://github.com/jmazin)) - - [#4879](https://github.com/facebook/docusaurus/pull/4879) docs(v2): Added FireCMS to the showcase ([@fgatti675](https://github.com/fgatti675)) - - [#4849](https://github.com/facebook/docusaurus/pull/4849) docs(v2): fix Java syntax highlight in website ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#4818](https://github.com/facebook/docusaurus/pull/4818) docs(v2): add mr-pdf to resources ([@antonygibbs](https://github.com/antonygibbs)) - - [#4835](https://github.com/facebook/docusaurus/pull/4835) docs(v2): fix grammar typo on Creating pages ([@Christopher-Hsieh](https://github.com/Christopher-Hsieh)) - - [#4837](https://github.com/facebook/docusaurus/pull/4837) docs(v2): fix missing closing bracket ([@pmqueiroz](https://github.com/pmqueiroz)) - - [#4820](https://github.com/facebook/docusaurus/pull/4820) docs(v2): Fix typo in doc: sidebar.md ([@pranabdas](https://github.com/pranabdas)) - - [#4813](https://github.com/facebook/docusaurus/pull/4813) docs(v2): fix css snipped with missing color ([@slorber](https://github.com/slorber)) - - [#4803](https://github.com/facebook/docusaurus/pull/4803) docs(v2): Add i18n tag and fix typo ([@HunteRoi](https://github.com/HunteRoi)) - - [#4786](https://github.com/facebook/docusaurus/pull/4786) docs(v2): Add tinaeldevresse.eu to Docusaurus' gallery ([@HunteRoi](https://github.com/HunteRoi)) - - [#4780](https://github.com/facebook/docusaurus/pull/4780) docs(v2): remove docs for alpha 71 + 72 ([@slorber](https://github.com/slorber)) - - [#4779](https://github.com/facebook/docusaurus/pull/4779) docs(v2): beta blog post edits ([@slorber](https://github.com/slorber)) -- `docusaurus-init` - - [#4973](https://github.com/facebook/docusaurus/pull/4973) docs(v2): replace `diff` codeblocks with line highlight ([@Josh-Cena](https://github.com/Josh-Cena)) - - [#4756](https://github.com/facebook/docusaurus/pull/4756) docs(v2): Docusaurus 2 beta blog post ([@slorber](https://github.com/slorber)) - -#### :house: Internal - -- Other - - [#4994](https://github.com/facebook/docusaurus/pull/4994) misc: more issue template improvements ([@slorber](https://github.com/slorber)) - - [#4951](https://github.com/facebook/docusaurus/pull/4951) misc: disable google-gtag plugin in Netlify deploys ([@lex111](https://github.com/lex111)) - - [#4901](https://github.com/facebook/docusaurus/pull/4901) misc: optimize showcase images ([@lex111](https://github.com/lex111)) - - [#4897](https://github.com/facebook/docusaurus/pull/4897) chore: fail CI if yarn.lock is modified on install ([@slorber](https://github.com/slorber)) - - [#4858](https://github.com/facebook/docusaurus/pull/4858) chore(v2): add external link to community sidebar ([@lex111](https://github.com/lex111)) - - [#4889](https://github.com/facebook/docusaurus/pull/4889) misc: issue template config typo ([@slorber](https://github.com/slorber)) - - [#4886](https://github.com/facebook/docusaurus/pull/4886) misc: add github issue template config ([@slorber](https://github.com/slorber)) - - [#4878](https://github.com/facebook/docusaurus/pull/4878) misc: improve bug report issue template ([@lex111](https://github.com/lex111)) - - [#4791](https://github.com/facebook/docusaurus/pull/4791) chore: fix canary version name ([@slorber](https://github.com/slorber)) - - [#4777](https://github.com/facebook/docusaurus/pull/4777) chore: regenerate examples on 2.0.0-beta.0 ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-migrate`, `docusaurus` - - [#4944](https://github.com/facebook/docusaurus/pull/4944) chore: lockfile cleanup ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x`, `docusaurus-init-1.x` - - [#4902](https://github.com/facebook/docusaurus/pull/4902) chore: remove docusaurus v1 from master branch (moved to docusaurus-v1 branch) ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-ideal-image` - - [#4915](https://github.com/facebook/docusaurus/pull/4915) chore(v2): bump react-waypoint from 9.0.2 to 10.1.0 ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock` - - [#4834](https://github.com/facebook/docusaurus/pull/4834) chore(v2): unlock prism-react-renderer version ([@lex111](https://github.com/lex111)) -- `docusaurus-cssnano-preset`, `docusaurus` - - [#4833](https://github.com/facebook/docusaurus/pull/4833) chore(v2): bump cssnano packages ([@lex111](https://github.com/lex111)) -- `docusaurus-cssnano-preset`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-debug`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#4816](https://github.com/facebook/docusaurus/pull/4816) chore(v2): upgrade dependencies ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#4790](https://github.com/facebook/docusaurus/pull/4790) chore(v2): TypeScript, use isolatedModules ([@slorber](https://github.com/slorber)) - -#### Committers: 31 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Arthur ([@ArtFlag](https://github.com/ArtFlag)) -- Ben Rometsch ([@dabeeeenster](https://github.com/dabeeeenster)) -- Christopher Hsieh ([@Christopher-Hsieh](https://github.com/Christopher-Hsieh)) -- Fardeen Panjwani ([@wise-introvert](https://github.com/wise-introvert)) -- Joel ([@Joelpo](https://github.com/Joelpo)) -- Jon Barker ([@jonbarker68](https://github.com/jonbarker68)) -- Jonathan Mazin ([@jmazin](https://github.com/jmazin)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Lior Heber ([@liorheber](https://github.com/liorheber)) -- Louis Gallet ([@l0u1sg](https://github.com/l0u1sg)) -- Louis Grenard ([@louistiti](https://github.com/louistiti)) -- Lucas Correia ([@tsirlucas](https://github.com/tsirlucas)) -- Nam Hoang Le ([@nam-hle](https://github.com/nam-hle)) -- Pablo Vidal ([@limkinZero](https://github.com/limkinZero)) -- Pedro Queiroz ([@pmqueiroz](https://github.com/pmqueiroz)) -- Pranab Das ([@pranabdas](https://github.com/pranabdas)) -- Pratyay Banerjee ([@Neilblaze](https://github.com/Neilblaze)) -- PsychTech ([@PsychTechApS](https://github.com/PsychTechApS)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tinaël Devresse ([@HunteRoi](https://github.com/HunteRoi)) -- [@Massibian](https://github.com/Massibian) -- [@antonygibbs](https://github.com/antonygibbs) -- [@besemuna](https://github.com/besemuna) -- [@e271828-](https://github.com/e271828-) -- [@fgatti675](https://github.com/fgatti675) -- [@nirtamir2](https://github.com/nirtamir2) -- [@silva-nick](https://github.com/silva-nick) -- mg ([@tiny-dancer](https://github.com/tiny-dancer)) -- phwt.smwt ([@phwt](https://github.com/phwt)) - -## 2.0.0-beta.0 (2021-05-12) - -Read the [2.0.0 beta blog post](https://docusaurus.io/blog/2021/05/12/announcing-docusaurus-two-beta)! - -**Note**: this first beta release does not contain any new major feature. We are removing the alpha label, as we are confident Docusaurus 2 is stable enough. - -#### :rocket: New Feature - -- `docusaurus-theme-classic` - - [#4762](https://github.com/facebook/docusaurus/pull/4762) feat(v2): add es translations for docusaurus-theme-classic ([@rodmoreno](https://github.com/rodmoreno)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#4750](https://github.com/facebook/docusaurus/pull/4750) fix(v2): improve french translation for theme-classic ([@forresst](https://github.com/forresst)) -- `docusaurus-mdx-loader`, `docusaurus-utils` - - [#4736](https://github.com/facebook/docusaurus/pull/4736) fix(v2): fix encoding of markdown image/file inline file-loaders ([@slorber](https://github.com/slorber)) -- `docusaurus-utils` - - [#4735](https://github.com/facebook/docusaurus/pull/4735) fix(v2): markdown title parser should ignore all forms of MDX import statements ([@nam-hle](https://github.com/nam-hle)) - - [#4729](https://github.com/facebook/docusaurus/pull/4729) fix(v2): optimize markdown parser regex (Closes [#4726](https://github.com/facebook/docusaurus/issues/4726)) ([@nam-hle](https://github.com/nam-hle)) - -#### :memo: Documentation - -- [#4770](https://github.com/facebook/docusaurus/pull/4770) docs(v2): Improve intro doc ([@slorber](https://github.com/slorber)) -- [#4773](https://github.com/facebook/docusaurus/pull/4773) docs(v2): fix i18n doc: bad i18n page plugin path in code sample ([@KostyaTretyak](https://github.com/KostyaTretyak)) -- [#4758](https://github.com/facebook/docusaurus/pull/4758) docs(v2): add browsers support documentation ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#4757](https://github.com/facebook/docusaurus/pull/4757) docs(v2): Add Netdata to showcase ([@joelhans](https://github.com/joelhans)) -- [#4754](https://github.com/facebook/docusaurus/pull/4754) docs(v2): fix Jest showcase screenshot ([@slorber](https://github.com/slorber)) -- [#4747](https://github.com/facebook/docusaurus/pull/4747) docs(v2): Update showcase page ([@slorber](https://github.com/slorber)) -- [#4734](https://github.com/facebook/docusaurus/pull/4734) docs(v2): Added MediaMachine.io to showcase ([@gianu](https://github.com/gianu)) -- [#4731](https://github.com/facebook/docusaurus/pull/4731) docs(v2): add CodeYourFuture to showcase ([@ChrisOwen101](https://github.com/ChrisOwen101)) -- [#4703](https://github.com/facebook/docusaurus/pull/4703) docs(v2): specify google-analytics and gtag plugins ([@yiliansource](https://github.com/yiliansource)) -- [#4727](https://github.com/facebook/docusaurus/pull/4727) docs(v2): fix doc lint ([@slorber](https://github.com/slorber)) -- [#4725](https://github.com/facebook/docusaurus/pull/4725) docs(v2): emphasize subset of markdown supported languages ([@Josh-Cena](https://github.com/Josh-Cena)) -- [#4711](https://github.com/facebook/docusaurus/pull/4711) docs(v2): showcase personal site evantay ([@DigiPie](https://github.com/DigiPie)) - -#### :house: Internal - -- [#4746](https://github.com/facebook/docusaurus/pull/4746) chore(v2): attempt to fix crowdin dl again ([@slorber](https://github.com/slorber)) -- [#4743](https://github.com/facebook/docusaurus/pull/4743) chore(v2): fix prod deployment due to bad image path ([@slorber](https://github.com/slorber)) -- [#4740](https://github.com/facebook/docusaurus/pull/4740) chore(v2): delay i18n-staging deployment to avoid Crowdin 409 errors ([@slorber](https://github.com/slorber)) -- [#4739](https://github.com/facebook/docusaurus/pull/4739) chore(v2): Fix Crowdin 409 issues in CI ([@slorber](https://github.com/slorber)) - -#### Committers: 11 - -- Chris Owen ([@ChrisOwen101](https://github.com/ChrisOwen101)) -- Evan ([@DigiPie](https://github.com/DigiPie)) -- Forresst ([@forresst](https://github.com/forresst)) -- Ian Hornik ([@yiliansource](https://github.com/yiliansource)) -- Joel Hans ([@joelhans](https://github.com/joelhans)) -- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) -- Nam Hoang Le ([@nam-hle](https://github.com/nam-hle)) -- Rodrigo Moreno ([@rodmoreno](https://github.com/rodmoreno)) -- Sergio Rafael Gianazza ([@gianu](https://github.com/gianu)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Костя Третяк ([@KostyaTretyak](https://github.com/KostyaTretyak)) - -## 2.0.0-alpha.75 (2021-04-30) - -#### :boom: Breaking Change - -- `docusaurus-cssnano-preset`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus`, `lqip-loader` - - [#4089](https://github.com/facebook/docusaurus/pull/4089) feat(v2): Webpack 5, PostCSS 8 ([@RDIL](https://github.com/RDIL)) - -#### :memo: Documentation - -- [#4704](https://github.com/facebook/docusaurus/pull/4704) docs(v2): showcase meli ([@gempain](https://github.com/gempain)) -- [#4699](https://github.com/facebook/docusaurus/pull/4699) docs(v2): Add Kosko to showcase ([@tommy351](https://github.com/tommy351)) - -#### Committers: 4 - -- Geoffroy Empain ([@gempain](https://github.com/gempain)) -- Reece Dunham ([@RDIL](https://github.com/RDIL)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tommy Chen ([@tommy351](https://github.com/tommy351)) - -## 2.0.0-alpha.74 (2021-04-27) - -#### :rocket: New Feature - -- Other - - [#4515](https://github.com/facebook/docusaurus/pull/4515) feat(v2): add tag filters to showcase page ([@lisa761](https://github.com/lisa761)) -- `docusaurus-plugin-content-docs` - - [#4658](https://github.com/facebook/docusaurus/pull/4658) feat(v2): allow user to customize/enhance the default sidebar items generator ([@slorber](https://github.com/slorber)) - - [#4655](https://github.com/facebook/docusaurus/pull/4655) feat(v2): docs, make numberPrefixParser configurable, better defaults, minor breaking-changes ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils`, `docusaurus` - - [#4688](https://github.com/facebook/docusaurus/pull/4688) fix(v2): fix title logic (meta vs heading) + ignore fixed anchor id syntax ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#4689](https://github.com/facebook/docusaurus/pull/4689) chore(v2): update infima to alpha 23 ([@slorber](https://github.com/slorber)) - - [#4667](https://github.com/facebook/docusaurus/pull/4667) fix(v2): Unbreak blog post title by handling title fallback in `LayoutHead` ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-plugin-content-docs` - - [#4687](https://github.com/facebook/docusaurus/pull/4687) fix(v2): accept empty/null custom_edit_url docs frontmatter for retrocompat ([@slorber](https://github.com/slorber)) - - [#4651](https://github.com/facebook/docusaurus/pull/4651) fix(v2): sidebar autogen from subfolder should read category metadata correctly ([@slorber](https://github.com/slorber)) - - [#4629](https://github.com/facebook/docusaurus/pull/4629) fix(v2): fix validation rejecting admonitions false ([@kazk](https://github.com/kazk)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils-validation` - - [#4654](https://github.com/facebook/docusaurus/pull/4654) fix(v2): fix too strict markdown frontmatter validation ([@johnnyreilly](https://github.com/johnnyreilly)) -- `docusaurus-utils` - - [#4646](https://github.com/facebook/docusaurus/pull/4646) fix(v2): ignore imports when h1 heading parsing ([@lex111](https://github.com/lex111)) - - [#4641](https://github.com/facebook/docusaurus/pull/4641) fix(v2): parse headings directly after h1 properly ([@lex111](https://github.com/lex111)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#4682](https://github.com/facebook/docusaurus/pull/4682) refactor(v2): align external icon on right ([@lex111](https://github.com/lex111)) - -#### :memo: Documentation - -- [#4496](https://github.com/facebook/docusaurus/pull/4496) docs(v2): Add Qovery to deployment doc ([@arnaudjnn](https://github.com/arnaudjnn)) -- [#4680](https://github.com/facebook/docusaurus/pull/4680) docs(v2): Fix urls in deployment.md ([@luism3861](https://github.com/luism3861)) -- [#4668](https://github.com/facebook/docusaurus/pull/4668) docs(v2): Add Hostman to deployment doc ([@alena-ko](https://github.com/alena-ko)) -- [#4676](https://github.com/facebook/docusaurus/pull/4676) docs(v2): Add Daily Digest - COVID-19 IN FRANCE to showcase ([@MisterFISHUP](https://github.com/MisterFISHUP)) -- [#4643](https://github.com/facebook/docusaurus/pull/4643) docs(v2): Fix typo in installation.md ([@react-learner](https://github.com/react-learner)) -- [#4649](https://github.com/facebook/docusaurus/pull/4649) docs(v2): Add new showcase user ([@JeremyDolle](https://github.com/JeremyDolle)) - -#### :house: Internal - -- Other - - [#4670](https://github.com/facebook/docusaurus/pull/4670) chore: add some redirects to v1.docusaurus.io ([@slorber](https://github.com/slorber)) -- `docusaurus-init` - - [#4631](https://github.com/facebook/docusaurus/pull/4631) chore(v2): update examples to use alpha73 ([@slorber](https://github.com/slorber)) - -#### Committers: 12 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Arnaud Jeannin ([@arnaudjnn](https://github.com/arnaudjnn)) -- DOLLE ([@JeremyDolle](https://github.com/JeremyDolle)) -- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) -- Lisa Chandra ([@lisa761](https://github.com/lisa761)) -- Luis Medina Huerta ([@luism3861](https://github.com/luism3861)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tommy ([@react-learner](https://github.com/react-learner)) -- [@MisterFISHUP](https://github.com/MisterFISHUP) -- [@alena-ko](https://github.com/alena-ko) -- kazk ([@kazk](https://github.com/kazk)) - -## 2.0.0-alpha.73 (2021-04-16) - -#### :rocket: New Feature - -- `docusaurus-theme-classic` - - [#4624](https://github.com/facebook/docusaurus/pull/4624) feat(v2): Add Filipino default translations to theme ([@gumacahin](https://github.com/gumacahin)) - - [#4596](https://github.com/facebook/docusaurus/pull/4596) feat(v2): theme default translations hindi ([@lisa761](https://github.com/lisa761)) - - [#4536](https://github.com/facebook/docusaurus/pull/4536) feat(v2): add pt-PT translations for docusaurus-theme-classic ([@tiago-rr](https://github.com/tiago-rr)) - - [#4525](https://github.com/facebook/docusaurus/pull/4525) feat(v2): add Brazilian Portuguese translation for docusaurus-theme-classic ([@thiagog3](https://github.com/thiagog3)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#4511](https://github.com/facebook/docusaurus/pull/4511) feat(v2): add unique page/wrapper className to each theme pages ([@ShinteiMai](https://github.com/ShinteiMai)) -- `docusaurus-init`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#4582](https://github.com/facebook/docusaurus/pull/4582) feat(v2): auto-generated sidebars, frontmatter-less sites ([@slorber](https://github.com/slorber)) -- `docusaurus-types`, `docusaurus` - - [#4545](https://github.com/facebook/docusaurus/pull/4545) feat(v2): docusaurus deploy: ability to configure port in git url ([@talesporto](https://github.com/talesporto)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils` - - [#4590](https://github.com/facebook/docusaurus/pull/4590) feat(v2): various markdown string parsing improvements/fixes ([@slorber](https://github.com/slorber)) - - [#4485](https://github.com/facebook/docusaurus/pull/4485) feat(v2): frontmatter-less: read first heading as title and use it in front-matter ([@armano2](https://github.com/armano2)) -- `docusaurus-utils` - - [#4581](https://github.com/facebook/docusaurus/pull/4581) feat(v2): default theme translations: locale "pt" should load "pt-BR" translations ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs` - - [#4495](https://github.com/facebook/docusaurus/pull/4495) feat(v2): include frontmatter in loadedContent doc metadatas ([@kaytwo](https://github.com/kaytwo)) - - [#4500](https://github.com/facebook/docusaurus/pull/4500) feat(v2): provide doc sidebar_label through sidebars.js ([@besemuna](https://github.com/besemuna)) -- `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#4449](https://github.com/facebook/docusaurus/pull/4449) feat(v2): infer default i18n locale config from locale code ([@slorber](https://github.com/slorber)) - -#### :boom: Breaking Change - -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#4619](https://github.com/facebook/docusaurus/pull/4619) refactor(v2): rename class main-docs-wrapper to docs-wrapper ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#4582](https://github.com/facebook/docusaurus/pull/4582) feat(v2): auto-generated sidebars, frontmatter-less sites ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#4627](https://github.com/facebook/docusaurus/pull/4627) chore(v2): update Infima to alpha.22 ([@slorber](https://github.com/slorber)) - - [#4621](https://github.com/facebook/docusaurus/pull/4621) fix(v2): center align content if no sidebar exists ([@lex111](https://github.com/lex111)) - - [#4620](https://github.com/facebook/docusaurus/pull/4620) fix(v2): restore toggle responsive sidebar button ([@lex111](https://github.com/lex111)) - - [#4598](https://github.com/facebook/docusaurus/pull/4598) fix(v2): render escaped HTML entities inside code properly ([@lex111](https://github.com/lex111)) - - [#4554](https://github.com/facebook/docusaurus/pull/4554) fix: DocNavbarItem error message ([@serut](https://github.com/serut)) - - [#4468](https://github.com/facebook/docusaurus/pull/4468) fix(v2): select correct tab when items are incorrectly ordered ([@armano2](https://github.com/armano2)) - - [#4461](https://github.com/facebook/docusaurus/pull/4461) fix(v2): Fix i18n staging deployment due to json typo ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#4541](https://github.com/facebook/docusaurus/pull/4541) fix(v2): fix code block title parsing, support multiple metastring attributes ([@duanwilliam](https://github.com/duanwilliam)) - - [#4600](https://github.com/facebook/docusaurus/pull/4600) fix(v2): use page title from config if not set ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#4501](https://github.com/facebook/docusaurus/pull/4501) fix(v2): fail-safe usage of browser storage (localStorage/sessionStorage) when access is denied ([@jknoxville](https://github.com/jknoxville)) -- `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` - - [#4593](https://github.com/facebook/docusaurus/pull/4593) fix(v2): i18n perf issue: getTranslationFile() should not load content again ([@slorber](https://github.com/slorber)) -- Other - - [#4574](https://github.com/facebook/docusaurus/pull/4574) fix(v2): examples should use Node 14 by default on CodeSandbox + regen with alpha72 ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#4547](https://github.com/facebook/docusaurus/pull/4547) feat(v2) : use symbols to denote swizzle safety ([@besemuna](https://github.com/besemuna)) - - [#4575](https://github.com/facebook/docusaurus/pull/4575) fix(v2): fix i18n isLastLocale bug preventing docusaurus from building some locales ([@slorber](https://github.com/slorber)) - - [#4506](https://github.com/facebook/docusaurus/pull/4506) fix(v2): remove no longer used postcss-present-env from dependencies ([@armano2](https://github.com/armano2)) - - [#4444](https://github.com/facebook/docusaurus/pull/4444) fix(v2): Fix writeHeadingIds on Windows due to non-posix paths ([@slorber](https://github.com/slorber)) -- `docusaurus-utils` - - [#4507](https://github.com/facebook/docusaurus/pull/4507) fix(v2): do not warn about duplicated title for pages ([@armano2](https://github.com/armano2)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus` - - [#4466](https://github.com/facebook/docusaurus/pull/4466) fix(v2): i18n fixes ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus` - - [#4459](https://github.com/facebook/docusaurus/pull/4459) fix(v2): Export Joi from validation-utils package ([@slorber](https://github.com/slorber)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#4626](https://github.com/facebook/docusaurus/pull/4626) refactor(v2): toggleResponsiveSidebar => more stable callback ([@slorber](https://github.com/slorber)) - - [#4617](https://github.com/facebook/docusaurus/pull/4617) refactor(v2): simplify and optimize sidebar ([@slorber](https://github.com/slorber)) - - [#4608](https://github.com/facebook/docusaurus/pull/4608) refactor(v2): replace react-toggle with own implementation ([@lex111](https://github.com/lex111)) - - [#4601](https://github.com/facebook/docusaurus/pull/4601) refactor(v2): increase heading anchor offset ([@lex111](https://github.com/lex111)) - - [#4467](https://github.com/facebook/docusaurus/pull/4467) refactor(v2): add missing types to theme-classic useTheme ([@armano2](https://github.com/armano2)) - - [#4448](https://github.com/facebook/docusaurus/pull/4448) polish(v2): Add german translations ([@miku86](https://github.com/miku86)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#4619](https://github.com/facebook/docusaurus/pull/4619) refactor(v2): rename class main-docs-wrapper to docs-wrapper ([@slorber](https://github.com/slorber)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus` - - [#4451](https://github.com/facebook/docusaurus/pull/4451) refactor(v2): correct client types and type aliases ([@armano2](https://github.com/armano2)) -- `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#4450](https://github.com/facebook/docusaurus/pull/4450) chore(v2): Fix more linter warnings ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` - - [#4442](https://github.com/facebook/docusaurus/pull/4442) chore(v2): Fix linter warnings ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#4375](https://github.com/facebook/docusaurus/pull/4375) refactor(v2): TS config update: reduce the size of npm modules ([@RDIL](https://github.com/RDIL)) - -#### :memo: Documentation - -- Other - - [#4616](https://github.com/facebook/docusaurus/pull/4616) docs(v2): add showcase: kubevela ([@sunny0826](https://github.com/sunny0826)) - - [#4612](https://github.com/facebook/docusaurus/pull/4612) docs(v2): Added IntelAGENT website to showcase. ([@akepecs](https://github.com/akepecs)) - - [#4609](https://github.com/facebook/docusaurus/pull/4609) docs(v2): add clarity to tip in versioned using-themes page ([@dickwyn](https://github.com/dickwyn)) - - [#4606](https://github.com/facebook/docusaurus/pull/4606) docs(v2): heading typo ([@arturcarvalho](https://github.com/arturcarvalho)) - - [#4604](https://github.com/facebook/docusaurus/pull/4604) docs(v2): add clarity to tip in using-themes page ([@dickwyn](https://github.com/dickwyn)) - - [#4602](https://github.com/facebook/docusaurus/pull/4602) docs(v2): Add "PptxGenJS" to showcase ([@gitbrent](https://github.com/gitbrent)) - - [#4599](https://github.com/facebook/docusaurus/pull/4599) docs(v2): i18n site: enable ko + zh-CN locales ([@slorber](https://github.com/slorber)) - - [#4595](https://github.com/facebook/docusaurus/pull/4595) docs(v2): fix typo theme-configuration.md ([@forresst](https://github.com/forresst)) - - [#4594](https://github.com/facebook/docusaurus/pull/4594) docs(v2): Include docusaurus-protobuffet to community plugins ([@AnthonyBobsin](https://github.com/AnthonyBobsin)) - - [#4558](https://github.com/facebook/docusaurus/pull/4558) docs(v2): fixed broken link in i18n-tutorial.md ([@covalentbond](https://github.com/covalentbond)) - - [#4573](https://github.com/facebook/docusaurus/pull/4573) docs: update README badges ([@slorber](https://github.com/slorber)) - - [#4559](https://github.com/facebook/docusaurus/pull/4559) docs(v2): fixed the directory of index.js ([@covalentbond](https://github.com/covalentbond)) - - [#4568](https://github.com/facebook/docusaurus/pull/4568) docs(v2): add social-embed to showcase ([@tony](https://github.com/tony)) - - [#4570](https://github.com/facebook/docusaurus/pull/4570) docs(v2): Add Redis Labs Developer Site to docusaurus showcase page ([@ajeetraina](https://github.com/ajeetraina)) - - [#4543](https://github.com/facebook/docusaurus/pull/4543) docs(v2): fix run-on sentence ([@duanwilliam](https://github.com/duanwilliam)) - - [#4539](https://github.com/facebook/docusaurus/pull/4539) docs(v2): fix typo deployment.mdx ([@forresst](https://github.com/forresst)) - - [#4538](https://github.com/facebook/docusaurus/pull/4538) Add Tuist to the list of projects that use Docusaurus ([@pepibumur](https://github.com/pepibumur)) - - [#4531](https://github.com/facebook/docusaurus/pull/4531) docs(v2): remove duplicate line on v1 docs ([@loozhengyuan](https://github.com/loozhengyuan)) - - [#4524](https://github.com/facebook/docusaurus/pull/4524) docs(v2): config for self-hosted docsearch crawler ([@loozhengyuan](https://github.com/loozhengyuan)) - - [#4526](https://github.com/facebook/docusaurus/pull/4526) docs(v2): fix markdown headings level 4 ([@forresst](https://github.com/forresst)) - - [#4505](https://github.com/facebook/docusaurus/pull/4505) docs(v2): add more links to v1: announcementBar, versionDropdown, homepage ([@slorber](https://github.com/slorber)) - - [#4497](https://github.com/facebook/docusaurus/pull/4497) docs: fix link to issue template ([@forresst](https://github.com/forresst)) - - [#4481](https://github.com/facebook/docusaurus/pull/4481) docs(v2): fix grammar and improve wording ([@aehrea](https://github.com/aehrea)) - - [#4472](https://github.com/facebook/docusaurus/pull/4472) docs(v2): fixed broken link in sidebar documentation ([@covalentbond](https://github.com/covalentbond)) - - [#4470](https://github.com/facebook/docusaurus/pull/4470) docs(v2): Add missing i18n docs: API lifecycles + Crowdin migration guide ([@slorber](https://github.com/slorber)) - - [#4460](https://github.com/facebook/docusaurus/pull/4460) docs(v2): use explicit heading IDs ([@lex111](https://github.com/lex111)) - - [#4446](https://github.com/facebook/docusaurus/pull/4446) docs(v2): Add blog.johnnyreilly.com to showcase ([@johnnyreilly](https://github.com/johnnyreilly)) - - [#4430](https://github.com/facebook/docusaurus/pull/4430) docs(v2): add Deploy with QuandCDN ([@steveworley](https://github.com/steveworley)) - - [#4441](https://github.com/facebook/docusaurus/pull/4441) docs(v2): add stylable site to users showcase list ([@tomrav](https://github.com/tomrav)) -- `docusaurus-init` - - [#4561](https://github.com/facebook/docusaurus/pull/4561) docs(v2): add a missing slug from the initial template ([@Foxeye-Rinx](https://github.com/Foxeye-Rinx)) - - [#4560](https://github.com/facebook/docusaurus/pull/4560) docs(v2): fixed typos ([@covalentbond](https://github.com/covalentbond)) - - [#4546](https://github.com/facebook/docusaurus/pull/4546) docs(v2): add a missing "export" from the initial template ([@Foxeye-Rinx](https://github.com/Foxeye-Rinx)) - - [#4320](https://github.com/facebook/docusaurus/pull/4320) feat(v2): Improve the initial templates #4302 ([@besemuna](https://github.com/besemuna)) -- `docusaurus-migrate`, `docusaurus` - - [#4479](https://github.com/facebook/docusaurus/pull/4479) docs(v2): fixed typos ([@covalentbond](https://github.com/covalentbond)) - -#### :house: Internal - -- `docusaurus-theme-classic` - - [#4627](https://github.com/facebook/docusaurus/pull/4627) chore(v2): update Infima to alpha.22 ([@slorber](https://github.com/slorber)) - - [#4463](https://github.com/facebook/docusaurus/pull/4463) chore: fb json header commit typo ([@slorber](https://github.com/slorber)) -- Other - - [#4613](https://github.com/facebook/docusaurus/pull/4613) chore(v2): fix yarn2 end2end test by using lerna publish --exact ([@slorber](https://github.com/slorber)) - - [#4611](https://github.com/facebook/docusaurus/pull/4611) chore(v2): CI: do not build all locales when monitoring build time perf ([@slorber](https://github.com/slorber)) - - [#4486](https://github.com/facebook/docusaurus/pull/4486) ci: enable yarn install cache ([@armano2](https://github.com/armano2)) - - [#4508](https://github.com/facebook/docusaurus/pull/4508) ci: change default actions timeout from 6h to 30m ([@armano2](https://github.com/armano2)) - - [#4488](https://github.com/facebook/docusaurus/pull/4488) chore(v2): fix typo in classic init template ([@clarus](https://github.com/clarus)) - - [#4471](https://github.com/facebook/docusaurus/pull/4471) chore: fix GH actions lint problem matchers issue in PR ([@slorber](https://github.com/slorber)) - - [#4458](https://github.com/facebook/docusaurus/pull/4458) chore(v2): enable staging locales: ko ja ([@slorber](https://github.com/slorber)) - - [#4457](https://github.com/facebook/docusaurus/pull/4457) chore(v2): remove docs for alpha v70 ([@lex111](https://github.com/lex111)) - - [#4452](https://github.com/facebook/docusaurus/pull/4452) chore(v2): update typescript-eslint to v4.18.0 ([@armano2](https://github.com/armano2)) -- `docusaurus` - - [#4516](https://github.com/facebook/docusaurus/pull/4516) ci(v2): fail CI if build takes too much time ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#4490](https://github.com/facebook/docusaurus/pull/4490) chore: rename v2.docusaurus.io urls after domain switch + redirect + cleanups ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x` - - [#4475](https://github.com/facebook/docusaurus/pull/4475) chore: prepare v1-v2 domain switch ([@slorber](https://github.com/slorber)) - - [#4447](https://github.com/facebook/docusaurus/pull/4447) chore: simplify CI setup ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x`, `docusaurus-init` - - [#4453](https://github.com/facebook/docusaurus/pull/4453) chore(v2): migrate babel-eslint to @babel/eslint-parser ([@armano2](https://github.com/armano2)) -- `docusaurus-utils-validation` - - [#4464](https://github.com/facebook/docusaurus/pull/4464) chore(v2): Joi cyclic dep warning ([@slorber](https://github.com/slorber)) -- `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` - - [#4462](https://github.com/facebook/docusaurus/pull/4462) chore: json files should be linted ([@slorber](https://github.com/slorber)) - -#### :running_woman: Performance - -- `docusaurus-theme-classic` - - [#4626](https://github.com/facebook/docusaurus/pull/4626) refactor(v2): toggleResponsiveSidebar => more stable callback ([@slorber](https://github.com/slorber)) - - [#4603](https://github.com/facebook/docusaurus/pull/4603) perf(v2): avoid rerender of sidebar items while scrolling ([@lex111](https://github.com/lex111)) - - [#4473](https://github.com/facebook/docusaurus/pull/4473) perf(v2): reduce amount of component updates while scrolling ([@armano2](https://github.com/armano2)) - -#### Committers: 37 - -- Ajeet Singh Raina, Docker Captain, RedisLabs ([@ajeetraina](https://github.com/ajeetraina)) -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Anthony Bobsin ([@AnthonyBobsin](https://github.com/AnthonyBobsin)) -- Arijit Kundu ([@covalentbond](https://github.com/covalentbond)) -- Armano ([@armano2](https://github.com/armano2)) -- Artur Carvalho ([@arturcarvalho](https://github.com/arturcarvalho)) -- Brent Ely ([@gitbrent](https://github.com/gitbrent)) -- Chris Kanich ([@kaytwo](https://github.com/kaytwo)) -- Dennis Thompson ([@atomicpages](https://github.com/atomicpages)) -- Dick Wyn Yong ([@dickwyn](https://github.com/dickwyn)) -- Forresst ([@forresst](https://github.com/forresst)) -- Guillaume Claret ([@clarus](https://github.com/clarus)) -- John Knox ([@jknoxville](https://github.com/jknoxville)) -- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) -- Lisa Chandra ([@lisa761](https://github.com/lisa761)) -- Lucas Alves ([@lucalves](https://github.com/lucalves)) -- Marco Enrico ([@gumacahin](https://github.com/gumacahin)) -- Pedro Piñera Buendía ([@pepibumur](https://github.com/pepibumur)) -- Reece Dunham ([@RDIL](https://github.com/RDIL)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Steve ([@steveworley](https://github.com/steveworley)) -- Steven Hansel ([@ShinteiMai](https://github.com/ShinteiMai)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tales Porto ([@talesporto](https://github.com/talesporto)) -- Thiago Sciotta ([@thiagog3](https://github.com/thiagog3)) -- Tiago Ribeiro ([@tiago-rr](https://github.com/tiago-rr)) -- Tom Raviv ([@tomrav](https://github.com/tomrav)) -- Tony Narlock ([@tony](https://github.com/tony)) -- ZhengYuan Loo ([@loozhengyuan](https://github.com/loozhengyuan)) -- [@Foxeye-Rinx](https://github.com/Foxeye-Rinx) -- [@aehrea](https://github.com/aehrea) -- [@akepecs](https://github.com/akepecs) -- [@besemuna](https://github.com/besemuna) -- [@duanwilliam](https://github.com/duanwilliam) -- [@miku86](https://github.com/miku86) -- [@serut](https://github.com/serut) -- guoxudong ([@sunny0826](https://github.com/sunny0826)) - -## 2.0.0-alpha.72 (2021-03-16) - -#### :boom: Breaking Change - -Starting with this release for a proper work of i18n functionality, you need to either use Node v14+ or in case of using earlier version of Node.js install [`full-icu` package](https://www.npmjs.com/package/full-icu) and set `NODE_ICU_DATA` environment variable in your npm scripts, for example: - -```json -"scripts": { - "start": "cross-env NODE_ICU_DATA=node_modules/full-icu docusaurus start" -} -``` - -#### :rocket: New Feature - -- `docusaurus-init` - - [#4302](https://github.com/facebook/docusaurus/pull/4302) feat(v2): Improve the initial templates ([@ShinteiMai](https://github.com/ShinteiMai)) -- `docusaurus-theme-classic` - - [#4390](https://github.com/facebook/docusaurus/pull/4390) feat(v2): Add korean default translations ([@koko8829](https://github.com/koko8829)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#4429](https://github.com/facebook/docusaurus/pull/4429) chore(v2): upgrade Infima to v0.2.0-alpha.21 ([@lex111](https://github.com/lex111)) - - [#4428](https://github.com/facebook/docusaurus/pull/4428) fix(v2): allow using pre tag in Markdown directly ([@lex111](https://github.com/lex111)) - - [#4381](https://github.com/facebook/docusaurus/pull/4381) fix(v2): specify proper TS path in classic theme ([@lex111](https://github.com/lex111)) - - [#4383](https://github.com/facebook/docusaurus/pull/4383) fix(v2): set theme color mode for SSR ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-pwa` - - [#4424](https://github.com/facebook/docusaurus/pull/4424) fix(v2): add missing peer dep on @babel/core ([@SimenB](https://github.com/SimenB)) - - [#4377](https://github.com/facebook/docusaurus/pull/4377) fix(v2): PWA issues + improve docs ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#4407](https://github.com/facebook/docusaurus/pull/4407) fix(v2): broken link checker should not report false positives when using encoded chars ([@Harvtronix](https://github.com/Harvtronix)) -- Other - - [#4410](https://github.com/facebook/docusaurus/pull/4410) fix(v1): Fix v1 site deployment with Crowdin again... ([@slorber](https://github.com/slorber)) - - [#4396](https://github.com/facebook/docusaurus/pull/4396) fix(v1): Temp fix v1 site deployment: fail-safe on Crowdin upload translations error ([@slorber](https://github.com/slorber)) - - [#4395](https://github.com/facebook/docusaurus/pull/4395) fix(v1): fix v1 site deploy issues ([@slorber](https://github.com/slorber)) - -#### :nail_care: Polish - -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus` - - [#4418](https://github.com/facebook/docusaurus/pull/4418) refactor(v2): correct plugin types ([@armano2](https://github.com/armano2)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-utils`, `docusaurus` - - [#4405](https://github.com/facebook/docusaurus/pull/4405) refactor(v2): i18n cleanups / refactors ([@longlho](https://github.com/longlho)) -- `docusaurus-module-type-aliases` - - [#4387](https://github.com/facebook/docusaurus/pull/4387) refactor(v2): add ExecutionEnvironment, BrowserOnly, isInternalUrl to type aliases ([@armano2](https://github.com/armano2)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils` - - [#4402](https://github.com/facebook/docusaurus/pull/4402) refactor(v2): merge linkify function used in blog and docs and align properties ([@armano2](https://github.com/armano2)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-docs`, `docusaurus-theme-common`, `docusaurus-utils-validation`, `docusaurus` - - [#4382](https://github.com/facebook/docusaurus/pull/4382) refactor(v2): correct some of type errors reported by eslint ([@armano2](https://github.com/armano2)) -- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#4385](https://github.com/facebook/docusaurus/pull/4385) refactor(v2): add missing theme-classic types ([@armano2](https://github.com/armano2)) - -#### :memo: Documentation - -- [#4416](https://github.com/facebook/docusaurus/pull/4416) docs(v2): add Realtime Web Applications Workshop to showcase ([@lowenhere](https://github.com/lowenhere)) -- [#4408](https://github.com/facebook/docusaurus/pull/4408) docs(v2): add gladysassistant.com to showcase ([@Pierre-Gilles](https://github.com/Pierre-Gilles)) -- [#4386](https://github.com/facebook/docusaurus/pull/4386) docs(v2): Showcase the pnpm docs ([@zkochan](https://github.com/zkochan)) -- [#4367](https://github.com/facebook/docusaurus/pull/4367) docs(v2): releasing i18n blog post ([@slorber](https://github.com/slorber)) - -#### :house: Internal - -- `docusaurus-1.x` - - [#4401](https://github.com/facebook/docusaurus/pull/4401) chore(v1): fix CircleCI v1 site deploy ([@slorber](https://github.com/slorber)) -- Other - - [#4399](https://github.com/facebook/docusaurus/pull/4399) chore(v2): upgrade example projects ([@slorber](https://github.com/slorber)) - - [#4398](https://github.com/facebook/docusaurus/pull/4398) chore(v1): trigger v1 site deploy through CI ([@slorber](https://github.com/slorber)) -- `docusaurus-utils` - - [#4384](https://github.com/facebook/docusaurus/pull/4384) chore(v2): avoid bad publish of intl-locales-supported ([@lex111](https://github.com/lex111)) - -#### Committers: 14 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Armano ([@armano2](https://github.com/armano2)) -- Harvtronix ([@Harvtronix](https://github.com/Harvtronix)) -- Joon-Ha Lee ([@koko8829](https://github.com/koko8829)) -- Leandro Oriente ([@leandrooriente](https://github.com/leandrooriente)) -- Long Ho ([@longlho](https://github.com/longlho)) -- Lowen ([@lowenhere](https://github.com/lowenhere)) -- Pierre-Gilles Leymarie ([@Pierre-Gilles](https://github.com/Pierre-Gilles)) -- Quan ([@quanengineering](https://github.com/quanengineering)) -- Simen Bekkhus ([@SimenB](https://github.com/SimenB)) -- Steven Hansel ([@ShinteiMai](https://github.com/ShinteiMai)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Zoltan Kochan ([@zkochan](https://github.com/zkochan)) -- [@Rhodanthe1116](https://github.com/Rhodanthe1116) - -## 2.0.0-alpha.71 (2021-03-09) - -#### :rocket: New Feature - -- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-utils`, `docusaurus` - - [#4222](https://github.com/facebook/docusaurus/pull/4222) feat(v2): add ability to set custom heading id ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-live-codeblock` - - [#4328](https://github.com/facebook/docusaurus/pull/4328) feat(v2): Add playgroundPosition config for live codeblock ([@tokarchyn](https://github.com/tokarchyn)) -- `docusaurus-theme-classic` - - [#4209](https://github.com/facebook/docusaurus/pull/4209) feat(v2): auto focus to tab if it is outside viewport ([@lex111](https://github.com/lex111)) - - [#4329](https://github.com/facebook/docusaurus/pull/4329) feat(v2): add arabic translation ([@3alisaki](https://github.com/3alisaki)) - - [#4325](https://github.com/facebook/docusaurus/pull/4325) feat(v2): [theme-classic] add Polish translation ([@Simek](https://github.com/Simek)) - - [#4312](https://github.com/facebook/docusaurus/pull/4312) feat(v2): Add Turkish translations for theme labels ([@caglarturali](https://github.com/caglarturali)) - - [#4271](https://github.com/facebook/docusaurus/pull/4271) feat(v2): add Farsi default translations ([@slorber](https://github.com/slorber)) - - [#4261](https://github.com/facebook/docusaurus/pull/4261) feat(v2): add icon to generic sidebar link ([@lex111](https://github.com/lex111)) - - [#4109](https://github.com/facebook/docusaurus/pull/4109) feat(v2): default canonical urls ([@slorber](https://github.com/slorber)) -- `docusaurus-types`, `docusaurus` - - [#4308](https://github.com/facebook/docusaurus/pull/4308) feat(v2): add --config option to CLI ([@longlho](https://github.com/longlho)) - - [#4185](https://github.com/facebook/docusaurus/pull/4185) feat(v2): allow extend PostCSS config ([@lex111](https://github.com/lex111)) - - [#4021](https://github.com/facebook/docusaurus/pull/4021) feat(v2): Allow plugins to consume webpack stats ([@RDIL](https://github.com/RDIL)) -- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#4303](https://github.com/facebook/docusaurus/pull/4303) feat(v2): add japanese translations ([@ykzts](https://github.com/ykzts)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus` - - [#4295](https://github.com/facebook/docusaurus/pull/4295) feat(v2): Add Interpolate / interpolate APIs + complete theme translations ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader` - - [#4278](https://github.com/facebook/docusaurus/pull/4278) feat(v2): ability to "escape" JSX in MDX files as code blocks ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` - - [#4232](https://github.com/facebook/docusaurus/pull/4232) feat(v2): editUrl functions should receive md doc permalink ([@slorber](https://github.com/slorber)) - - [#4121](https://github.com/facebook/docusaurus/pull/4121) feat(v2): editUrl function for advanced use-cases ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#4218](https://github.com/facebook/docusaurus/pull/4218) feat(v2): support/use React v17 by default ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` - - [#4215](https://github.com/facebook/docusaurus/pull/4215) feat(v2): Add i18n default code translation bundles ([@slorber](https://github.com/slorber)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#4140](https://github.com/facebook/docusaurus/pull/4140) feat(v2): add support for RTL direction ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#4199](https://github.com/facebook/docusaurus/pull/4199) feat(v2): allow to change location of search bar ([@lex111](https://github.com/lex111)) - - [#3993](https://github.com/facebook/docusaurus/pull/3993) feat(v2): themed logo in footer ([@natac13](https://github.com/natac13)) -- `docusaurus` - - [#4198](https://github.com/facebook/docusaurus/pull/4198) feat(v2): add fonts loaders + webpack resolve.roots ([@slorber](https://github.com/slorber)) - - [#3998](https://github.com/facebook/docusaurus/pull/3998) feat(v2): Cache hashed assets to dedicated folders ([@kumaraditya303](https://github.com/kumaraditya303)) - - [#3979](https://github.com/facebook/docusaurus/pull/3979) feat(v2): better error message for invalid plugin config ([@9oelM](https://github.com/9oelM)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus` - - [#4168](https://github.com/facebook/docusaurus/pull/4168) feat(v2): Extract/translate hardcoded labels from classic theme ([@slorber](https://github.com/slorber)) -- `docusaurus-init` - - [#4098](https://github.com/facebook/docusaurus/pull/4098) feat(v2): improve templates, use JSDoc type annotation, improve `docusaurus.config.js` autocompletion ([@LittleboyHarry](https://github.com/LittleboyHarry)) -- `docusaurus-init`, `docusaurus-migrate` - - [#3986](https://github.com/facebook/docusaurus/pull/3986) feat(v2): skip dependency install on docusaurus init ([@kumaraditya303](https://github.com/kumaraditya303)) -- `docusaurus-plugin-content-docs` - - [#3949](https://github.com/facebook/docusaurus/pull/3949) feat(v2): new docs edit options: editCurrentVersion + editLocalizedDocs ([@slorber](https://github.com/slorber)) - -#### :boom: Breaking Change - -- `docusaurus-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#4223](https://github.com/facebook/docusaurus/pull/4223) chore(v2): upgrade dependencies + require Node 12 ([@lex111](https://github.com/lex111)) - -#### :bug: Bug Fix - -- `docusaurus` - - [#4366](https://github.com/facebook/docusaurus/pull/4366) fix(v2): align installed core-js version with babel config ([@armano2](https://github.com/armano2)) - - [#4345](https://github.com/facebook/docusaurus/pull/4345) fix(v2): always extract translations from site/src ([@slorber](https://github.com/slorber)) - - [#4342](https://github.com/facebook/docusaurus/pull/4342) chore(v2): bump clean-css to 5.1.1 ([@lex111](https://github.com/lex111)) - - [#4212](https://github.com/facebook/docusaurus/pull/4212) fix(v2): typo in resolve.roots ([@slorber](https://github.com/slorber)) - - [#4155](https://github.com/facebook/docusaurus/pull/4155) fix(v2): BaseUrl issue banner insertion should be prevented if JS can load ([@slorber](https://github.com/slorber)) - - [#4137](https://github.com/facebook/docusaurus/pull/4137) fix(v2): escape apostrophes in route paths ([@lex111](https://github.com/lex111)) - - [#4136](https://github.com/facebook/docusaurus/pull/4136) fix(v2): fix navigation from homepage ([@lex111](https://github.com/lex111)) - - [#4125](https://github.com/facebook/docusaurus/pull/4125) fix(v2): baseUrl help banner should not be indexed by Google / SEO ([@slorber](https://github.com/slorber)) - - [#4080](https://github.com/facebook/docusaurus/pull/4080) fix(v2): chokidar reloading debounced ([@semoal](https://github.com/semoal)) - - [#3965](https://github.com/facebook/docusaurus/pull/3965) fix(v2): fix svg loader for CSS files ([@apurvaojas](https://github.com/apurvaojas)) - - [#3943](https://github.com/facebook/docusaurus/pull/3943) fix(v2): disables all inlining in CleanCSS ([@lex111](https://github.com/lex111)) - - [#3941](https://github.com/facebook/docusaurus/pull/3941) fix(v2): fix i18n build logging. ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#4349](https://github.com/facebook/docusaurus/pull/4349) fix(v2): fix update code translations script + update some translations ([@slorber](https://github.com/slorber)) - - [#4311](https://github.com/facebook/docusaurus/pull/4311) fix(v2): fit footer in viewport when content area is too small ([@lex111](https://github.com/lex111)) - - [#4340](https://github.com/facebook/docusaurus/pull/4340) fix(v2): prevent useless blog pages to be in search results ([@slorber](https://github.com/slorber)) - - [#4274](https://github.com/facebook/docusaurus/pull/4274) fix(v2): theme classic should have lib-next prettified ([@slorber](https://github.com/slorber)) - - [#4267](https://github.com/facebook/docusaurus/pull/4267) fix(v2): Allow null as valid for title of item in footer links. ([@ben-qnimble](https://github.com/ben-qnimble)) - - [#4254](https://github.com/facebook/docusaurus/pull/4254) fix(v2): fix LTR PostCSS bug on Netlify and monorepo symlinks ([@slorber](https://github.com/slorber)) - - [#4247](https://github.com/facebook/docusaurus/pull/4247) fix(v2): make doc container full width when hidden sidebar ([@lex111](https://github.com/lex111)) - - [#4241](https://github.com/facebook/docusaurus/pull/4241) fix(v2): avoid horizontal scrolling when long lines of code ([@lex111](https://github.com/lex111)) - - [#4200](https://github.com/facebook/docusaurus/pull/4200) fix(v2): various minor bugs with location hash ([@lex111](https://github.com/lex111)) - - [#4195](https://github.com/facebook/docusaurus/pull/4195) fix(v2): restore hamburger menu ([@lex111](https://github.com/lex111)) - - [#4189](https://github.com/facebook/docusaurus/pull/4189) fix(v2): prevent click on item menu with children on mobiles ([@lex111](https://github.com/lex111)) - - [#4176](https://github.com/facebook/docusaurus/pull/4176) fix(v2): make locale dropdown accessible from keyboard ([@lex111](https://github.com/lex111)) - - [#4163](https://github.com/facebook/docusaurus/pull/4163) fix(v2): fix warning and improve styling inline TOC ([@lex111](https://github.com/lex111)) - - [#4162](https://github.com/facebook/docusaurus/pull/4162) fix(v2): make more accessible skip link ([@lex111](https://github.com/lex111)) - - [#4160](https://github.com/facebook/docusaurus/pull/4160) fix(v2): fix hreflang headers ([@slorber](https://github.com/slorber)) - - [#4147](https://github.com/facebook/docusaurus/pull/4147) fix(v2): avoid misuse section tag in blog posts ([@lex111](https://github.com/lex111)) - - [#4146](https://github.com/facebook/docusaurus/pull/4146) fix(v2): use current color for language icon ([@lex111](https://github.com/lex111)) - - [#4118](https://github.com/facebook/docusaurus/pull/4118) fix(v2): navbar dropdown subitems should be translated properly ([@slorber](https://github.com/slorber)) - - [#4011](https://github.com/facebook/docusaurus/pull/4011) fix(v2): fix accessibility issue with IconArrow ([@natac13](https://github.com/natac13)) - - [#3968](https://github.com/facebook/docusaurus/pull/3968) fix(v2): fix blog only contextual search ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#4315](https://github.com/facebook/docusaurus/pull/4315) fix(v2): make code blocks more standalone ([@lex111](https://github.com/lex111)) - - [#4277](https://github.com/facebook/docusaurus/pull/4277) fix(v2): Code blocks should be LTR by default ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-live-codeblock` - - [#4318](https://github.com/facebook/docusaurus/pull/4318) fix(v2): evaluate code in live editor on client only ([@lex111](https://github.com/lex111)) - - [#3954](https://github.com/facebook/docusaurus/pull/3954) fix(v2): allow async/await in live code editor ([@9oelM](https://github.com/9oelM)) -- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#4339](https://github.com/facebook/docusaurus/pull/4339) fix(v2): search page results localization ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#4304](https://github.com/facebook/docusaurus/pull/4304) fix(v2): fix bad theme pluralization rules for some labels ([@slorber](https://github.com/slorber)) -- `docusaurus-cssnano-preset` - - [#4240](https://github.com/facebook/docusaurus/pull/4240) fix(v2): remove PostCSS plugin for combine duplicated selectors ([@lex111](https://github.com/lex111)) -- Other - - [#4234](https://github.com/facebook/docusaurus/pull/4234) fix(v2): fix website versions page ([@slorber](https://github.com/slorber)) - - [#4233](https://github.com/facebook/docusaurus/pull/4233) fix(v2): website editUrl should target upstream docs ([@slorber](https://github.com/slorber)) - - [#4067](https://github.com/facebook/docusaurus/pull/4067) fix(v2): Fix blog post url/date ([@slorber](https://github.com/slorber)) - - [#3952](https://github.com/facebook/docusaurus/pull/3952) docs(v2): Fix invalid json ([@oze4](https://github.com/oze4)) -- `docusaurus-theme-search-algolia` - - [#4188](https://github.com/facebook/docusaurus/pull/4188) fix(v2): prepend docsearch modal to body element ([@lex111](https://github.com/lex111)) - - [#4154](https://github.com/facebook/docusaurus/pull/4154) fix(v2): add base url to opensearch.xml ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-ideal-image` - - [#4166](https://github.com/facebook/docusaurus/pull/4166) fix(v2): ideal image assets should be served under ./assets ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-common` - - [#4092](https://github.com/facebook/docusaurus/pull/4092) fix(v2): fix/enhance minor i18n issues reported ([@slorber](https://github.com/slorber)) - - [#3940](https://github.com/facebook/docusaurus/pull/3940) fix(v2): i18n should not crash theme without footer ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-sitemap` - - [#4004](https://github.com/facebook/docusaurus/pull/4004) fix(v2): Fix double trailingSlash in sitemap.xml ([@ntbosscher](https://github.com/ntbosscher)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils` - - [#3970](https://github.com/facebook/docusaurus/pull/3970) fix(v2): fix multi-instance mdx loaders not sandboxed correctly ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects` - - [#3903](https://github.com/facebook/docusaurus/pull/3903) fix(v2): fix redirect toUrl (windows + trailing slash) ([@saydo17](https://github.com/saydo17)) -- `docusaurus-utils` - - [#3944](https://github.com/facebook/docusaurus/pull/3944) fix(v2): ignore style imports in excerpt ([@lex111](https://github.com/lex111)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#4371](https://github.com/facebook/docusaurus/pull/4371) refactor(v2): update Russian translation in classic theme ([@lex111](https://github.com/lex111)) - - [#4359](https://github.com/facebook/docusaurus/pull/4359) polish(v2): [theme-classic] slightly improve Japanese translation ([@MisterFISHUP](https://github.com/MisterFISHUP)) - - [#4350](https://github.com/facebook/docusaurus/pull/4350) polish(v2): Updated theme label translations for Turkish ([@caglarturali](https://github.com/caglarturali)) - - [#4351](https://github.com/facebook/docusaurus/pull/4351) polish(v2): add japanese translation for #4304 ([@ykzts](https://github.com/ykzts)) - - [#4309](https://github.com/facebook/docusaurus/pull/4309) polish(v2): improved Farsi translation ([@massoudmaboudi](https://github.com/massoudmaboudi)) - - [#4279](https://github.com/facebook/docusaurus/pull/4279) polish(v2): theme default translations for language de / german ([@philipp985](https://github.com/philipp985)) - - [#4275](https://github.com/facebook/docusaurus/pull/4275) polish(v2): Add more tags translations ([@slorber](https://github.com/slorber)) - - [#4246](https://github.com/facebook/docusaurus/pull/4246) refactor(v2): add Russian translation for classic theme ([@lex111](https://github.com/lex111)) - - [#4242](https://github.com/facebook/docusaurus/pull/4242) refactor(v2): use Link component for external links ([@lex111](https://github.com/lex111)) - - [#4244](https://github.com/facebook/docusaurus/pull/4244) refactor(v2): clean-ups and fixes ([@lex111](https://github.com/lex111)) - - [#4193](https://github.com/facebook/docusaurus/pull/4193) refactor(v2): update tabs to follow WAI-ARIA spec ([@lex111](https://github.com/lex111)) - - [#4194](https://github.com/facebook/docusaurus/pull/4194) refactor(v2): use transform instead of top position for hideable navbar ([@lex111](https://github.com/lex111)) - - [#4167](https://github.com/facebook/docusaurus/pull/4167) refactor(v2): minor styling improvements ([@lex111](https://github.com/lex111)) - - [#4169](https://github.com/facebook/docusaurus/pull/4169) refactor(v2): remove delay after skip link pressed ([@lex111](https://github.com/lex111)) - - [#4086](https://github.com/facebook/docusaurus/pull/4086) style(v2): add className to tab container ([@ArtFlag](https://github.com/ArtFlag)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#4352](https://github.com/facebook/docusaurus/pull/4352) refactor(v2): format last updated date using Intl ([@lex111](https://github.com/lex111)) - - [#4243](https://github.com/facebook/docusaurus/pull/4243) refactor(v2): introduce Seo component for internal using ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic`, `docusaurus-utils` - - [#4344](https://github.com/facebook/docusaurus/pull/4344) refactor(v2): format post date using Intl ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#4257](https://github.com/facebook/docusaurus/pull/4257) refactor(v2): improve notifier message ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#4219](https://github.com/facebook/docusaurus/pull/4219) refactor(v2): add more translatable strings ([@lex111](https://github.com/lex111)) -- Other - - [#4074](https://github.com/facebook/docusaurus/pull/4074) polish(v2): improve codesandbox template package.json ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-debug` - - [#3953](https://github.com/facebook/docusaurus/pull/3953) refactor(v2): fix debug plugin name ([@RDIL](https://github.com/RDIL)) -- `docusaurus-plugin-debug`, `docusaurus-theme-classic` - - [#3946](https://github.com/facebook/docusaurus/pull/3946) refactor(v2): minor a11y tweaks ([@lex111](https://github.com/lex111)) - -#### :memo: Documentation - -- Other - - [#4369](https://github.com/facebook/docusaurus/pull/4369) docs(v2): various improvements ([@lex111](https://github.com/lex111)) - - [#4362](https://github.com/facebook/docusaurus/pull/4362) docs(v2): Add stryker-mutator.io to showcase ([@nicojs](https://github.com/nicojs)) - - [#4354](https://github.com/facebook/docusaurus/pull/4354) docs(v2): add trpgengine showcase ([@moonrailgun](https://github.com/moonrailgun)) - - [#4346](https://github.com/facebook/docusaurus/pull/4346) docs(v1): update phrasing for website dir relative to docs dir ([@aukokyong](https://github.com/aukokyong)) - - [#4338](https://github.com/facebook/docusaurus/pull/4338) docs(v2): update showcase instruction regarding tags + fix site tags ([@slorber](https://github.com/slorber)) - - [#4331](https://github.com/facebook/docusaurus/pull/4331) docs(v2): add ocpeasy to users ([@dbrrt](https://github.com/dbrrt)) - - [#4307](https://github.com/facebook/docusaurus/pull/4307) docs(v2): Add RactivePlayer to showcase ([@ysulyma](https://github.com/ysulyma)) - - [#4297](https://github.com/facebook/docusaurus/pull/4297) docs(v2): Fix examples by importing React ([@roydukkey](https://github.com/roydukkey)) - - [#4296](https://github.com/facebook/docusaurus/pull/4296) docs(v2): move migrated sites from v1 to v2 showcase ([@lisa761](https://github.com/lisa761)) - - [#4293](https://github.com/facebook/docusaurus/pull/4293) docs(v2): Added React Native ARIA to showcase ([@theankurkedia](https://github.com/theankurkedia)) - - [#4284](https://github.com/facebook/docusaurus/pull/4284) docs(v2): Add AttoBot website to showcase page ([@wolf20482](https://github.com/wolf20482)) - - [#4285](https://github.com/facebook/docusaurus/pull/4285) docs(v2): escape more jsx in mdx files for Crowdin ([@slorber](https://github.com/slorber)) - - [#4283](https://github.com/facebook/docusaurus/pull/4283) docs(v2): Add Postgres.ai to showcase ([@NikolayS](https://github.com/NikolayS)) - - [#4282](https://github.com/facebook/docusaurus/pull/4282) docs: update Netlify deploy status badge ([@slorber](https://github.com/slorber)) - - [#4259](https://github.com/facebook/docusaurus/pull/4259) docs(v2): improve cli docs ([@massoudmaboudi](https://github.com/massoudmaboudi)) - - [#4266](https://github.com/facebook/docusaurus/pull/4266) docs(v2): update agilets banner ([@bennodev19](https://github.com/bennodev19)) - - [#4263](https://github.com/facebook/docusaurus/pull/4263) docs(v2): remove npx and use github action to configure ssh key ([@MatanBobi](https://github.com/MatanBobi)) - - [#4262](https://github.com/facebook/docusaurus/pull/4262) docs(v2): Added kotest to showcase ([@sksamuel](https://github.com/sksamuel)) - - [#4256](https://github.com/facebook/docusaurus/pull/4256) docs(v2): Add docusaurus2-graphql-doc-generator to community resources ([@edno](https://github.com/edno)) - - [#4252](https://github.com/facebook/docusaurus/pull/4252) docs(v2): Added mailgo to showcase ([@manzinello](https://github.com/manzinello)) - - [#4251](https://github.com/facebook/docusaurus/pull/4251) docs(v2): Add Axioms to showcase ([@limkinZero](https://github.com/limkinZero)) - - [#4237](https://github.com/facebook/docusaurus/pull/4237) docs(v2): Replace mbt-bundle by sicope-model ([@tienvx](https://github.com/tienvx)) - - [#4236](https://github.com/facebook/docusaurus/pull/4236) docs(v2): v2 migration should mention RSS feed url change ([@slorber](https://github.com/slorber)) - - [#4230](https://github.com/facebook/docusaurus/pull/4230) docs(v2): fix npm/yarn command example for swizzling TypeScript theme components ([@YashTotale](https://github.com/YashTotale)) - - [#4229](https://github.com/facebook/docusaurus/pull/4229) docs(v2): Fix link to slash introduction svg ([@SamChou19815](https://github.com/SamChou19815)) - - [#4226](https://github.com/facebook/docusaurus/pull/4226) docs(v2): Removing wrong parenthesis on image variable ([@juancarlosjr97](https://github.com/juancarlosjr97)) - - [#4225](https://github.com/facebook/docusaurus/pull/4225) docs(v2): added Apache APISIX ([@juzhiyuan](https://github.com/juzhiyuan)) - - [#4224](https://github.com/facebook/docusaurus/pull/4224) docs(v2): Add MikroORM site to showcase page ([@B4nan](https://github.com/B4nan)) - - [#4220](https://github.com/facebook/docusaurus/pull/4220) Add WebdriverIO docs page as showcase ([@christian-bromann](https://github.com/christian-bromann)) - - [#4210](https://github.com/facebook/docusaurus/pull/4210) misc: add requirements for sites being added to showcase ([@lex111](https://github.com/lex111)) - - [#4207](https://github.com/facebook/docusaurus/pull/4207) docs(v2): Added Console Table Documentation Site to showcase ([@ayonious](https://github.com/ayonious)) - - [#4204](https://github.com/facebook/docusaurus/pull/4204) docs(v1): fixing a broken link in blog posts ([@ayonious](https://github.com/ayonious)) - - [#4178](https://github.com/facebook/docusaurus/pull/4178) docs(v2): localize 404 page with Netlify + docs ([@slorber](https://github.com/slorber)) - - [#4177](https://github.com/facebook/docusaurus/pull/4177) docs(v2): Add docusaurus-plugin-remote-content to resources list ([@RDIL](https://github.com/RDIL)) - - [#4172](https://github.com/facebook/docusaurus/pull/4172) docs(v2): Add react-hooks.org to showcase ([@imbhargav5](https://github.com/imbhargav5)) - - [#4173](https://github.com/facebook/docusaurus/pull/4173) docs(v2): typo fixing double colon ([@ayonious](https://github.com/ayonious)) - - [#4164](https://github.com/facebook/docusaurus/pull/4164) docs(v2): add a note for images not rendered on dev server ([@yuval-hazaz](https://github.com/yuval-hazaz)) - - [#4161](https://github.com/facebook/docusaurus/pull/4161) docs(v2): Add docusaurus-theme-github-codeblock ([@christian-bromann](https://github.com/christian-bromann)) - - [#4158](https://github.com/facebook/docusaurus/pull/4158) docs(v2): improve bad static assets doc + remove some useless useBaseUrl usage ([@slorber](https://github.com/slorber)) - - [#4144](https://github.com/facebook/docusaurus/pull/4144) docs(v2): community docs typo fix ([@ayonious](https://github.com/ayonious)) - - [#4143](https://github.com/facebook/docusaurus/pull/4143) docs(v2): guide docs typo fix ([@ayonious](https://github.com/ayonious)) - - [#4141](https://github.com/facebook/docusaurus/pull/4141) docs(v2): plugins docs typo fix ([@ayonious](https://github.com/ayonious)) - - [#4139](https://github.com/facebook/docusaurus/pull/4139) docs(v2): Add Rematch site to showcase page ([@semoal](https://github.com/semoal)) - - [#4128](https://github.com/facebook/docusaurus/pull/4128) docs(v2): remove duplicate link from docs about Docusaurus1 ([@ayonious](https://github.com/ayonious)) - - [#4129](https://github.com/facebook/docusaurus/pull/4129) docs(v2): typo fix in Migration Docs ([@ayonious](https://github.com/ayonious)) - - [#4127](https://github.com/facebook/docusaurus/pull/4127) docs(v2): remove unnecessary brace from installation doc ([@ayonious](https://github.com/ayonious)) - - [#4130](https://github.com/facebook/docusaurus/pull/4130) docs(v2): typo in i18n docs ([@ayonious](https://github.com/ayonious)) - - [#4112](https://github.com/facebook/docusaurus/pull/4112) docs(v2): Do not encourage using the permalink prop ([@slorber](https://github.com/slorber)) - - [#4106](https://github.com/facebook/docusaurus/pull/4106) docs(v2): update broken link on resources page ([@eric-hc](https://github.com/eric-hc)) - - [#4084](https://github.com/facebook/docusaurus/pull/4084) docs(v2): Use the TOCInline component in config doc ([@slorber](https://github.com/slorber)) - - [#4020](https://github.com/facebook/docusaurus/pull/4020) docs(v2): 2020 recap blog post ([@slorber](https://github.com/slorber)) - - [#4009](https://github.com/facebook/docusaurus/pull/4009) docs(v2): add hideableSidebar option to config demo ([@natac13](https://github.com/natac13)) - - [#4062](https://github.com/facebook/docusaurus/pull/4062) docs(v2): Add codesandbox integration ([@sammychinedu2ky](https://github.com/sammychinedu2ky)) - - [#4058](https://github.com/facebook/docusaurus/pull/4058) docs(v2): Include new.docusaurus.io CodeSandbox in issue templates + README ([@slorber](https://github.com/slorber)) - - [#4053](https://github.com/facebook/docusaurus/pull/4053) docs(v2): Add Eightshift Docs site to showcase page ([@iruzevic](https://github.com/iruzevic)) - - [#4048](https://github.com/facebook/docusaurus/pull/4048) docs(v1): Docker: remind the user to use the --host flag ([@tomsfernandez](https://github.com/tomsfernandez)) - - [#4047](https://github.com/facebook/docusaurus/pull/4047) docs(v1): version page should recommend v2 ([@slorber](https://github.com/slorber)) - - [#4046](https://github.com/facebook/docusaurus/pull/4046) docs(v2): add sciwp to showcase ([@edulazaro](https://github.com/edulazaro)) - - [#4036](https://github.com/facebook/docusaurus/pull/4036) docs(v2): Add Nodify to showcase ([@miroiu](https://github.com/miroiu)) - - [#4038](https://github.com/facebook/docusaurus/pull/4038) docs(v1): suggest to use Docusaurus 2 even for non-FB websites ([@slorber](https://github.com/slorber)) - - [#4026](https://github.com/facebook/docusaurus/pull/4026) docs(v2): Add FlexIt to showcase ([@ataft](https://github.com/ataft)) - - [#4022](https://github.com/facebook/docusaurus/pull/4022) docs: fix typo from 'dissapear' to 'disappear' ([@vamsi3](https://github.com/vamsi3)) - - [#4002](https://github.com/facebook/docusaurus/pull/4002) docs(v2): Add how to run your own DocSearch ([@TheodoreChu](https://github.com/TheodoreChu)) - - [#3997](https://github.com/facebook/docusaurus/pull/3997) docs(v2): Add Datagit site to showcase page ([@massoudmaboudi](https://github.com/massoudmaboudi)) - - [#3990](https://github.com/facebook/docusaurus/pull/3990) docs(v2): Add wiki-powerto site showcase ([@linyuxuanlin](https://github.com/linyuxuanlin)) - - [#3991](https://github.com/facebook/docusaurus/pull/3991) docs(v2): add overwriting css variables for dark mode ([@natac13](https://github.com/natac13)) - - [#3987](https://github.com/facebook/docusaurus/pull/3987) docs(v2): Add AgileTs site to showcase page ([@bennodev19](https://github.com/bennodev19)) - - [#3978](https://github.com/facebook/docusaurus/pull/3978) docs(v2): Add documentation for docs multi-instance support ([@slorber](https://github.com/slorber)) - - [#3977](https://github.com/facebook/docusaurus/pull/3977) docs(v2): nudge users to add site to showcase ([@slorber](https://github.com/slorber)) - - [#3975](https://github.com/facebook/docusaurus/pull/3975) docs(v2): Reorganize/split the guides doc / markdown sections ([@slorber](https://github.com/slorber)) - - [#3976](https://github.com/facebook/docusaurus/pull/3976) docs(v2): Add AI-Speaker site to showcase page ([@asystentka-jolka](https://github.com/asystentka-jolka)) - - [#3974](https://github.com/facebook/docusaurus/pull/3974) docs(v2): doc typo on sidebar admonition ([@slorber](https://github.com/slorber)) - - [#3962](https://github.com/facebook/docusaurus/pull/3962) docs(v2): Add migration info doc regarding docs folder location ([@slorber](https://github.com/slorber)) - - [#3950](https://github.com/facebook/docusaurus/pull/3950) docs(v2): update GitHub entreprise deployment doc ([@samhrncir](https://github.com/samhrncir)) - - [#3945](https://github.com/facebook/docusaurus/pull/3945) docs(v2): Added information about setting `/` in routeBasePath ([@Siemienik](https://github.com/Siemienik)) -- `docusaurus-theme-classic` - - [#4356](https://github.com/facebook/docusaurus/pull/4356) polish(v2): [theme-classic] add Chinese translations (zh-Hant & zh-Hans) ([@MisterFISHUP](https://github.com/MisterFISHUP)) -- `docusaurus` - - [#4126](https://github.com/facebook/docusaurus/pull/4126) docs(v2): do not recommend using useBaseUrl() hook in most cases ([@slorber](https://github.com/slorber)) - - [#4049](https://github.com/facebook/docusaurus/pull/4049) docs(v1): version page should recommend v2 (bis) ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-theme-classic`, `docusaurus` - - [#4014](https://github.com/facebook/docusaurus/pull/4014) docs(v2): i18n doc + polish ([@slorber](https://github.com/slorber)) -- `docusaurus-cssnano-preset`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-bootstrap`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` - - [#4034](https://github.com/facebook/docusaurus/pull/4034) docs(v2): Add READMEs to v2 packages ([@RDIL](https://github.com/RDIL)) -- `docusaurus-init` - - [#3881](https://github.com/facebook/docusaurus/pull/3881) docs(v2): update FB OSS logo ([@Simek](https://github.com/Simek)) - -#### :house: Internal - -- Other - - [#4372](https://github.com/facebook/docusaurus/pull/4372) chore(v1): release docusaurus v1.14.7 ([@slorber](https://github.com/slorber)) - - [#4368](https://github.com/facebook/docusaurus/pull/4368) chore(deps): bump elliptic from 6.5.3 to 6.5.4 ([@dependabot[bot]](https://github.com/apps/dependabot)) - - [#4365](https://github.com/facebook/docusaurus/pull/4365) chore: unstable yarnlock ([@slorber](https://github.com/slorber)) - - [#4337](https://github.com/facebook/docusaurus/pull/4337) misc: restore build size bot ([@slorber](https://github.com/slorber)) - - [#4289](https://github.com/facebook/docusaurus/pull/4289) chore(v2): remove docs for alpha v69 ([@lex111](https://github.com/lex111)) - - [#4253](https://github.com/facebook/docusaurus/pull/4253) chore(v2): remove docs for alpha v68 ([@lex111](https://github.com/lex111)) - - [#4248](https://github.com/facebook/docusaurus/pull/4248) chore(v2): Fix build size bot ([@slorber](https://github.com/slorber)) - - [#4214](https://github.com/facebook/docusaurus/pull/4214) chore(v2): setup for i18n staging deployment ([@slorber](https://github.com/slorber)) - - [#4159](https://github.com/facebook/docusaurus/pull/4159) chore(v2): fix build size bot again ([@slorber](https://github.com/slorber)) - - [#4156](https://github.com/facebook/docusaurus/pull/4156) chore(v2): fix build size bot monitoring of js/css assets ([@slorber](https://github.com/slorber)) - - [#4100](https://github.com/facebook/docusaurus/pull/4100) chore(v2): remove docs for alpha v66 ([@lex111](https://github.com/lex111)) - - [#4077](https://github.com/facebook/docusaurus/pull/4077) chore(v2): fix unstable master yarn.lock ([@slorber](https://github.com/slorber)) - - [#4063](https://github.com/facebook/docusaurus/pull/4063) chore(v2): Regen codesandbox templates + add template: "docusaurus" ([@slorber](https://github.com/slorber)) - - [#4056](https://github.com/facebook/docusaurus/pull/4056) chore(v2): update codesandbox redirect ([@slorber](https://github.com/slorber)) - - [#4041](https://github.com/facebook/docusaurus/pull/4041) chore(v1): revert v1 netlify.toml ([@slorber](https://github.com/slorber)) - - [#4040](https://github.com/facebook/docusaurus/pull/4040) chore(v1): upgrade v1 Crowdin cli + CI config ([@slorber](https://github.com/slorber)) - - [#4030](https://github.com/facebook/docusaurus/pull/4030) chore(v2): install Crowdin cli through npm package ([@slorber](https://github.com/slorber)) - - [#4003](https://github.com/facebook/docusaurus/pull/4003) chore: add DevContainer config for GitHub codespaces ([@kumaraditya303](https://github.com/kumaraditya303)) - - [#4001](https://github.com/facebook/docusaurus/pull/4001) chore(v2): Upgrade crowdin ([@slorber](https://github.com/slorber)) - - [#3995](https://github.com/facebook/docusaurus/pull/3995) chore(v2): remove docs for alpha v65 ([@lex111](https://github.com/lex111)) - - [#3960](https://github.com/facebook/docusaurus/pull/3960) fix(v2): remove duplicate section on Versions page ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#4370](https://github.com/facebook/docusaurus/pull/4370) chore(v2): update infima ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#4361](https://github.com/facebook/docusaurus/pull/4361) refactor(v2): remove duplicated lodash dependencies and import only what needed ([@armano2](https://github.com/armano2)) -- `docusaurus-1.x`, `docusaurus` - - [#4270](https://github.com/facebook/docusaurus/pull/4270) chore(v2): upgrade react-dev-utils ([@yangshun](https://github.com/yangshun)) -- `docusaurus-init`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-types`, `docusaurus` - - [#4264](https://github.com/facebook/docusaurus/pull/4264) chore(v2): bump/align deps in monorepo: commander, semver, fs-extra ([@Simek](https://github.com/Simek)) -- `docusaurus` - - [#4265](https://github.com/facebook/docusaurus/pull/4265) chore(v2): PostCSS peer dep fix ([@RDIL](https://github.com/RDIL)) - - [#4091](https://github.com/facebook/docusaurus/pull/4091) refactor(v2): Switch from inquirer to prompts ([@RDIL](https://github.com/RDIL)) - - [#4066](https://github.com/facebook/docusaurus/pull/4066) chore(v2): Update a few dependencies ([@RDIL](https://github.com/RDIL)) -- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#4148](https://github.com/facebook/docusaurus/pull/4148) chore(v2): upgrade dependencies ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-pwa` - - [#4120](https://github.com/facebook/docusaurus/pull/4120) chore(v2): Update workbox to v6 ([@RDIL](https://github.com/RDIL)) -- `docusaurus-utils`, `docusaurus` - - [#4081](https://github.com/facebook/docusaurus/pull/4081) chore(v2): Update webpack-related dependencies, pre-work to migrate to Webpack 5 ([@RDIL](https://github.com/RDIL)) -- `docusaurus-init`, `docusaurus` - - [#4012](https://github.com/facebook/docusaurus/pull/4012) chore(v2): docusaurus-init: switch from inquirer to prompts ([@RDIL](https://github.com/RDIL)) -- `docusaurus-plugin-sitemap` - - [#4005](https://github.com/facebook/docusaurus/pull/4005) chore(v2): prettier fixes ([@slorber](https://github.com/slorber)) -- `docusaurus-migrate` - - [#3988](https://github.com/facebook/docusaurus/pull/3988) chore(v2): fix date-sensitive test fixture ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` - - [#3959](https://github.com/facebook/docusaurus/pull/3959) chore(v2): fix windows Jest tests ([@slorber](https://github.com/slorber)) - -#### :running_woman: Performance - -- `docusaurus-cssnano-preset`, `docusaurus-plugin-content-blog`, `docusaurus` - - [#4355](https://github.com/facebook/docusaurus/pull/4355) perf(v2): improve blog mdx-loader and postcss loader ([@lex111](https://github.com/lex111)) - -#### Committers: 70 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Ali Saki ([@3alisaki](https://github.com/3alisaki)) -- Andrew Taft ([@ataft](https://github.com/ataft)) -- Ankur Kedia ([@theankurkedia](https://github.com/theankurkedia)) -- Apurva Ojas ([@apurvaojas](https://github.com/apurvaojas)) -- Armano ([@armano2](https://github.com/armano2)) -- Arthur ([@ArtFlag](https://github.com/ArtFlag)) -- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) -- Ben ([@ben-qnimble](https://github.com/ben-qnimble)) -- BennoDev ([@bennodev19](https://github.com/bennodev19)) -- Bhargav Ponnapalli ([@imbhargav5](https://github.com/imbhargav5)) -- Christian Bromann ([@christian-bromann](https://github.com/christian-bromann)) -- David Barrat ([@dbrrt](https://github.com/dbrrt)) -- Eduardo Lázaro ([@edulazaro](https://github.com/edulazaro)) -- Eric Carboni ([@eric-hc](https://github.com/eric-hc)) -- Grégory Heitz ([@edno](https://github.com/edno)) -- Ivan Ružević ([@iruzevic](https://github.com/iruzevic)) -- Jessica Lin ([@jlin27](https://github.com/jlin27)) -- Joel M ([@9oelM](https://github.com/9oelM)) -- Joel Marcey ([@JoelMarcey](https://github.com/JoelMarcey)) -- Jola ([@asystentka-jolka](https://github.com/asystentka-jolka)) -- Juan Carlos Blanco Delgado ([@juancarlosjr97](https://github.com/juancarlosjr97)) -- Kevin Viglucci ([@viglucci](https://github.com/viglucci)) -- Kumar Aditya ([@kumaraditya303](https://github.com/kumaraditya303)) -- Lisa Chandra ([@lisa761](https://github.com/lisa761)) -- LittleboyHarry ([@LittleboyHarry](https://github.com/LittleboyHarry)) -- Long Ho ([@longlho](https://github.com/longlho)) -- Martin Adámek ([@B4nan](https://github.com/B4nan)) -- Massoud Maboudi ([@massoudmaboudi](https://github.com/massoudmaboudi)) -- Matan Borenkraout ([@MatanBobi](https://github.com/MatanBobi)) -- Matt Oestreich ([@oze4](https://github.com/oze4)) -- Matteo Manzinello ([@manzinello](https://github.com/manzinello)) -- Miroiu Emanuel ([@miroiu](https://github.com/miroiu)) -- Mohd Shad Mirza ([@iamshadmirza](https://github.com/iamshadmirza)) -- Nahiyan Kamal ([@ayonious](https://github.com/ayonious)) -- Nathan Bosscher ([@ntbosscher](https://github.com/ntbosscher)) -- Nico Jansen ([@nicojs](https://github.com/nicojs)) -- Nikolay Samokhvalov ([@NikolayS](https://github.com/NikolayS)) -- Pablo Vidal ([@limkinZero](https://github.com/limkinZero)) -- Power Lin ([@linyuxuanlin](https://github.com/linyuxuanlin)) -- Reece Dunham ([@RDIL](https://github.com/RDIL)) -- Saihajpreet Singh ([@saihaj](https://github.com/saihaj)) -- Sam Hrncir ([@samhrncir](https://github.com/samhrncir)) -- Sam Sam ([@sksamuel](https://github.com/sksamuel)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Sean Campbell ([@natac13](https://github.com/natac13)) -- Sergio Moreno ([@semoal](https://github.com/semoal)) -- Siemienik Pawel ([@Siemienik](https://github.com/Siemienik)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Theodore Chu ([@TheodoreChu](https://github.com/TheodoreChu)) -- Tien Vo Xuan ([@tienvx](https://github.com/tienvx)) -- Tomas Fernandez ([@tomsfernandez](https://github.com/tomsfernandez)) -- Vamsi Krishna Reddy Satti ([@vamsi3](https://github.com/vamsi3)) -- Welly ([@wellyshen](https://github.com/wellyshen)) -- Yamagishi Kazutoshi ([@ykzts](https://github.com/ykzts)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) -- Yash Totale ([@YashTotale](https://github.com/YashTotale)) -- Yuri Sulyma ([@ysulyma](https://github.com/ysulyma)) -- Yuval Hazaz ([@yuval-hazaz](https://github.com/yuval-hazaz)) -- [@MisterFISHUP](https://github.com/MisterFISHUP) -- [@aukokyong](https://github.com/aukokyong) -- [@philipp985](https://github.com/philipp985) -- [@roydukkey](https://github.com/roydukkey) -- [@sammychinedu2ky](https://github.com/sammychinedu2ky) -- [@saydo17](https://github.com/saydo17) -- [@tokarchyn](https://github.com/tokarchyn) -- [@wolf20482](https://github.com/wolf20482) -- moonrailgun ([@moonrailgun](https://github.com/moonrailgun)) -- Çağlar Turalı ([@caglarturali](https://github.com/caglarturali)) -- 琚致远 ([@juzhiyuan](https://github.com/juzhiyuan)) - -## 2.0.0-alpha.70 (2020-12-17) - -#### :rocket: New Feature - -- `docusaurus` - - [#3932](https://github.com/facebook/docusaurus/pull/3932) feat(v2): Add Root theme element ([@slorber](https://github.com/slorber)) -- `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#3916](https://github.com/facebook/docusaurus/pull/3916) feat(v2): Add localeDropdown navbar item type + i18n localeConfigs field ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-types` - - [#3904](https://github.com/facebook/docusaurus/pull/3904) feat(v2): inline table-of-contents + refactor TOC ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs` - - [#3888](https://github.com/facebook/docusaurus/pull/3888) feat(v2): add custom props for consumption by swizzled sidebar ([@oriooctopus](https://github.com/oriooctopus)) -- `docusaurus-plugin-content-blog` - - [#3842](https://github.com/facebook/docusaurus/pull/3842) feat(v2): enable feeds by default in blog plugin ([@cindygu4](https://github.com/cindygu4)) -- Other - - [#3827](https://github.com/facebook/docusaurus/pull/3827) feat(v2): add automated canary releases ([@slorber](https://github.com/slorber)) - - [#3761](https://github.com/facebook/docusaurus/pull/3761) feat(v2): Added Lighthouse CI to PR checks ([@sarthakkundra](https://github.com/sarthakkundra)) -- `docusaurus-1.x`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` - - [#3325](https://github.com/facebook/docusaurus/pull/3325) feat(v2): core v2 i18n support + Docusaurus site Crowdin integration ([@slorber](https://github.com/slorber)) - -#### :boom: Breaking Change - -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-types` - - [#3904](https://github.com/facebook/docusaurus/pull/3904) feat(v2): inline table-of-contents + refactor TOC ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-blog` - - [#3842](https://github.com/facebook/docusaurus/pull/3842) feat(v2): enable feeds by default in blog plugin ([@cindygu4](https://github.com/cindygu4)) - -#### :bug: Bug Fix - -- `docusaurus` - - [#3922](https://github.com/facebook/docusaurus/pull/3922) fix(v2): fix navbar items issue on Windows? ([@slorber](https://github.com/slorber)) - - [#3920](https://github.com/facebook/docusaurus/pull/3920) fix(v2): i18n translation extractor should handle JSX formatting edge cases better ([@slorber](https://github.com/slorber)) - - [#3896](https://github.com/facebook/docusaurus/pull/3896) fix(v2): do not treat at-rules during CSS minification ([@lex111](https://github.com/lex111)) - - [#3869](https://github.com/facebook/docusaurus/pull/3869) fix(v2): load plugin commands async to fix broken plugin CLI commands `docs:version` ([@aeneasr](https://github.com/aeneasr)) -- `docusaurus-theme-classic` - - [#3921](https://github.com/facebook/docusaurus/pull/3921) fix(v2): remove useless console log ([@slorber](https://github.com/slorber)) - - [#3895](https://github.com/facebook/docusaurus/pull/3895) fix(v2): use proper element for pagination nav label ([@lex111](https://github.com/lex111)) - - [#3882](https://github.com/facebook/docusaurus/pull/3882) fix(v2): improve Footer structure, add class names, use Infima transition ([@Simek](https://github.com/Simek)) - - [#3877](https://github.com/facebook/docusaurus/pull/3877) fix(v2): dynamic dark mode detection without toggle widget ([@hmil](https://github.com/hmil)) - - [#3854](https://github.com/facebook/docusaurus/pull/3854) fix(v2): refactor icons in theme-classic, fix swizzle issue ([@Simek](https://github.com/Simek)) - - [#3823](https://github.com/facebook/docusaurus/pull/3823) fix(v2): support rendering of singular tabs ([@aeneasr](https://github.com/aeneasr)) - - [#3817](https://github.com/facebook/docusaurus/pull/3817) fix(v2): Allow footer logo at attribute to be empty ([@aarongarciah](https://github.com/aarongarciah)) -- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` - - [#3900](https://github.com/facebook/docusaurus/pull/3900) fix(v2): correct typo in metas generated for Twitter cards ([@mpsq](https://github.com/mpsq)) -- Other - - [#3872](https://github.com/facebook/docusaurus/pull/3872) chore: add missing v1 generated files to ignores ([@Simek](https://github.com/Simek)) - - [#3833](https://github.com/facebook/docusaurus/pull/3833) fix(v2): temporary: disable crowdin until PR env variable permission fixed ([@slorber](https://github.com/slorber)) -- `stylelint-copyright` - - [#3852](https://github.com/facebook/docusaurus/pull/3852) fix(v2): to fix the canary release GH workflow ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-search-algolia` - - [#3853](https://github.com/facebook/docusaurus/pull/3853) fix(v2): fix DocSearch keyboard navigator ([@francoischalifour](https://github.com/francoischalifour)) - - [#3837](https://github.com/facebook/docusaurus/pull/3837) fix(v2): update SearchPage styling, fix appearance in dark mode ([@Simek](https://github.com/Simek)) - - [#3828](https://github.com/facebook/docusaurus/pull/3828) fix(v2): restore Algolia search ([@lex111](https://github.com/lex111)) - - [#3819](https://github.com/facebook/docusaurus/pull/3819) feat(search): update DocSearch to alpha.31 ([@francoischalifour](https://github.com/francoischalifour)) -- `docusaurus-plugin-content-docs` - - [#3839](https://github.com/facebook/docusaurus/pull/3839) fix(v2): remove unnecessary backtick in output ([@sivaraam](https://github.com/sivaraam)) -- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#3829](https://github.com/facebook/docusaurus/pull/3829) fix(v2): fix search ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus` - - [#3824](https://github.com/facebook/docusaurus/pull/3824) fix(v2): update notifier dist tag ([@slorber](https://github.com/slorber)) - -#### :nail_care: Polish - -- `docusaurus` - - [#3880](https://github.com/facebook/docusaurus/pull/3880) polish(v2): improve docusaurus deploy logs ([@slorber](https://github.com/slorber)) - -#### :memo: Documentation - -- [#3931](https://github.com/facebook/docusaurus/pull/3931) docs(v2): blog.md with docs: false, for blog-only mode ([@Romstar](https://github.com/Romstar)) -- [#3924](https://github.com/facebook/docusaurus/pull/3924) docs(v2): Removed unnecessary closing parenthesis ([@Varshit07](https://github.com/Varshit07)) -- [#3928](https://github.com/facebook/docusaurus/pull/3928) docs(v2): add FoalTS to showcase page ([@LoicPoullain](https://github.com/LoicPoullain)) -- [#3899](https://github.com/facebook/docusaurus/pull/3899) docs(v2): Move sidebar content to its own page ([@ArtFlag](https://github.com/ArtFlag)) -- [#3856](https://github.com/facebook/docusaurus/pull/3856) docs(v2): typo ([@borool](https://github.com/borool)) -- [#3891](https://github.com/facebook/docusaurus/pull/3891) docs(v2): Wrap section about custom domains in :::info ([@Alex1304](https://github.com/Alex1304)) -- [#3871](https://github.com/facebook/docusaurus/pull/3871) docs(v2): missing `` mdx import ([@slorber](https://github.com/slorber)) -- [#3873](https://github.com/facebook/docusaurus/pull/3873) docs(v2): From docusaurus-migrate to @docusaurus/migrate ([@manzinello](https://github.com/manzinello)) -- [#3867](https://github.com/facebook/docusaurus/pull/3867) docs(v2): Add docusaurus-plugin-moesif to community plugins ([@dgilling](https://github.com/dgilling)) -- [#3851](https://github.com/facebook/docusaurus/pull/3851) docs(v2): Fixed Typo: Hided => Hidden ([@woodrufs](https://github.com/woodrufs)) -- [#3832](https://github.com/facebook/docusaurus/pull/3832) docs(v2): Add wasp to showcase ([@matijaSos](https://github.com/matijaSos)) -- [#3813](https://github.com/facebook/docusaurus/pull/3813) docs(v2): render deployment doc ([@davidmauskop](https://github.com/davidmauskop)) -- [#3835](https://github.com/facebook/docusaurus/pull/3835) docs(v2): update Client API docs page ([@Simek](https://github.com/Simek)) -- [#3831](https://github.com/facebook/docusaurus/pull/3831) docs(v2): Docs refactoring and reorganization ([@slorber](https://github.com/slorber)) - -#### :house: Internal - -- Other - - [#3912](https://github.com/facebook/docusaurus/pull/3912) chore(v2): remove docs for alpha v64 ([@lex111](https://github.com/lex111)) - - [#3907](https://github.com/facebook/docusaurus/pull/3907) chore(ci): fix canary release filtering ([@slorber](https://github.com/slorber)) - - [#3902](https://github.com/facebook/docusaurus/pull/3902) chore(deps): bump ini from 1.3.5 to 1.3.7 ([@dependabot[bot]](https://github.com/apps/dependabot)) - - [#3884](https://github.com/facebook/docusaurus/pull/3884) chore(ci): increase Lighthouse CI max_timeout ([@Simek](https://github.com/Simek)) - - [#3883](https://github.com/facebook/docusaurus/pull/3883) chore(v2): remove docs for alpha v62-63 ([@lex111](https://github.com/lex111)) - - [#3863](https://github.com/facebook/docusaurus/pull/3863) chore(ci): run V1 Build and Migration CLI tests conditionally on CI ([@Simek](https://github.com/Simek)) - - [#3861](https://github.com/facebook/docusaurus/pull/3861) chore(ci): reduce number of jobs, remove build from lighthouse pipeline ([@Simek](https://github.com/Simek)) - - [#3860](https://github.com/facebook/docusaurus/pull/3860) chore: add Yarn v2 cache directory to ignores ([@Simek](https://github.com/Simek)) - - [#3858](https://github.com/facebook/docusaurus/pull/3858) chore(v2): disable Crowdin for deploy previews ([@slorber](https://github.com/slorber)) - - [#3857](https://github.com/facebook/docusaurus/pull/3857) fix(v2): fix Crowdin ci commands ([@slorber](https://github.com/slorber)) - - [#3849](https://github.com/facebook/docusaurus/pull/3849) chore(ci): CI scripts cleanup, add Node 14 runs, bump checkout action ([@Simek](https://github.com/Simek)) - - [#3850](https://github.com/facebook/docusaurus/pull/3850) chore(v2): i18n CI: add write-translations call ([@slorber](https://github.com/slorber)) - - [#3848](https://github.com/facebook/docusaurus/pull/3848) chore(v2): fix CI typo ([@slorber](https://github.com/slorber)) - - [#3847](https://github.com/facebook/docusaurus/pull/3847) chore(v2): wire production Crowdin project + setup ([@slorber](https://github.com/slorber)) - - [#3846](https://github.com/facebook/docusaurus/pull/3846) chore(v2): fix PRs not able to add lighthouse/buildsize comment from works ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` - - [#3865](https://github.com/facebook/docusaurus/pull/3865) chore(v2): fix ignore paths and Prettier commands in themes ([@Simek](https://github.com/Simek)) -- `docusaurus-cssnano-preset`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus` - - [#3844](https://github.com/facebook/docusaurus/pull/3844) chore(v2): fix several lint warnings, add missing types, cleanup ([@Simek](https://github.com/Simek)) -- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia` - - [#3838](https://github.com/facebook/docusaurus/pull/3838) refactor(v2): extract site title formatter to theme-common util ([@Simek](https://github.com/Simek)) - -#### Committers: 23 - -- Aarón García Hervás ([@aarongarciah](https://github.com/aarongarciah)) -- Alex1304 ([@Alex1304](https://github.com/Alex1304)) -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Arthur ([@ArtFlag](https://github.com/ArtFlag)) -- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) -- Cindy Gu ([@cindygu4](https://github.com/cindygu4)) -- Derric Gilling ([@dgilling](https://github.com/dgilling)) -- François Chalifour ([@francoischalifour](https://github.com/francoischalifour)) -- Hadrien Milano ([@hmil](https://github.com/hmil)) -- Kaartic Sivaraam ([@sivaraam](https://github.com/sivaraam)) -- Loïc Poullain ([@LoicPoullain](https://github.com/LoicPoullain)) -- Matija Sosic ([@matijaSos](https://github.com/matijaSos)) -- Matteo Manzinello ([@manzinello](https://github.com/manzinello)) -- Méril ([@mpsq](https://github.com/mpsq)) -- Oliver Ullman ([@oriooctopus](https://github.com/oriooctopus)) -- Rami ([@Romstar](https://github.com/Romstar)) -- Sarthak kundra ([@sarthakkundra](https://github.com/sarthakkundra)) -- Stephen Woodruff ([@woodrufs](https://github.com/woodrufs)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Varshit Shah ([@Varshit07](https://github.com/Varshit07)) -- [@borool](https://github.com/borool) -- [@davidmauskop](https://github.com/davidmauskop) -- hackerman ([@aeneasr](https://github.com/aeneasr)) - -## 2.0.0-alpha.69 (2020-11-24) - -#### :rocket: New Feature - -- `docusaurus-types`, `docusaurus` - - [#3802](https://github.com/facebook/docusaurus/pull/3802) feat(v2): add baseUrlIssueBanner configuration to disable banner ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#3807](https://github.com/facebook/docusaurus/pull/3807) chore(v2): upgrade Infima to v0.2.0-alpha.18 ([@lex111](https://github.com/lex111)) - - [#3806](https://github.com/facebook/docusaurus/pull/3806) fix(v2): remove aria-hidden attr from anchor link of heading ([@lex111](https://github.com/lex111)) - - [#3784](https://github.com/facebook/docusaurus/pull/3784) fix(v2): fix missing logo in dark theme when darkSrc was not set ([@Simek](https://github.com/Simek)) -- `docusaurus-theme-search-algolia` - - [#3804](https://github.com/facebook/docusaurus/pull/3804) fix(v2): Algolia: allow contextualSearch + facetFilters ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#3796](https://github.com/facebook/docusaurus/pull/3796) Adds createRequire for preset resolution ([@arcanis](https://github.com/arcanis)) - -#### :memo: Documentation - -- [#3803](https://github.com/facebook/docusaurus/pull/3803) docs(v2): fix docusaurus init issue when not using @latest ([@slorber](https://github.com/slorber)) -- [#3785](https://github.com/facebook/docusaurus/pull/3785) docs(v2): recommend Docusaurus 2 usage ([@slorber](https://github.com/slorber)) -- [#3783](https://github.com/facebook/docusaurus/pull/3783) docs(v2): remove @next tags needed to install v2 packages ([@slorber](https://github.com/slorber)) -- [#3781](https://github.com/facebook/docusaurus/pull/3781) docs(v2): rename zeit to vercel ([@camiluc](https://github.com/camiluc)) - -#### :house: Internal - -- [#3800](https://github.com/facebook/docusaurus/pull/3800) chore(v2): remove useless stylelint-copyright peerDependency ([@slorber](https://github.com/slorber)) -- [#3786](https://github.com/facebook/docusaurus/pull/3786) chore(v2): ensure publishConfig.access presence with tests ([@slorber](https://github.com/slorber)) - -#### Committers: 5 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) -- Maël Nison ([@arcanis](https://github.com/arcanis)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- [@camiluc](https://github.com/camiluc) - -## 2.0.0-alpha.68 (2020-11-18) - -#### :rocket: New Feature - -- Other - - [#3717](https://github.com/facebook/docusaurus/pull/3717) feat(v2): official CodeSandbox support ([@sammychinedu2ky](https://github.com/sammychinedu2ky)) -- `docusaurus-init` - - [#3729](https://github.com/facebook/docusaurus/pull/3729) feat(v2): allow init project via npm ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` - - [#3730](https://github.com/facebook/docusaurus/pull/3730) feat(v2): add ThemedImage component ([@Simek](https://github.com/Simek)) -- `docusaurus-cssnano-preset`, `docusaurus-theme-classic`, `docusaurus` - - [#3716](https://github.com/facebook/docusaurus/pull/3716) feat(v2): introduce new minification of CSS bundle ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#3694](https://github.com/facebook/docusaurus/pull/3694) feat(v2): Added the ability to specify GIT_PASS in deploy command (for CI purposes) ([@smcelhinney](https://github.com/smcelhinney)) - - [#3621](https://github.com/facebook/docusaurus/pull/3621) feat(v2): baseUrl config issues: show help message if css/js can't load ([@jcs98](https://github.com/jcs98)) - - [#3594](https://github.com/facebook/docusaurus/pull/3594) feat(v2): add support for key,cert in https ([@ThakurKarthik](https://github.com/ThakurKarthik)) -- `docusaurus-remark-plugin-npm2yarn` - - [#3705](https://github.com/facebook/docusaurus/pull/3705) feat(v2): add support for sync to npm2yarn tabs ([@lex111](https://github.com/lex111)) -- `docusaurus-init`, `docusaurus-migrate`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` - - [#3658](https://github.com/facebook/docusaurus/pull/3658) feat(v2): onBrokenMarkdownLinks config ([@AmyrAhmady](https://github.com/AmyrAhmady)) -- `docusaurus-theme-classic` - - [#3640](https://github.com/facebook/docusaurus/pull/3640) feat(v2): add skip to content link ([@lex111](https://github.com/lex111)) - - [#3615](https://github.com/facebook/docusaurus/pull/3615) feat(v2): add ability to hide doc sidebar ([@lex111](https://github.com/lex111)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#3749](https://github.com/facebook/docusaurus/pull/3749) fix(v2): add support for interleaving Markdown in code blocks ([@lex111](https://github.com/lex111)) - - [#3739](https://github.com/facebook/docusaurus/pull/3739) fix(v2): add support for prefers-reduced-motion in hideable sidebar ([@lex111](https://github.com/lex111)) - - [#3726](https://github.com/facebook/docusaurus/pull/3726) fix(v2): add thin scrollbar to proper element in TOC ([@lex111](https://github.com/lex111)) - - [#3681](https://github.com/facebook/docusaurus/pull/3681) Revert "refactor(v2): improve regex matching code-block title" ([@lex111](https://github.com/lex111)) - - [#3662](https://github.com/facebook/docusaurus/pull/3662) fix(v2): navbar dropdown crash when item.to is undefined ([@artemkovalyov](https://github.com/artemkovalyov)) - - [#3669](https://github.com/facebook/docusaurus/pull/3669) fix(v2): make scrollbar styles consistent ([@nategiraudeau](https://github.com/nategiraudeau)) - - [#3666](https://github.com/facebook/docusaurus/pull/3666) fix(v2): make optional title for footer links column ([@lex111](https://github.com/lex111)) - - [#3647](https://github.com/facebook/docusaurus/pull/3647) fix(v2): do not set height for mobile dropdown during build ([@lex111](https://github.com/lex111)) - - [#3650](https://github.com/facebook/docusaurus/pull/3650) fix(v2): add landmark for skip to content link ([@lex111](https://github.com/lex111)) - - [#3627](https://github.com/facebook/docusaurus/pull/3627) fix(v2): disable tabbing on hidden doc sidebar ([@lex111](https://github.com/lex111)) - - [#3637](https://github.com/facebook/docusaurus/pull/3637) fix(v2): wrap code blocks on print ([@haivp3010](https://github.com/haivp3010)) - - [#3603](https://github.com/facebook/docusaurus/pull/3603) fix(v2): animate dropdown properly ([@lex111](https://github.com/lex111)) - - [#3611](https://github.com/facebook/docusaurus/pull/3611) fix(v2): Added back support for optional logo field in theme-classic navbarConfig ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-theme-classic`, `docusaurus` - - [#3763](https://github.com/facebook/docusaurus/pull/3763) refactor(v2): various markup improvements ([@lex111](https://github.com/lex111)) - - [#3724](https://github.com/facebook/docusaurus/pull/3724) fix(v2): add support for non-ASCII chars in anchor link scroll ([@lex111](https://github.com/lex111)) -- `docusaurus-module-type-aliases`, `docusaurus` - - [#3723](https://github.com/facebook/docusaurus/pull/3723) fix(v2): restore prefetch functionality ([@lex111](https://github.com/lex111)) -- Other - - [#3760](https://github.com/facebook/docusaurus/pull/3760) fix(v2): codesandbox generated examples should use published init package ([@slorber](https://github.com/slorber)) - - [#3701](https://github.com/facebook/docusaurus/pull/3701) fix(v2): limit images height on showcase page ([@lex111](https://github.com/lex111)) -- `docusaurus-mdx-loader` - - [#3757](https://github.com/facebook/docusaurus/pull/3757) fix(v2): escape alt text in img tag ([@lex111](https://github.com/lex111)) - - [#3653](https://github.com/facebook/docusaurus/pull/3653) fix(v2): handle multiple asset links in one line properly ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-search-algolia`, `docusaurus-utils` - - [#3721](https://github.com/facebook/docusaurus/pull/3721) fix(v2): use swizzled SearchPage component if any ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#3725](https://github.com/facebook/docusaurus/pull/3725) fix(v2): fix inconsistent error output in swizzle command ([@lex111](https://github.com/lex111)) - - [#3704](https://github.com/facebook/docusaurus/pull/3704) refactor(v2): allow adding plugins depending on condition ([@lex111](https://github.com/lex111)) - - [#3691](https://github.com/facebook/docusaurus/pull/3691) fix(v2): use SVGO in webpack SVGR loader ([@charleskorn](https://github.com/charleskorn)) - - [#3667](https://github.com/facebook/docusaurus/pull/3667) fix(v2): Fix typo in BaseUrlSuggestionWarning ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-utils` - - [#3703](https://github.com/facebook/docusaurus/pull/3703) fix(v2): ignore export declarations in excerpt ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-search-algolia` - - [#3639](https://github.com/facebook/docusaurus/pull/3639) fix(v2): restore infinite scroll pagination on search page ([@lex111](https://github.com/lex111)) -- `docusaurus-types`, `docusaurus` - - [#3622](https://github.com/facebook/docusaurus/pull/3622) fix(v2): docusaurus start --poll 500 should work + better config load failure error ([@slorber](https://github.com/slorber)) - -#### :nail_care: Polish - -- `docusaurus` - - [#3765](https://github.com/facebook/docusaurus/pull/3765) chore(v2): replace wait-file with wait-on to reduce npm warnings ([@lex111](https://github.com/lex111)) - - [#3725](https://github.com/facebook/docusaurus/pull/3725) fix(v2): fix inconsistent error output in swizzle command ([@lex111](https://github.com/lex111)) - - [#3609](https://github.com/facebook/docusaurus/pull/3609) refactor(v2): Improve SSR error message: log page path ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#3764](https://github.com/facebook/docusaurus/pull/3764) refactor(v2): make accessible anchor links from keyboard ([@lex111](https://github.com/lex111)) - - [#3745](https://github.com/facebook/docusaurus/pull/3745) refactor(v2): introduce Logo component, remove useLogo hook ([@Simek](https://github.com/Simek)) - - [#3706](https://github.com/facebook/docusaurus/pull/3706) refactor(v2): render all tab panels at once ([@lex111](https://github.com/lex111)) - - [#3712](https://github.com/facebook/docusaurus/pull/3712) chore(v2): upgrade Infima to v0.2.0-alpha.15 ([@lex111](https://github.com/lex111)) - - [#3685](https://github.com/facebook/docusaurus/pull/3685) refactor(v2): improve regex matching code-block title ([@hong4rc](https://github.com/hong4rc)) - - [#3674](https://github.com/facebook/docusaurus/pull/3674) feat(v2): add additional wrapper class to blog pages ([@Simek](https://github.com/Simek)) - - [#3671](https://github.com/facebook/docusaurus/pull/3671) refactor(v2): improve regex matching code-block title ([@hong4rc](https://github.com/hong4rc)) - - [#3654](https://github.com/facebook/docusaurus/pull/3654) refactor(v2): clean up code blocks ([@lex111](https://github.com/lex111)) - - [#3649](https://github.com/facebook/docusaurus/pull/3649) refactor(v2): make code blocks scrollable from keyboard ([@lex111](https://github.com/lex111)) - - [#3626](https://github.com/facebook/docusaurus/pull/3626) refactor(v2): remove focus outline from mouse users ([@lex111](https://github.com/lex111)) -- `docusaurus-init` - - [#3709](https://github.com/facebook/docusaurus/pull/3709) chore(v2): adjust website npm package ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#3707](https://github.com/facebook/docusaurus/pull/3707) chore(v2): upgrade Infima to v0.2.0-alpha.14 ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-utils-validation`, `docusaurus` - - [#3638](https://github.com/facebook/docusaurus/pull/3638) chore(v2): migrate hapi/joi to joi ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-search-algolia` - - [#3604](https://github.com/facebook/docusaurus/pull/3604) refactor(v2): use new way to get versions for search page ([@lex111](https://github.com/lex111)) - -#### :memo: Documentation - -- Other - - [#3762](https://github.com/facebook/docusaurus/pull/3762) Adding ConfigCat to showcase ([@sigewuzhere](https://github.com/sigewuzhere)) - - [#3750](https://github.com/facebook/docusaurus/pull/3750) docs(v2): add npm2yarn to typescript install command ([@davidjgoss](https://github.com/davidjgoss)) - - [#3743](https://github.com/facebook/docusaurus/pull/3743) docs(v2): convert teams page to MDX ([@slorber](https://github.com/slorber)) - - [#3737](https://github.com/facebook/docusaurus/pull/3737) docs(v2): add Inline SVG color override example ([@Simek](https://github.com/Simek)) - - [#3718](https://github.com/facebook/docusaurus/pull/3718) docs(v2): showcase Botonic ([@vanbasten17](https://github.com/vanbasten17)) - - [#3696](https://github.com/facebook/docusaurus/pull/3696) docs(v2): normalize showcase preview images height ([@Simek](https://github.com/Simek)) - - [#3699](https://github.com/facebook/docusaurus/pull/3699) docs(v2): deployment should use mdx extension ([@slorber](https://github.com/slorber)) - - [#3695](https://github.com/facebook/docusaurus/pull/3695) docs(v2): add React Native website to the showcase ([@Simek](https://github.com/Simek)) - - [#3645](https://github.com/facebook/docusaurus/pull/3645) Update Docusaurus v2 Showcase ([@ndom91](https://github.com/ndom91)) - - [#3644](https://github.com/facebook/docusaurus/pull/3644) docs(v2): update the link of joi ([@kenve](https://github.com/kenve)) - - [#3636](https://github.com/facebook/docusaurus/pull/3636) docs(v2): fix some misspellings ([@ka1bi4](https://github.com/ka1bi4)) - - [#3630](https://github.com/facebook/docusaurus/pull/3630) docs: remove runme ([@juzhiyuan](https://github.com/juzhiyuan)) -- `docusaurus-remark-plugin-npm2yarn` - - [#3624](https://github.com/facebook/docusaurus/pull/3624) Fix typo in remark-plugin-npm2yarn documentation ([@belemaire](https://github.com/belemaire)) - -#### :house: Internal - -- Other - - [#3769](https://github.com/facebook/docusaurus/pull/3769) docs(v2): fix statements background, update footer background ([@Simek](https://github.com/Simek)) - - [#3744](https://github.com/facebook/docusaurus/pull/3744) chore(v2): add build size bot workflow GitHub CI workflow ([@jcs98](https://github.com/jcs98)) - - [#3741](https://github.com/facebook/docusaurus/pull/3741) chore: update yarn lock again ([@slorber](https://github.com/slorber)) - - [#3740](https://github.com/facebook/docusaurus/pull/3740) chore: update yarn lock ([@slorber](https://github.com/slorber)) - - [#3738](https://github.com/facebook/docusaurus/pull/3738) chore(internal): add yarn deduplicate script, cleanup lock ([@Simek](https://github.com/Simek)) - - [#3732](https://github.com/facebook/docusaurus/pull/3732) fix(internal): fix clear script from the main package.json ([@Simek](https://github.com/Simek)) - - [#3708](https://github.com/facebook/docusaurus/pull/3708) chore(v2): remove docs for alpha v60-61 ([@lex111](https://github.com/lex111)) - - [#3693](https://github.com/facebook/docusaurus/pull/3693) fix(v2): fix website scripts on Windows by using cross-env ([@Simek](https://github.com/Simek)) - - [#3673](https://github.com/facebook/docusaurus/pull/3673) test(e2e): dogfood Yarn with enableGlobalCache ([@ylemkimon](https://github.com/ylemkimon)) - - [#3641](https://github.com/facebook/docusaurus/pull/3641) misc: fix unbound env variable in test release script ([@lex111](https://github.com/lex111)) -- `docusaurus-mdx-loader`, `docusaurus-migrate`, `lqip-loader` - - [#3766](https://github.com/facebook/docusaurus/pull/3766) chore(v2): fix several npm warnings ([@lex111](https://github.com/lex111)) -- `docusaurus-mdx-loader` - - [#3753](https://github.com/facebook/docusaurus/pull/3753) chore(v2): fix mismatch peer dependency in MDX loader ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#3742](https://github.com/facebook/docusaurus/pull/3742) chore(v2): pin version of babel-plugin-dynamic-import-node to 2.3.0 ([@lex111](https://github.com/lex111)) - - [#3734](https://github.com/facebook/docusaurus/pull/3734) chore(v2): downgrade babel-plugin-dynamic-import-node to 2.3.0 ([@lex111](https://github.com/lex111)) - - [#3714](https://github.com/facebook/docusaurus/pull/3714) chore(v2): fix prettier formatting ([@slorber](https://github.com/slorber)) - - [#3619](https://github.com/facebook/docusaurus/pull/3619) refactor(v2): add better error message for yarn workspace/monorepo/terser issue ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-pwa`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#3727](https://github.com/facebook/docusaurus/pull/3727) chore(v2): upgrade dependencies ([@lex111](https://github.com/lex111)) -- `docusaurus-1.x` - - [#3715](https://github.com/facebook/docusaurus/pull/3715) chore(v2): update Browserslist ([@lex111](https://github.com/lex111)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-sitemap` - - [#3675](https://github.com/facebook/docusaurus/pull/3675) fix(v2): add missing 'react' and 'webpack' peer dependencies ([@ylemkimon](https://github.com/ylemkimon)) -- `docusaurus-1.x`, `docusaurus-init-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` - - [#3613](https://github.com/facebook/docusaurus/pull/3613) fix: add repository metadata to all packages ([@rarkins](https://github.com/rarkins)) - -#### Committers: 26 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Anh Hong ([@hong4rc](https://github.com/hong4rc)) -- Artem Kovalov ([@artemkovalyov](https://github.com/artemkovalyov)) -- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) -- Benoît Lemaire ([@belemaire](https://github.com/belemaire)) -- Bright Egbo ([@egbobright](https://github.com/egbobright)) -- Charles Korn ([@charleskorn](https://github.com/charleskorn)) -- David Goss ([@davidjgoss](https://github.com/davidjgoss)) -- Gergely Sinka ([@sigewuzhere](https://github.com/sigewuzhere)) -- Hai ([@haivp3010](https://github.com/haivp3010)) -- Jainam Chirag Shah ([@jcs98](https://github.com/jcs98)) -- Marc Rabat Pla ([@vanbasten17](https://github.com/vanbasten17)) -- Nate Giraudeau ([@nategiraudeau](https://github.com/nategiraudeau)) -- Nico Domino ([@ndom91](https://github.com/ndom91)) -- Rhys Arkins ([@rarkins](https://github.com/rarkins)) -- Roman Bug ([@ka1bi4](https://github.com/ka1bi4)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Shenwei Wang ([@weareoutman](https://github.com/weareoutman)) -- Stephen McElhinney ([@smcelhinney](https://github.com/smcelhinney)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Thakur Karthik ([@ThakurKarthik](https://github.com/ThakurKarthik)) -- [@sammychinedu2ky](https://github.com/sammychinedu2ky) -- iAmir ([@AmyrAhmady](https://github.com/AmyrAhmady)) -- kenve ([@kenve](https://github.com/kenve)) -- ylemkimon ([@ylemkimon](https://github.com/ylemkimon)) -- 琚致远 ([@juzhiyuan](https://github.com/juzhiyuan)) - -## 2.0.0-alpha.67 (2020-11-18) - -Failed release - -## 2.0.0-alpha.66 (2020-10-19) - -#### :rocket: New Feature - -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` - - [#3593](https://github.com/facebook/docusaurus/pull/3593) feat(v2): blog sidebar ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader`, `docusaurus-remark-plugin-npm2yarn` - - [#3469](https://github.com/facebook/docusaurus/pull/3469) feat(v2): Extract npm2yarn plugin ([@fanny](https://github.com/fanny)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#3550](https://github.com/facebook/docusaurus/pull/3550) feat(v2): contextual search, dynamic Algolia facetFilters ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#3580](https://github.com/facebook/docusaurus/pull/3580) feat(v2): allow to define custom CSS class for Tabs component ([@Simek](https://github.com/Simek)) - - [#3553](https://github.com/facebook/docusaurus/pull/3553) feat(v2): make dropdown menu collapsible on mobiles ([@lex111](https://github.com/lex111)) -- `docusaurus-migrate`, `docusaurus-types`, `docusaurus` - - [#3573](https://github.com/facebook/docusaurus/pull/3573) feat(v2): Add themeConfig.noIndex option #3528 ([@hamzahamidi](https://github.com/hamzahamidi)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus` - - [#3543](https://github.com/facebook/docusaurus/pull/3543) feat(v2): persist docs preferred version ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus` - - [#3548](https://github.com/facebook/docusaurus/pull/3548) feat(v2): version dropdown before/after items + move site "All Versions" link ([@slorber](https://github.com/slorber)) -- `docusaurus-types`, `docusaurus` - - [#3545](https://github.com/facebook/docusaurus/pull/3545) feat(v2): site client modules ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#3539](https://github.com/facebook/docusaurus/pull/3539) feat(v2): doc navbar item type ([@slorber](https://github.com/slorber)) - -#### :boom: Breaking Change - -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#3550](https://github.com/facebook/docusaurus/pull/3550) feat(v2): contextual search, dynamic Algolia facetFilters ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic`, `docusaurus` - - [#3607](https://github.com/facebook/docusaurus/pull/3607) fix(v2): fix error with required href attr of link in mobiles ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#3602](https://github.com/facebook/docusaurus/pull/3602) fix(v2): make dropdown button clickable with mouse ([@lex111](https://github.com/lex111)) - - [#3601](https://github.com/facebook/docusaurus/pull/3601) fix(v2): fix table-of-content scroll highlighting issues ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` - - [#3599](https://github.com/facebook/docusaurus/pull/3599) fix(v2): remove event listeners on Tabs component unmount ([@lex111](https://github.com/lex111)) -- `docusaurus-types`, `docusaurus` - - [#3531](https://github.com/facebook/docusaurus/pull/3531) fix(v2): Fixes serve cli --port option ([@UmairKamran](https://github.com/UmairKamran)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#3585](https://github.com/facebook/docusaurus/pull/3585) refactor(v2): various dropdown improvements ([@lex111](https://github.com/lex111)) - - [#3588](https://github.com/facebook/docusaurus/pull/3588) refactor(v2): make accessible copy code button from keyboard ([@lex111](https://github.com/lex111)) - - [#3578](https://github.com/facebook/docusaurus/pull/3578) refactor(v2): apply common behavior to dropdowns ([@lex111](https://github.com/lex111)) - - [#3546](https://github.com/facebook/docusaurus/pull/3546) docs: various fixes and improvements ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus` - - [#3587](https://github.com/facebook/docusaurus/pull/3587) refactor(v2): various fixes ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#3569](https://github.com/facebook/docusaurus/pull/3569) refactor(v2): improve broken links error message ([@slorber](https://github.com/slorber)) - -#### :memo: Documentation - -- Other - - [#3576](https://github.com/facebook/docusaurus/pull/3576) docs(v2): removed obsolete "you" identifier ([@christian-bromann](https://github.com/christian-bromann)) - - [#3589](https://github.com/facebook/docusaurus/pull/3589) docs(v2): add taro to users ([@honlyHuang](https://github.com/honlyHuang)) - - [#3565](https://github.com/facebook/docusaurus/pull/3565) docs(v2): deployment, add required GitHub token scope infos ([@russtaylor](https://github.com/russtaylor)) - - [#3574](https://github.com/facebook/docusaurus/pull/3574) docs(v2): adding vue-nodegui to users ([@shubhamzanwar](https://github.com/shubhamzanwar)) - - [#3556](https://github.com/facebook/docusaurus/pull/3556) Added Axioms to users ([@abhishektiwari](https://github.com/abhishektiwari)) - - [#3558](https://github.com/facebook/docusaurus/pull/3558) docs(v2): embedding real source code in MDX as a code block ([@slorber](https://github.com/slorber)) - - [#3555](https://github.com/facebook/docusaurus/pull/3555) docs(v2): add "Wisdom" dev docs website to showcase. ([@jagracey](https://github.com/jagracey)) - - [#3532](https://github.com/facebook/docusaurus/pull/3532) docs(v2): change package name in example script ([@MatanBobi](https://github.com/MatanBobi)) - - [#3538](https://github.com/facebook/docusaurus/pull/3538) docs(v1): added drone for 1.0 #3491 ([@aakhtar3](https://github.com/aakhtar3)) - - [#3533](https://github.com/facebook/docusaurus/pull/3533) docs(v1): Fix broken link in the documentation ([@saintmalik](https://github.com/saintmalik)) - - [#3534](https://github.com/facebook/docusaurus/pull/3534) docs(v2): Fix url bugs in v2 docs ([@saintmalik](https://github.com/saintmalik)) -- `docusaurus-theme-classic` - - [#3546](https://github.com/facebook/docusaurus/pull/3546) docs: various fixes and improvements ([@lex111](https://github.com/lex111)) - -#### :house: Internal - -- `docusaurus-theme-search-algolia` - - [#3591](https://github.com/facebook/docusaurus/pull/3591) chore(v2): enable new contextual search feature ([@slorber](https://github.com/slorber)) -- Other - - [#3586](https://github.com/facebook/docusaurus/pull/3586) chore(v2): fix/upgrade react types ([@slorber](https://github.com/slorber)) - - [#3577](https://github.com/facebook/docusaurus/pull/3577) refactor(v2): clarify versions page ([@lex111](https://github.com/lex111)) - - [#3560](https://github.com/facebook/docusaurus/pull/3560) feat(v2): prevent using remote image urls in showcase ([@slorber](https://github.com/slorber)) - - [#3554](https://github.com/facebook/docusaurus/pull/3554) fix(v2): use absolute path to manifest file ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#3394](https://github.com/facebook/docusaurus/pull/3394) refactor(v2): add useThemeConfig hook + cleanup useless theme default values ([@imskr](https://github.com/imskr)) - -#### Committers: 17 - -- Abhishek Tiwari ([@abhishektiwari](https://github.com/abhishektiwari)) -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) -- Christian Bromann ([@christian-bromann](https://github.com/christian-bromann)) -- Fanny ([@fanny](https://github.com/fanny)) -- Hamza Hamidi ([@hamzahamidi](https://github.com/hamzahamidi)) -- John Gracey ([@jagracey](https://github.com/jagracey)) -- Matan Borenkraout ([@MatanBobi](https://github.com/MatanBobi)) -- Russ Taylor ([@russtaylor](https://github.com/russtaylor)) -- SaintMalik ([@saintmalik](https://github.com/saintmalik)) -- Shubham Kumar ([@imskr](https://github.com/imskr)) -- Shubham Zanwar ([@shubhamzanwar](https://github.com/shubhamzanwar)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Umair Kamran ([@UmairKamran](https://github.com/UmairKamran)) -- Utkarsh Goel ([@utkarsh867](https://github.com/utkarsh867)) -- [@aakhtar3](https://github.com/aakhtar3) -- honlyHuang ([@honlyHuang](https://github.com/honlyHuang)) - -## 2.0.0-alpha.65 (2020-10-02) - -#### :rocket: New Feature - -- `docusaurus` - - [#3497](https://github.com/facebook/docusaurus/pull/3497) feat(v2): env variable TERSER_PARALLEL to customize TerserPlugin.parallel ([@aeneasr](https://github.com/aeneasr)) - - [#3446](https://github.com/facebook/docusaurus/pull/3446) feat(v2): new docusaurus clear command ([@abadon7](https://github.com/abadon7)) - - [#3485](https://github.com/facebook/docusaurus/pull/3485) feat(v2): Add @theme-init components to user theme ([@edno](https://github.com/edno)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages` - - [#3467](https://github.com/facebook/docusaurus/pull/3467) feat(v2): add beforeDefaultRemarkPlugins/beforeDefaultRehypePlugins options to all md content plugins ([@ayshiff](https://github.com/ayshiff)) -- `docusaurus-init`, `docusaurus-theme-bootstrap` - - [#3496](https://github.com/facebook/docusaurus/pull/3496) feat(v2): migrate bootstrap components to ts ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#3474](https://github.com/facebook/docusaurus/pull/3474) feat(v2): allow to use array of files in customCss field ([@Simek](https://github.com/Simek)) -- `docusaurus-plugin-content-pages`, `docusaurus-theme-classic` - - [#3457](https://github.com/facebook/docusaurus/pull/3457) feat(v2): add optional custom wrapper class name for pages based on theme classic Layout ([@Simek](https://github.com/Simek)) - -#### :bug: Bug Fix - -- Other - - [#3517](https://github.com/facebook/docusaurus/pull/3517) fix(v1): v1 deploy preview should be available ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#3498](https://github.com/facebook/docusaurus/pull/3498) fix(v2): fixed props being passed to @svgr/webpack loader ([@anru](https://github.com/anru)) -- `docusaurus-theme-search-algolia` - - [#3456](https://github.com/facebook/docusaurus/pull/3456) fix(v2): use valid value for crossorigin attribute ([@lex111](https://github.com/lex111)) -- `docusaurus-utils` - - [#3427](https://github.com/facebook/docusaurus/pull/3427) fix(v2): normalizeUrl edge cases ([@ayshiff](https://github.com/ayshiff)) -- `docusaurus-theme-classic` - - [#3472](https://github.com/facebook/docusaurus/pull/3472) fix(v2): Show dropdown instead of a single button when there are two versions ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-plugin-content-docs` - - [#3441](https://github.com/facebook/docusaurus/pull/3441) fix(v2): fixing typo in error message ([@ayonious](https://github.com/ayonious)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#3499](https://github.com/facebook/docusaurus/pull/3499) chore(v2): upgrade Infima to 0.2.0-alpha.13 ([@lex111](https://github.com/lex111)) - -#### :memo: Documentation - -- `docusaurus` - - [#3502](https://github.com/facebook/docusaurus/pull/3502) docs(v2): add doc for wrapping theme components with @theme-original and @theme-init ([@slorber](https://github.com/slorber)) -- Other - - [#3473](https://github.com/facebook/docusaurus/pull/3473) misc: add License to the documentation ([@muskanvk](https://github.com/muskanvk)) - - [#3492](https://github.com/facebook/docusaurus/pull/3492) docs(v2): Added drone.io publish docs #3491 ([@aakhtar3](https://github.com/aakhtar3)) - - [#3479](https://github.com/facebook/docusaurus/pull/3479) docs(v2): remove redundant new line in code block ([@lex111](https://github.com/lex111)) - - [#3448](https://github.com/facebook/docusaurus/pull/3448) chore(v2): fix theme classic navbar style docs ([@Simek](https://github.com/Simek)) - -#### :house: Internal - -- `docusaurus-1.x`, `docusaurus-migrate` - - [#3504](https://github.com/facebook/docusaurus/pull/3504) chore(v1): move v1 docs inside website-1.x ([@slorber](https://github.com/slorber)) -- Other - - [#3506](https://github.com/facebook/docusaurus/pull/3506) chore(v2): v2 website should make it easy to contribute to upstream docs ([@slorber](https://github.com/slorber)) - - [#3511](https://github.com/facebook/docusaurus/pull/3511) misc: update CODEOWNERS ([@yangshun](https://github.com/yangshun)) - - [#3477](https://github.com/facebook/docusaurus/pull/3477) chore(v2): remove alpha 58 doc ([@lex111](https://github.com/lex111)) -- `docusaurus-utils-validation` - - [#3453](https://github.com/facebook/docusaurus/pull/3453) test(v2): add protocol relative uri validation test ([@moonrailgun](https://github.com/moonrailgun)) - -#### Committers: 18 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Andrey Rublev ([@anru](https://github.com/anru)) -- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) -- Grégory Heitz ([@edno](https://github.com/edno)) -- Henry Vélez ([@abadon7](https://github.com/abadon7)) -- Jeremy Hager ([@jeremyhager](https://github.com/jeremyhager)) -- Joel Marcey ([@JoelMarcey](https://github.com/JoelMarcey)) -- Long Ho ([@longlho](https://github.com/longlho)) -- Muskan Kumar ([@muskanvk](https://github.com/muskanvk)) -- Nahiyan Kamal ([@ayonious](https://github.com/ayonious)) -- Rémi Doreau ([@ayshiff](https://github.com/ayshiff)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tim Gates ([@timgates42](https://github.com/timgates42)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) -- [@aakhtar3](https://github.com/aakhtar3) -- hackerman ([@aeneasr](https://github.com/aeneasr)) -- moonrailgun ([@moonrailgun](https://github.com/moonrailgun)) - -## 2.0.0-alpha.64 (2020-09-11) - -#### :rocket: New Feature - -- `docusaurus-theme-classic` - - [#3432](https://github.com/facebook/docusaurus/pull/3432) feat(v2): add style property to theme-classic navbar ([@Simek](https://github.com/Simek)) - - [#3406](https://github.com/facebook/docusaurus/pull/3406) feat(v2): ability to add/override theme html metadatas ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-sitemap` - - [#3426](https://github.com/facebook/docusaurus/pull/3426) feat(v2): add option to add trailing slash to urls in sitemap ([@mpsq](https://github.com/mpsq)) - -#### :bug: Bug Fix - -- Other - - [#3438](https://github.com/facebook/docusaurus/pull/3438) fix(v2): docusaurus 2 PWA should work under baseurl (deploy previews) ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader` - - [#3435](https://github.com/facebook/docusaurus/pull/3435) fix(v2): fix empty link error message ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-pwa` - - [#3436](https://github.com/facebook/docusaurus/pull/3436) fix(v2): Correctly resolve sw.js path on windows ([@ashscodes](https://github.com/ashscodes)) -- `docusaurus-theme-classic` - - [#3433](https://github.com/facebook/docusaurus/pull/3433) fix(v2): fix theme-classic announcement bar closeable style ([@Simek](https://github.com/Simek)) -- `docusaurus-1.x` - - [#3429](https://github.com/facebook/docusaurus/pull/3429) fix(v1): versioned_docs and skip-next-release relative path issue ([@josephMG](https://github.com/josephMG)) -- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` - - [#3418](https://github.com/facebook/docusaurus/pull/3418) fix(v2): reset sidebar state on sidebar changes ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-debug` - - [#3405](https://github.com/facebook/docusaurus/pull/3405) fix(v2): fix debug plugin unscoped inline code global css ([@slorber](https://github.com/slorber)) - -#### :memo: Documentation - -- [#3428](https://github.com/facebook/docusaurus/pull/3428) docs(v2): fix grammar ([@thadguidry](https://github.com/thadguidry)) -- [#3425](https://github.com/facebook/docusaurus/pull/3425) docs(v2): mention Eta in ssrTemplate section ([@mpsq](https://github.com/mpsq)) -- [#3423](https://github.com/facebook/docusaurus/pull/3423) docs(v2): minor typo fix ([@rutikwankhade](https://github.com/rutikwankhade)) - -#### :house: Internal - -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus` - - [#3439](https://github.com/facebook/docusaurus/pull/3439) chore(v2): fix serialize-javascript security issue by upgrading webpack/workbox ([@slorber](https://github.com/slorber)) -- Other - - [#3401](https://github.com/facebook/docusaurus/pull/3401) chore(deps): bump decompress from 4.2.0 to 4.2.1 ([@dependabot[bot]](https://github.com/apps/dependabot)) - -#### Committers: 7 - -- Ash ([@ashscodes](https://github.com/ashscodes)) -- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) -- Méril ([@mpsq](https://github.com/mpsq)) -- Rutik Wankhade ([@rutikwankhade](https://github.com/rutikwankhade)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Thad Guidry ([@thadguidry](https://github.com/thadguidry)) -- [@josephMG](https://github.com/josephMG) - -## 2.0.0-alpha.63 (2020-09-03) - -#### :rocket: New Feature - -- `docusaurus-types`, `docusaurus` - - [#3387](https://github.com/facebook/docusaurus/pull/3387) feat(v2): allow users to specify a custom ssr HTML template ([@mpsq](https://github.com/mpsq)) -- `docusaurus-plugin-debug` - - [#3392](https://github.com/facebook/docusaurus/pull/3392) feat(v2): officially release @docusaurus/plugin-debug ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#3388](https://github.com/facebook/docusaurus/pull/3388) feat(v2): add isCloseable property for theme-classic announcement bar ([@Simek](https://github.com/Simek)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#3373](https://github.com/facebook/docusaurus/pull/3373) feat(v2): docs options.onlyIncludeVersions ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- Other - - [#3397](https://github.com/facebook/docusaurus/pull/3397) fix(v2): DocSearch should keep working after a new release (part 2/2) ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#3393](https://github.com/facebook/docusaurus/pull/3393) fix(v2): DocSearch should keep working after a new release (part 1/2) ([@slorber](https://github.com/slorber)) - - [#3381](https://github.com/facebook/docusaurus/pull/3381) fix(v2): alpha 62 doc fixes ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#3385](https://github.com/facebook/docusaurus/pull/3385) fix(v2): scripts should allow unknown values ([@slorber](https://github.com/slorber)) -- `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus` - - [#3382](https://github.com/facebook/docusaurus/pull/3382) fix(v2): allow using classic theme/preset without the docs plugin ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils-validation` - - [#3377](https://github.com/facebook/docusaurus/pull/3377) fix(v2): reject routeBasePath: '' ([@slorber](https://github.com/slorber)) - -#### :memo: Documentation - -- [#3390](https://github.com/facebook/docusaurus/pull/3390) docs(v1, v2): Update Deploy to Vercel guide ([@samsisle](https://github.com/samsisle)) -- [#3344](https://github.com/facebook/docusaurus/pull/3344) docs(v2): Update Deploy to Vercel guide ([@samsisle](https://github.com/samsisle)) - -#### :house: Internal - -- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus` - - [#3386](https://github.com/facebook/docusaurus/pull/3386) chore(v2): pin exact dependency versions ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x`, `docusaurus-init-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` - - [#3359](https://github.com/facebook/docusaurus/pull/3359) chore(v2): prepare v2.0.0.alpha-62 release ([@slorber](https://github.com/slorber)) - -#### Committers: 5 - -- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) -- Méril ([@mpsq](https://github.com/mpsq)) -- Sam Ko ([@samsisle](https://github.com/samsisle)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Thad Guidry ([@thadguidry](https://github.com/thadguidry)) - -## 2.0.0-alpha.62 (2020-08-28) - -#### :rocket: New Feature - -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#3357](https://github.com/facebook/docusaurus/pull/3357) feat(v2): docs version configuration: lastVersion, version.{path,label} ([@slorber](https://github.com/slorber)) - - [#3328](https://github.com/facebook/docusaurus/pull/3328) feat(v2): Provide docs plugin theme typing ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-theme-classic` - - [#3356](https://github.com/facebook/docusaurus/pull/3356) feat(v2): Provide type definitions for remaining theme-classic components ([@SamChou19815](https://github.com/SamChou19815)) - - [#3274](https://github.com/facebook/docusaurus/pull/3274) feat(v2): add TOC to blog posts ([@amy-lei](https://github.com/amy-lei)) -- `docusaurus-plugin-content-pages`, `docusaurus-theme-classic` - - [#3354](https://github.com/facebook/docusaurus/pull/3354) feat(v2): Provide type definitions for MDXPage from page plugin ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#3348](https://github.com/facebook/docusaurus/pull/3348) feat(v2): Provide typing to most of the theme-classic components ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-init`, `docusaurus-plugin-content-blog` - - [#3284](https://github.com/facebook/docusaurus/pull/3284) feat(v2): blog slug frontmatter ([@JeanMarcSaad](https://github.com/JeanMarcSaad)) -- `docusaurus-init`, `docusaurus-theme-bootstrap` - - [#2981](https://github.com/facebook/docusaurus/pull/2981) feat(v2): bootstrap theme, preset, template, CI previews ([@fanny](https://github.com/fanny)) -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` - - [#3267](https://github.com/facebook/docusaurus/pull/3267) feat(v2): Provide blog plugin theme typing ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-debug`, `docusaurus-preset-classic`, `docusaurus-theme-bootstrap`, `docusaurus-types`, `docusaurus` - - [#3229](https://github.com/facebook/docusaurus/pull/3229) feat(v2): debug pages + debug layout + ability to debug content ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#3021](https://github.com/facebook/docusaurus/pull/3021) feat(v2): update swizzle command to suggest component/theme ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-pages` - - [#3196](https://github.com/facebook/docusaurus/pull/3196) feat(v2): add support to ignore files in pages plugin ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-utils-validation`, `docusaurus` - - [#3204](https://github.com/facebook/docusaurus/pull/3204) feat(v2): blog + docs multi-instance plugins ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader` - - [#3096](https://github.com/facebook/docusaurus/pull/3096) feat(v2): add support to import assets using relative link in markdown syntax ([@anshulrgoyal](https://github.com/anshulrgoyal)) - -#### :bug: Bug Fix - -- `docusaurus-migrate` - - [#3358](https://github.com/facebook/docusaurus/pull/3358) fix(v2): fix migrate cli paths (sidebars/customcss) ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#3311](https://github.com/facebook/docusaurus/pull/3311) fix(v2): add https support in webpack devserver ([@arcvats](https://github.com/arcvats)) - - [#3313](https://github.com/facebook/docusaurus/pull/3313) fix(v2): resolve webpack loaders from siteDir/node_modules ([@anshulrgoyal](https://github.com/anshulrgoyal)) - - [#3308](https://github.com/facebook/docusaurus/pull/3308) fix(v2): brokenLinks should not report links that belong to an existing folder if folder/index.html exists ([@slorber](https://github.com/slorber)) - - [#3273](https://github.com/facebook/docusaurus/pull/3273) fix: logic error while deciding deploymentBranch ([@thehanimo](https://github.com/thehanimo)) - - [#3281](https://github.com/facebook/docusaurus/pull/3281) fix(v2): allow swizzling of component even if case doesn't match ([@anshulrgoyal](https://github.com/anshulrgoyal)) - - [#3222](https://github.com/facebook/docusaurus/pull/3222) fix(v2): update react-loadable-ssr-addon to solve yarn2 error ([@slorber](https://github.com/slorber)) - - [#3191](https://github.com/facebook/docusaurus/pull/3191) fix(v2): add missing `lodash.flatmap` dependency ([@ylemkimon](https://github.com/ylemkimon)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-bootstrap`, `docusaurus-theme-search-algolia`, `docusaurus-types` - - [#3355](https://github.com/facebook/docusaurus/pull/3355) fix(v2): Add missing dependencies to packages ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-theme-classic` - - [#3352](https://github.com/facebook/docusaurus/pull/3352) fix(v2): Allow the alt for the logo to be empty ([@Vinnl](https://github.com/Vinnl)) - - [#3240](https://github.com/facebook/docusaurus/pull/3240) fix(v2): navbar dropdown opened with tab, not closing on click outside ([@Ako92](https://github.com/Ako92)) -- `docusaurus-mdx-loader`, `docusaurus` - - [#3347](https://github.com/facebook/docusaurus/pull/3347) fix(v2): linking to asset or external html page -> don't use history.push() ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x` - - [#3340](https://github.com/facebook/docusaurus/pull/3340) fix(v1): show images after one line code block ([@adinaja](https://github.com/adinaja)) -- `docusaurus-1.x`, `docusaurus` - - [#3290](https://github.com/facebook/docusaurus/pull/3290) fix(v1,v2): Add initial-scale=1.0 to all meta viewport tags ([@nebrelbug](https://github.com/nebrelbug)) -- `docusaurus-theme-search-algolia` - - [#3297](https://github.com/facebook/docusaurus/pull/3297) fix(v2): keep DocSearch state on remounts ([@francoischalifour](https://github.com/francoischalifour)) - - [#3280](https://github.com/facebook/docusaurus/pull/3280) fix(v2): allow search page swizzle ([@Ako92](https://github.com/Ako92)) - - [#3263](https://github.com/facebook/docusaurus/pull/3263) fix(v2): do not index search pages ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-pages` - - [#3283](https://github.com/facebook/docusaurus/pull/3283) fix(v2): pass images in static dir to webpack-loader ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- Other - - [#3269](https://github.com/facebook/docusaurus/pull/3269) fix(v2): website feedback page hydration bug ([@mecm1993](https://github.com/mecm1993)) - - [#3200](https://github.com/facebook/docusaurus/pull/3200) fix(v1): self-host user images ([@leoigel](https://github.com/leoigel)) -- `docusaurus-plugin-google-gtag` - - [#3243](https://github.com/facebook/docusaurus/pull/3243) fix(v2): GTM, send page_view events on navigate ([@govardhan-srinivas](https://github.com/govardhan-srinivas)) -- `docusaurus-plugin-content-docs`, `docusaurus-utils` - - [#3262](https://github.com/facebook/docusaurus/pull/3262) fix(v2): doc path special char (space or other) should lead to a valid slug ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-utils-validation`, `docusaurus` - - [#3247](https://github.com/facebook/docusaurus/pull/3247) fix(v2): modify validation schema and tests for rehype/remark + remove duplicate dependency ([@teikjun](https://github.com/teikjun)) -- `docusaurus-init` - - [#3258](https://github.com/facebook/docusaurus/pull/3258) fix(v2): fix template alt image prop ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils-validation`, `docusaurus` - - [#3227](https://github.com/facebook/docusaurus/pull/3227) fix(v2): relax URI validation ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- `docusaurus-init`, `docusaurus-plugin-content-docs` - - [#3228](https://github.com/facebook/docusaurus/pull/3228) fix(v2): deprecate docs homePageId in favor of frontmatter "slug: /" ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus` - - [#3225](https://github.com/facebook/docusaurus/pull/3225) fix(v2): swizzle minor improvements ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#3210](https://github.com/facebook/docusaurus/pull/3210) fix(v2): fix theme validation for prism field and add tests ([@teikjun](https://github.com/teikjun)) -- `docusaurus-plugin-content-docs` - - [#3192](https://github.com/facebook/docusaurus/pull/3192) fix(v2): add missing `chalk` and `lodash` dependencies ([@ylemkimon](https://github.com/ylemkimon)) - -#### :nail_care: Polish - -- `docusaurus-module-type-aliases`, `docusaurus` - - [#3244](https://github.com/facebook/docusaurus/pull/3244) chore(v2): tighten up the TypeScript onboarding ([@orta](https://github.com/orta)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils`, `docusaurus` - - [#3245](https://github.com/facebook/docusaurus/pull/3245) refactor(v2): docs plugin refactor ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#3188](https://github.com/facebook/docusaurus/pull/3188) fix(v2): Add a missing whitespace before prompt to use `npm run serve` ([@SamChou19815](https://github.com/SamChou19815)) - -#### :memo: Documentation - -- Other - - [#3346](https://github.com/facebook/docusaurus/pull/3346) docs(v2): add draft doc ([@imskr](https://github.com/imskr)) - - [#3336](https://github.com/facebook/docusaurus/pull/3336) docs(v2): add Nisarag to Fellows section ([@FocalChord](https://github.com/FocalChord)) - - [#3335](https://github.com/facebook/docusaurus/pull/3335) docs(v2): update team profile ([@yangshun](https://github.com/yangshun)) - - [#3334](https://github.com/facebook/docusaurus/pull/3334) docs(v2): add Drew to Fellows section ([@Drewbi](https://github.com/Drewbi)) - - [#3333](https://github.com/facebook/docusaurus/pull/3333) docs(v2): add anshul and teikjun to fellows section of team page ([@teikjun](https://github.com/teikjun)) - - [#3326](https://github.com/facebook/docusaurus/pull/3326) docs(v1): showcase user Casbin ([@hsluoyz](https://github.com/hsluoyz)) - - [#3316](https://github.com/facebook/docusaurus/pull/3316) docs(v1): add Global CTO Forum to users ([@MirzayevFarid](https://github.com/MirzayevFarid)) - - [#3310](https://github.com/facebook/docusaurus/pull/3310) docs(v2): add "T-Regx" website to showcase ([@Danon](https://github.com/Danon)) - - [#3307](https://github.com/facebook/docusaurus/pull/3307) docs(v2): showcase SpotifyAPI-NET ([@JohnnyCrazy](https://github.com/JohnnyCrazy)) - - [#3295](https://github.com/facebook/docusaurus/pull/3295) docs(v2): showcase Oxidizer ([@vandreleal](https://github.com/vandreleal)) - - [#3287](https://github.com/facebook/docusaurus/pull/3287) docs: update README.md with some grammatical corrections ([@shalinikumari50](https://github.com/shalinikumari50)) - - [#3271](https://github.com/facebook/docusaurus/pull/3271) docs(v2): fix typo ([@thehanimo](https://github.com/thehanimo)) - - [#3277](https://github.com/facebook/docusaurus/pull/3277) docs(v1): Add Radity to users ([@tolunayakbulut](https://github.com/tolunayakbulut)) - - [#3276](https://github.com/facebook/docusaurus/pull/3276) docs: corrected some few typos in the docusaurus tech docs ([@ajifrank75](https://github.com/ajifrank75)) - - [#3249](https://github.com/facebook/docusaurus/pull/3249) docs(v2): fix migration command ([@BogdanDor](https://github.com/BogdanDor)) - - [#3248](https://github.com/facebook/docusaurus/pull/3248) Added twitter badge and modified discord Badges ([@Souravdey777](https://github.com/Souravdey777)) - - [#3251](https://github.com/facebook/docusaurus/pull/3251) docs(v2): fix migration command for earlier versions ([@teikjun](https://github.com/teikjun)) - - [#3252](https://github.com/facebook/docusaurus/pull/3252) docs(v2): docs typos ([@olawanlejoel](https://github.com/olawanlejoel)) - - [#3111](https://github.com/facebook/docusaurus/pull/3111) docs(v2): clarify theme-original and theme-init ([@Jonathannsegal](https://github.com/Jonathannsegal)) - - [#3232](https://github.com/facebook/docusaurus/pull/3232) docs(v2): showcase user QA-Board ([@arthur-flam](https://github.com/arthur-flam)) - - [#3205](https://github.com/facebook/docusaurus/pull/3205) docs: format reference links ([@lebogangolifant](https://github.com/lebogangolifant)) - - [#3194](https://github.com/facebook/docusaurus/pull/3194) docs(v2): Added switch config docs to theme-classic API ([@Drewbi](https://github.com/Drewbi)) - - [#3201](https://github.com/facebook/docusaurus/pull/3201) docs(v2): removed duplicate text under "Using React" section ([@boosh511](https://github.com/boosh511)) - - [#3186](https://github.com/facebook/docusaurus/pull/3186) docs(v1): formatting changelog ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#3202](https://github.com/facebook/docusaurus/pull/3202) fix(v2): fix svg loader ([@anshulrgoyal](https://github.com/anshulrgoyal)) - -#### :house: Internal - -- `docusaurus-migrate` - - [#3323](https://github.com/facebook/docusaurus/pull/3323) test(v2): Add unit test for migration of config file ([@BogdanDor](https://github.com/BogdanDor)) -- `docusaurus-theme-classic` - - [#3343](https://github.com/facebook/docusaurus/pull/3343) refactor(v2): announcement bar bad spelling + minor refactors ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-blog` - - [#3339](https://github.com/facebook/docusaurus/pull/3339) test(v2): make blog posts unit test ordering determinate ([@BogdanDor](https://github.com/BogdanDor)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-theme-classic`, `docusaurus-types` - - [#3306](https://github.com/facebook/docusaurus/pull/3306) chore(v2): Define type for markdown right table of contents ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-module-type-aliases`, `docusaurus` - - [#3244](https://github.com/facebook/docusaurus/pull/3244) chore(v2): tighten up the TypeScript onboarding ([@orta](https://github.com/orta)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils`, `docusaurus` - - [#3245](https://github.com/facebook/docusaurus/pull/3245) refactor(v2): docs plugin refactor ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#3282](https://github.com/facebook/docusaurus/pull/3282) chore(v2): fix javascript-serialize vulnerability ([@slorber](https://github.com/slorber)) - - [#3265](https://github.com/facebook/docusaurus/pull/3265) chore(v2): upgrade terser-webpack-plugin ([@dschaller](https://github.com/dschaller)) -- Other - - [#3241](https://github.com/facebook/docusaurus/pull/3241) chore(deps): bump prismjs from 1.20.0 to 1.21.0 ([@dependabot[bot]](https://github.com/apps/dependabot)) - - [#3259](https://github.com/facebook/docusaurus/pull/3259) chore(v2): fix slow commits due to lint-staged ([@slorber](https://github.com/slorber)) - - [#3197](https://github.com/facebook/docusaurus/pull/3197) chore(v2): lockfile update ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x` - - [#3218](https://github.com/facebook/docusaurus/pull/3218) chore(v1): release 1.14.6 ([@slorber](https://github.com/slorber)) - -#### :running_woman: Performance - -- `docusaurus-plugin-client-redirects`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#3238](https://github.com/facebook/docusaurus/pull/3238) refactor(v2): precompile ETA templates ([@slorber](https://github.com/slorber)) - -#### Committers: 39 - -- Ali Hosseini ([@Ako92](https://github.com/Ako92)) -- Amy Lei ([@amy-lei](https://github.com/amy-lei)) -- Anshul Goyal ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- Archit ([@arcvats](https://github.com/arcvats)) -- Arthur Flam ([@arthur-flam](https://github.com/arthur-flam)) -- Ben Gubler ([@nebrelbug](https://github.com/nebrelbug)) -- Bogdan Doroschenko ([@BogdanDor](https://github.com/BogdanDor)) -- Daniel Wilkowski ([@Danon](https://github.com/Danon)) -- Derek ([@dschaller](https://github.com/dschaller)) -- Drew Alexander ([@Drewbi](https://github.com/Drewbi)) -- Fanny ([@fanny](https://github.com/fanny)) -- Franklyn Chisom ([@ajifrank75](https://github.com/ajifrank75)) -- François Chalifour ([@francoischalifour](https://github.com/francoischalifour)) -- Govardhan Srinivas ([@govardhan-srinivas](https://github.com/govardhan-srinivas)) -- Hani Mohammed ([@thehanimo](https://github.com/thehanimo)) -- Jean-Marc Saad ([@JeanMarcSaad](https://github.com/JeanMarcSaad)) -- Jonas Dellinger ([@JohnnyCrazy](https://github.com/JohnnyCrazy)) -- Jonathan ([@Jonathannsegal](https://github.com/Jonathannsegal)) -- Manuel Cepeda ([@mecm1993](https://github.com/mecm1993)) -- Mirzayev Farid ([@MirzayevFarid](https://github.com/MirzayevFarid)) -- Nisarag ([@FocalChord](https://github.com/FocalChord)) -- Olawanle Joel ([@olawanlejoel](https://github.com/olawanlejoel)) -- Orta Therox ([@orta](https://github.com/orta)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Shubham Kumar ([@imskr](https://github.com/imskr)) -- Sourav Dey ([@Souravdey777](https://github.com/Souravdey777)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Teik Jun ([@teikjun](https://github.com/teikjun)) -- Tolunay Akbulut ([@tolunayakbulut](https://github.com/tolunayakbulut)) -- Vandré Leal ([@vandreleal](https://github.com/vandreleal)) -- Vincent ([@Vinnl](https://github.com/Vinnl)) -- Yang Luo ([@hsluoyz](https://github.com/hsluoyz)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) -- [@adinaja](https://github.com/adinaja) -- [@leoigel](https://github.com/leoigel) -- [@shalinikumari50](https://github.com/shalinikumari50) -- alex busnelli ([@boosh511](https://github.com/boosh511)) -- lebogang Olifant ([@lebogangolifant](https://github.com/lebogangolifant)) -- ylemkimon ([@ylemkimon](https://github.com/ylemkimon)) - -## 2.0.0-alpha.61 (2020-08-01) - -#### :rocket: New Feature - -- `docusaurus-types`, `docusaurus` - - [#3083](https://github.com/facebook/docusaurus/pull/3083) feat(v2): warn user when there are conflicting routes ([@teikjun](https://github.com/teikjun)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-utils-validation`, `docusaurus-utils` - - [#3158](https://github.com/facebook/docusaurus/pull/3158) feat(v2): markdown pages ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#3127](https://github.com/facebook/docusaurus/pull/3127) feat(v2): dark mode toggle customization ([@Drewbi](https://github.com/Drewbi)) -- `docusaurus-theme-search-algolia` - - [#3166](https://github.com/facebook/docusaurus/pull/3166) feat(v2): improve Algolia search accessibility ([@francoischalifour](https://github.com/francoischalifour)) -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` - - [#2359](https://github.com/facebook/docusaurus/pull/2359) feat(v2): support custom description for blog-only mode ([@zxuqian](https://github.com/zxuqian)) - -#### :bug: Bug Fix - -- `docusaurus-mdx-loader`, `docusaurus` - - [#3180](https://github.com/facebook/docusaurus/pull/3180) fix(v2): fix markdown images always using webpack url-loader ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#3171](https://github.com/facebook/docusaurus/pull/3171) fix(v2): tab label showing outline & background when clicked ([@mdfaizan7](https://github.com/mdfaizan7)) -- `docusaurus-init`, `docusaurus-theme-classic` - - [#3168](https://github.com/facebook/docusaurus/pull/3168) fix(v2): fix link items refusing attributes like target, rel etc... ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#3162](https://github.com/facebook/docusaurus/pull/3162) fix(v2): inability for users to pin their docusaurus version ([@BuckyMaler](https://github.com/BuckyMaler)) - -#### :memo: Documentation - -- [#3163](https://github.com/facebook/docusaurus/pull/3163) docs(v2): showcase user questdb ([@mpsq](https://github.com/mpsq)) - -#### :house: Internal - -- Other - - [#3164](https://github.com/facebook/docusaurus/pull/3164) chore(deps): bump elliptic from 6.5.2 to 6.5.3 ([@dependabot[bot]](https://github.com/apps/dependabot)) - - [#3157](https://github.com/facebook/docusaurus/pull/3157) chore(v2): remove alpha 59 doc ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x`, `docusaurus-init-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` - - [#3154](https://github.com/facebook/docusaurus/pull/3154) chore(v2): prepare v2.0.0.alpha-60 release ([@slorber](https://github.com/slorber)) - -#### Committers: 8 - -- Bucky Maler ([@BuckyMaler](https://github.com/BuckyMaler)) -- Drew Alexander ([@Drewbi](https://github.com/Drewbi)) -- Faizan ([@mdfaizan7](https://github.com/mdfaizan7)) -- François Chalifour ([@francoischalifour](https://github.com/francoischalifour)) -- Méril ([@mpsq](https://github.com/mpsq)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Teik Jun ([@teikjun](https://github.com/teikjun)) -- Xuqian ([@zxuqian](https://github.com/zxuqian)) - -## 2.0.0-alpha.60 (2020-07-29) - -#### :rocket: New Feature - -- `docusaurus` - - [#3134](https://github.com/facebook/docusaurus/pull/3134) feat(v2): add validation escape hatch ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x` - - [#3124](https://github.com/facebook/docusaurus/pull/3124) feat(v1): add 'slugPreprocessor' config option to allow users customize the hash links ([@Simek](https://github.com/Simek)) -- `docusaurus-theme-search-algolia` - - [#3133](https://github.com/facebook/docusaurus/pull/3133) feat(v2): add themeConfig validation to algolia theme ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus` - - [#3142](https://github.com/facebook/docusaurus/pull/3142) fix(v2): config validation fixes + add tests for config validation ([@teikjun](https://github.com/teikjun)) -- `docusaurus` - - [#3149](https://github.com/facebook/docusaurus/pull/3149) fix(v2): BrowserOnly should not return undefined ([@slorber](https://github.com/slorber)) - - [#3143](https://github.com/facebook/docusaurus/pull/3143) fix(v2): absolute Links should be automatically prefixed by baseurl ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` - - [#3141](https://github.com/facebook/docusaurus/pull/3141) fix(v2): remove buggy routesLoaded + deprecate routesLoaded lifecycle ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#3140](https://github.com/facebook/docusaurus/pull/3140) fix(v2): navbar item links should allow unknown attributes ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-search-algolia` - - [#3138](https://github.com/facebook/docusaurus/pull/3138) fix(v2): add accessible label for Algolia search button ([@hobadams](https://github.com/hobadams)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus` - - [#3120](https://github.com/facebook/docusaurus/pull/3120) fix(v2): make config validation less strict ([@teikjun](https://github.com/teikjun)) - -#### :memo: Documentation - -- [#3145](https://github.com/facebook/docusaurus/pull/3145) docs(v2): add myself to /team page + add TeamProfileCard component ([@slorber](https://github.com/slorber)) -- [#3146](https://github.com/facebook/docusaurus/pull/3146) docs(v2): prettier docs ([@slorber](https://github.com/slorber)) -- [#3116](https://github.com/facebook/docusaurus/pull/3116) chore(v2): docs updates after release ([@slorber](https://github.com/slorber)) - -#### :house: Internal - -- Other - - [#3130](https://github.com/facebook/docusaurus/pull/3130) chore(v2): remove old versions ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x`, `docusaurus-init-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-migrate`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-sitemap`, `docusaurus-preset-bootstrap`, `docusaurus-preset-classic`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus`, `lqip-loader`, `stylelint-copyright` - - [#3114](https://github.com/facebook/docusaurus/pull/3114) chore(v2): prepare v2.0.0.alpha-59 release ([@slorber](https://github.com/slorber)) - -#### Committers: 4 - -- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) -- Hob Adams ([@hobadams](https://github.com/hobadams)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Teik Jun ([@teikjun](https://github.com/teikjun)) - -## 2.0.0-alpha.59 (2020-07-24) - -#### :rocket: New Feature - -- `docusaurus-migrate`, `docusaurus-plugin-client-redirects` - - [#3015](https://github.com/facebook/docusaurus/pull/3015) feat: automate migration from v1 to v2 ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- `docusaurus-init` - - [#3105](https://github.com/facebook/docusaurus/pull/3105) feat(v2): add docusaurus script for npm users ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-search-algolia` - - [#2815](https://github.com/facebook/docusaurus/pull/2815) feat(v2): introduce DocSearch v3 search ([@francoischalifour](https://github.com/francoischalifour)) -- `docusaurus-init`, `docusaurus-types`, `docusaurus` - - [#3059](https://github.com/facebook/docusaurus/pull/3059) feat(v2): broken links detection ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-utils` - - [#3084](https://github.com/facebook/docusaurus/pull/3084) feat(v2): absolute slugs and slug resolution system ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` - - [#3069](https://github.com/facebook/docusaurus/pull/3069) feat(v2): support for adding relative images and handling broken image links ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- `docusaurus-init`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-debug`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#2971](https://github.com/facebook/docusaurus/pull/2971) feat(v2): global data + useGlobalData + docs versions dropdown ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus` - - [#3080](https://github.com/facebook/docusaurus/pull/3080) feat(v2): add support for serve command ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-debug`, `docusaurus-types`, `docusaurus` - - [#3058](https://github.com/facebook/docusaurus/pull/3058) feat(v2): useDocusaurusContext().siteMetadata ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#3032](https://github.com/facebook/docusaurus/pull/3032) feat(v2): notify users when docusaurus version is outdated ([@teikjun](https://github.com/teikjun)) - - [#3033](https://github.com/facebook/docusaurus/pull/3033) feat(v2): add useBaseUrlUtils() hook ([@slorber](https://github.com/slorber)) - - [#3006](https://github.com/facebook/docusaurus/pull/3006) feat(v2): prompt user when default port is in use ([@taylorallen0913](https://github.com/taylorallen0913)) -- `docusaurus-module-type-aliases`, `docusaurus-plugin-debug`, `docusaurus` - - [#3050](https://github.com/facebook/docusaurus/pull/3050) feat(v2): Collect plugin versions to allow them to be inspected in debug plugin ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-theme-classic` - - [#3038](https://github.com/facebook/docusaurus/pull/3038) feat(v2): Support keywords meta in blog posts ([@dpkg](https://github.com/dpkg)) - - [#2974](https://github.com/facebook/docusaurus/pull/2974) feat(v2): Error when hooks depends on context is used outside of Layout ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-plugin-pwa`, `docusaurus` - - [#2205](https://github.com/facebook/docusaurus/pull/2205) feat(v2): Plugin for Offline/PWA support ([@codemonkey800](https://github.com/codemonkey800)) -- `docusaurus-plugin-ideal-image`, `docusaurus-types`, `docusaurus` - - [#2994](https://github.com/facebook/docusaurus/pull/2994) feat(v2): configureWebpack merge strategy + use file-loader for common asset types ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs` - - [#2989](https://github.com/facebook/docusaurus/pull/2989) feat(v2): add disableVersioning config to docs plugin ([@slorber](https://github.com/slorber)) - - [#2877](https://github.com/facebook/docusaurus/pull/2877) feat(v2): allow skipping build docs for next version ([@lex111](https://github.com/lex111)) -- `docusaurus-1.x` - - [#2955](https://github.com/facebook/docusaurus/pull/2955) feat(v1): add deletedDocs config to fix unwanted versioning fallback ([@aldeed](https://github.com/aldeed)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-types`, `docusaurus` - - [#2943](https://github.com/facebook/docusaurus/pull/2943) feat(v2): option and config validation life cycle method for official plugins ([@anshulrgoyal](https://github.com/anshulrgoyal)) - -#### :boom: Breaking Change - -- `docusaurus-init`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-debug`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#2971](https://github.com/facebook/docusaurus/pull/2971) feat(v2): global data + useGlobalData + docs versions dropdown ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus` - - [#3012](https://github.com/facebook/docusaurus/pull/3012) fix(v2): refactor color mode system ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus` - - [#3107](https://github.com/facebook/docusaurus/pull/3107) fix(v2): broken links detector: ignore existing folders ([@slorber](https://github.com/slorber)) - - [#3112](https://github.com/facebook/docusaurus/pull/3112) fix(v2): baseUrl is wrongly appended to anchor links ([@slorber](https://github.com/slorber)) - - [#3063](https://github.com/facebook/docusaurus/pull/3063) fix(v2): classify link hrefs with protocol identifier as internal ([@svtfrida](https://github.com/svtfrida)) -- `docusaurus-theme-classic` - - [#3106](https://github.com/facebook/docusaurus/pull/3106) fix(v2): dropdown navbar item: validation too strict ([@slorber](https://github.com/slorber)) - - [#3029](https://github.com/facebook/docusaurus/pull/3029) fix(v2): change description for blog post paginator ([@teikjun](https://github.com/teikjun)) -- `docusaurus-plugin-content-docs` - - [#3108](https://github.com/facebook/docusaurus/pull/3108) fix(v2): fix docs instance path typo ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-pages` - - [#3025](https://github.com/facebook/docusaurus/pull/3025) fix(v2):pass siteConfig as prop to pages ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- `docusaurus-init` - - [#3008](https://github.com/facebook/docusaurus/pull/3008) chore(v2): Add E2E test for yarn v2 ([@SamChou19815](https://github.com/SamChou19815)) -- Other - - [#3017](https://github.com/facebook/docusaurus/pull/3017) fix(v2): fix broken links on versions page ([@teikjun](https://github.com/teikjun)) -- `docusaurus-theme-classic`, `docusaurus` - - [#3012](https://github.com/facebook/docusaurus/pull/3012) fix(v2): refactor color mode system ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-content-docs`, `docusaurus-utils`, `docusaurus` - - [#3001](https://github.com/facebook/docusaurus/pull/3001) fix(v2): refactor routes.ts + add route hash for chunkNames key ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects`, `docusaurus-utils`, `docusaurus` - - [#3010](https://github.com/facebook/docusaurus/pull/3010) fix(v2): make client-redirect-plugin not baseUrl sensitive ([@teikjun](https://github.com/teikjun)) -- `docusaurus-1.x` - - [#2993](https://github.com/facebook/docusaurus/pull/2993) fix(relative path): last update date and by isn’t generated if localh… ([@amirulahmad](https://github.com/amirulahmad)) -- `docusaurus-plugin-client-redirects` - - [#2969](https://github.com/facebook/docusaurus/pull/2969) fix: fromExtensions and toExtensions translation when used with baseUrl ([@jknoxville](https://github.com/jknoxville)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic`, `docusaurus` - - [#3088](https://github.com/facebook/docusaurus/pull/3088) improve navbar menu ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader` - - [#3087](https://github.com/facebook/docusaurus/pull/3087) refactor(v2): async md image transformer + pathname protocol as an escape hatch ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-theme-live-codeblock`, `docusaurus-types` - - [#2970](https://github.com/facebook/docusaurus/pull/2970) feat(v2): add option validation for remaining official plugins ([@teikjun](https://github.com/teikjun)) -- `docusaurus` - - [#2987](https://github.com/facebook/docusaurus/pull/2987) chore(v2): use joi for config validation ([@anshulrgoyal](https://github.com/anshulrgoyal)) - -#### :memo: Documentation - -- [#3026](https://github.com/facebook/docusaurus/pull/3026) docs(v2): add documentation for migration command ([@teikjun](https://github.com/teikjun)) -- [#3094](https://github.com/facebook/docusaurus/pull/3094) docs(v2): showcase user Clutch ([@danielhochman](https://github.com/danielhochman)) -- [#3101](https://github.com/facebook/docusaurus/pull/3101) docs(v2):Add azure-pipelines CI guide ([@ayan-b](https://github.com/ayan-b)) -- [#3098](https://github.com/facebook/docusaurus/pull/3098) docs: Add azure-pipelines CI guide ([@ayan-b](https://github.com/ayan-b)) -- [#3086](https://github.com/facebook/docusaurus/pull/3086) doc(v2): replace heading position ([@eKhattak](https://github.com/eKhattak)) -- [#3082](https://github.com/facebook/docusaurus/pull/3082) fixing few typos and enhancing few sentences clarity ([@aladin002dz](https://github.com/aladin002dz)) -- [#3078](https://github.com/facebook/docusaurus/pull/3078) Updated link for #docusaurus-2-dev discord ([@jordanliu](https://github.com/jordanliu)) -- [#3076](https://github.com/facebook/docusaurus/pull/3076) docs(v2): showcase Runlet ([@vandreleal](https://github.com/vandreleal)) -- [#3040](https://github.com/facebook/docusaurus/pull/3040) docs(v2): correct the documentation for docs-only mode ([@teikjun](https://github.com/teikjun)) -- [#3034](https://github.com/facebook/docusaurus/pull/3034) docs(v2): showcase user Tasit ([@pcowgill](https://github.com/pcowgill)) -- [#3022](https://github.com/facebook/docusaurus/pull/3022) docs(v2): showcase Eta ([@nebrelbug](https://github.com/nebrelbug)) -- [#3011](https://github.com/facebook/docusaurus/pull/3011) docs(v1): external links ([@slorber](https://github.com/slorber)) -- [#2997](https://github.com/facebook/docusaurus/pull/2997) docs(v2): Document TypeScript support ([@SamChou19815](https://github.com/SamChou19815)) -- [#2973](https://github.com/facebook/docusaurus/pull/2973) docs(v2): Fix typo in markdown-features ([@ehsanjso](https://github.com/ehsanjso)) -- [#2991](https://github.com/facebook/docusaurus/pull/2991) Showcase Amphora Data ([@xtellurian](https://github.com/xtellurian)) -- [#2983](https://github.com/facebook/docusaurus/pull/2983) docs(v2): add plugin redirects production build note ([@slorber](https://github.com/slorber)) -- [#2967](https://github.com/facebook/docusaurus/pull/2967) docs(v2): fix typos in plugin-content examples ([@hi-matbub](https://github.com/hi-matbub)) -- [#2960](https://github.com/facebook/docusaurus/pull/2960) doc(v2): publish doc update after alpha.58 release ([@slorber](https://github.com/slorber)) -- [#2966](https://github.com/facebook/docusaurus/pull/2966) docs(v2): fix typo in plugin-content-pages example ([@hi-matbub](https://github.com/hi-matbub)) - -#### :house: Internal - -- `docusaurus-migrate` - - [#3113](https://github.com/facebook/docusaurus/pull/3113) chore(v2): ability to test the migration cli easily ([@slorber](https://github.com/slorber)) -- Other - - [#3099](https://github.com/facebook/docusaurus/pull/3099) fix(v2): netlify.toml shouldn't affect v1 site deployment config ([@slorber](https://github.com/slorber)) - - [#3068](https://github.com/facebook/docusaurus/pull/3068) chore(deps): bump lodash from 4.17.15 to 4.17.19 ([@dependabot[bot]](https://github.com/apps/dependabot)) - - [#2958](https://github.com/facebook/docusaurus/pull/2958) docs(v2): rename 2.0.0-alpha.57 to 2.0.0-alpha.58 ([@yangshun](https://github.com/yangshun)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus` - - [#3093](https://github.com/facebook/docusaurus/pull/3093) fix(v2): fix recent baseurl issues ([@slorber](https://github.com/slorber)) -- `docusaurus-mdx-loader` - - [#3087](https://github.com/facebook/docusaurus/pull/3087) refactor(v2): async md image transformer + pathname protocol as an escape hatch ([@slorber](https://github.com/slorber)) -- `docusaurus-plugin-pwa`, `docusaurus` - - [#3055](https://github.com/facebook/docusaurus/pull/3055) chore(v2): Adopt corejs 3 and only import at entry point ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-init`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus-utils`, `docusaurus` - - [#2998](https://github.com/facebook/docusaurus/pull/2998) chore(v2): refactor yarn tsc to yarn build + add theme-classic watch mode ([@slorber](https://github.com/slorber)) -- `docusaurus-init` - - [#3008](https://github.com/facebook/docusaurus/pull/3008) chore(v2): Add E2E test for yarn v2 ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-plugin-content-docs`, `docusaurus-utils`, `docusaurus` - - [#3001](https://github.com/facebook/docusaurus/pull/3001) fix(v2): refactor routes.ts + add route hash for chunkNames key ([@slorber](https://github.com/slorber)) -- `docusaurus` - - [#3007](https://github.com/facebook/docusaurus/pull/3007) fix(v2): Add two missing docusaurus core babel dependency ([@SamChou19815](https://github.com/SamChou19815)) - - [#2987](https://github.com/facebook/docusaurus/pull/2987) chore(v2): use joi for config validation ([@anshulrgoyal](https://github.com/anshulrgoyal)) - - [#2950](https://github.com/facebook/docusaurus/pull/2950) chore(v2): Implement a simple E2E testing mechanism for `docusausus start` ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-sitemap`, `docusaurus-theme-live-codeblock`, `docusaurus-types` - - [#2970](https://github.com/facebook/docusaurus/pull/2970) feat(v2): add option validation for remaining official plugins ([@teikjun](https://github.com/teikjun)) -- `docusaurus-theme-classic` - - [#2996](https://github.com/facebook/docusaurus/pull/2996) chore(v2): Merge devDependencies in theme-classic ([@SamChou19815](https://github.com/SamChou19815)) - - [#2977](https://github.com/facebook/docusaurus/pull/2977) chore(v2): Remove extraneous package-lock.json ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-plugin-client-redirects` - - [#2962](https://github.com/facebook/docusaurus/pull/2962) Feat: replace yup with joi for cleaner validation ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- `docusaurus-init`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#2976](https://github.com/facebook/docusaurus/pull/2976) chore(v2): Fix more eslint errors ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-sitemap`, `docusaurus-utils`, `docusaurus`, `lqip-loader` - - [#2972](https://github.com/facebook/docusaurus/pull/2972) chore(v2): Fix a lot of eslint warnings ([@SamChou19815](https://github.com/SamChou19815)) - -#### Committers: 25 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Amirul Ahmad ([@amirulahmad](https://github.com/amirulahmad)) -- Anshul Goyal ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- Arsalan Khattak ([@eKhattak](https://github.com/eKhattak)) -- Ayan Banerjee ([@ayan-b](https://github.com/ayan-b)) -- Ben Gubler ([@nebrelbug](https://github.com/nebrelbug)) -- Daniel Hochman ([@danielhochman](https://github.com/danielhochman)) -- Deepak Giri ([@dpkg](https://github.com/dpkg)) -- Eric Dobbertin ([@aldeed](https://github.com/aldeed)) -- François Chalifour ([@francoischalifour](https://github.com/francoischalifour)) -- Frida Hjelm ([@svtfrida](https://github.com/svtfrida)) -- Jeremy Asuncion ([@codemonkey800](https://github.com/codemonkey800)) -- John Knox ([@jknoxville](https://github.com/jknoxville)) -- Jordan Liu ([@jordanliu](https://github.com/jordanliu)) -- Mahfoudh Arous ([@aladin002dz](https://github.com/aladin002dz)) -- Paul Cowgill ([@pcowgill](https://github.com/pcowgill)) -- Rian Finnegan ([@xtellurian](https://github.com/xtellurian)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Taylor Allen ([@taylorallen0913](https://github.com/taylorallen0913)) -- Teik Jun ([@teikjun](https://github.com/teikjun)) -- Vandré Leal ([@vandreleal](https://github.com/vandreleal)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) -- ehsan jso ([@ehsanjso](https://github.com/ehsanjso)) -- matbub ([@hi-matbub](https://github.com/hi-matbub)) - -## 2.0.0-alpha.58 (2020-06-18) - -#### :rocket: New Feature - -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#2916](https://github.com/facebook/docusaurus/pull/2916) feat(v2): add a banner that links to latest version of documentation ([@teikjun](https://github.com/teikjun)) - - [#2682](https://github.com/facebook/docusaurus/pull/2682) feat(v2): expanded sidebar categories by default ([@jsjoeio](https://github.com/jsjoeio)) -- `docusaurus-plugin-debug`, `docusaurus-preset-classic` - - [#2928](https://github.com/facebook/docusaurus/pull/2928) feat(v2): Implement proof-of-concept Docusaurus Debug Dashboard ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-init`, `docusaurus` - - [#2903](https://github.com/facebook/docusaurus/pull/2903) feat(v2): Allow configuring babel via babel.config.js ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-plugin-client-redirects`, `docusaurus-utils` - - [#2793](https://github.com/facebook/docusaurus/pull/2793) feat(v2): docusaurus-plugin-client-redirects ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-live-codeblock` - - [#2826](https://github.com/facebook/docusaurus/pull/2826) feat(v2): allow adding components to react-live scope ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic`, `docusaurus` - - [#2856](https://github.com/facebook/docusaurus/pull/2856) feat(v2): allow specifying meta image for blog posts ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#2841](https://github.com/facebook/docusaurus/pull/2841) feat(v2): Allow swizzling prism-include-languages in theme-classic ([@SamChou19815](https://github.com/SamChou19815)) - -#### :boom: Breaking Change - -- `docusaurus-init`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#2895](https://github.com/facebook/docusaurus/pull/2895) chore(v2): replace classnames with clsx ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs` - - [#2861](https://github.com/facebook/docusaurus/pull/2861) fix(v2): do not create route for document that serve as docs home page ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#2682](https://github.com/facebook/docusaurus/pull/2682) feat(v2): expanded sidebar categories by default ([@jsjoeio](https://github.com/jsjoeio)) - -#### :bug: Bug Fix - -- `docusaurus-plugin-content-docs`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` - - [#2905](https://github.com/facebook/docusaurus/pull/2905) fix(v2): fix docs homepage permalink issues ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#2932](https://github.com/facebook/docusaurus/pull/2932) fix(v2): Add hooks to detect window resize, toggle off sidebar and navbar in desktop ([@guillaumejacquart](https://github.com/guillaumejacquart)) - - [#2909](https://github.com/facebook/docusaurus/pull/2909) fix(v2): adjust anchor offset when routes switched ([@lex111](https://github.com/lex111)) - - [#2896](https://github.com/facebook/docusaurus/pull/2896) fix(v2): set correct canonical url for docs home page ([@lex111](https://github.com/lex111)) - - [#2893](https://github.com/facebook/docusaurus/pull/2893) fix(v2): Do not automatically change tab when a non-existing option is selected ([@SamChou19815](https://github.com/SamChou19815)) - - [#2888](https://github.com/facebook/docusaurus/pull/2888) fix(v2): restore styles for menu scrollbar ([@lex111](https://github.com/lex111)) - - [#2857](https://github.com/facebook/docusaurus/pull/2857) fix(v2): treat inline code in raw HTML as native element ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#2951](https://github.com/facebook/docusaurus/pull/2951) fix(v2): Add optional-chaining and nullish-coalescing babel plugin ([@SamChou19815](https://github.com/SamChou19815)) - - [#2921](https://github.com/facebook/docusaurus/pull/2921) fix(v2): upgrade react-loadable-ssr-addon ([@slorber](https://github.com/slorber)) - - [#2854](https://github.com/facebook/docusaurus/pull/2854) fix(v2): fix broken build when swizzled NotFound component exist ([@lex111](https://github.com/lex111)) - - [#2829](https://github.com/facebook/docusaurus/pull/2829) fix(v2): Fix plugin path resolution ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-preset-classic` - - [#2944](https://github.com/facebook/docusaurus/pull/2944) fix(v2): Declare @docusaurus-plugin-debug as dependency of preset classic ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-init` - - [#2902](https://github.com/facebook/docusaurus/pull/2902) feat(v2): add nojekyll file to static folder for all templates ([@teikjun](https://github.com/teikjun)) -- `docusaurus-theme-bootstrap` - - [#2860](https://github.com/facebook/docusaurus/pull/2860) fix(v2): bootstrap doc sidebar ([@fanny](https://github.com/fanny)) -- Other - - [#2874](https://github.com/facebook/docusaurus/pull/2874) fix(v2): Getting Started URL ([@fanny](https://github.com/fanny)) -- `docusaurus-plugin-content-docs` - - [#2861](https://github.com/facebook/docusaurus/pull/2861) fix(v2): do not create route for document that serve as docs home page ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#2867](https://github.com/facebook/docusaurus/pull/2867) fix(v2): fix FOUC in doc sidebar and various improvements ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-search-algolia` - - [#2838](https://github.com/facebook/docusaurus/pull/2838) fix(v2): use base url to navigate to search page ([@tetunori](https://github.com/tetunori)) -- `docusaurus-utils` - - [#2855](https://github.com/facebook/docusaurus/pull/2855) fix(v2): strip images and footnotes for excerpt correctly ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-live-codeblock` - - [#2835](https://github.com/facebook/docusaurus/pull/2835) fix(v2): set proper font for live editor ([@lex111](https://github.com/lex111)) - -#### :nail_care: Polish - -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils`, `docusaurus` - - [#2884](https://github.com/facebook/docusaurus/pull/2884) polish(v2): improve Docusaurus 1 to 2 migration developer experience ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#2870](https://github.com/facebook/docusaurus/pull/2870) refactor(v2): combine nested theme providers into one ([@lex111](https://github.com/lex111)) - - [#2880](https://github.com/facebook/docusaurus/pull/2880) fix(v2): render as regular text uncollapsible categories ([@lex111](https://github.com/lex111)) - - [#2864](https://github.com/facebook/docusaurus/pull/2864) refactor(v2): add aria role for doc sidebar ([@lex111](https://github.com/lex111)) - - [#2859](https://github.com/facebook/docusaurus/pull/2859) refactor(v2): add aria label to paginators ([@lex111](https://github.com/lex111)) - - [#2858](https://github.com/facebook/docusaurus/pull/2858) refactor(v2): add missing main landmark for needed pages ([@lex111](https://github.com/lex111)) -- Other - - [#2862](https://github.com/facebook/docusaurus/pull/2862) Updated banner in solidarity ([@JoelMarcey](https://github.com/JoelMarcey)) - -#### :memo: Documentation - -- [#2946](https://github.com/facebook/docusaurus/pull/2946) docs(v2): add require.resolve to plugin imports on remaining pages ([@teikjun](https://github.com/teikjun)) -- [#2941](https://github.com/facebook/docusaurus/pull/2941) docs(v2): wrap all plugin imports in require.resolve() ([@TomBrien](https://github.com/TomBrien)) -- [#2934](https://github.com/facebook/docusaurus/pull/2934) docs(v2): add useThemeContext note ([@Drewbi](https://github.com/Drewbi)) -- [#2935](https://github.com/facebook/docusaurus/pull/2935) docs(v2): Add router implementation note ([@Drewbi](https://github.com/Drewbi)) -- [#2933](https://github.com/facebook/docusaurus/pull/2933) docs(v2): add documentation for multiple blogs ([@teikjun](https://github.com/teikjun)) -- [#2910](https://github.com/facebook/docusaurus/pull/2910) docs(v2): fix GitHub action workflow in docs ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- [#2886](https://github.com/facebook/docusaurus/pull/2886) docs(v2): fix typo in command on installation page ([@pglezen](https://github.com/pglezen)) -- [#2887](https://github.com/facebook/docusaurus/pull/2887) docs(v2): make .nojekyll warning more obvious ([@yangshun](https://github.com/yangshun)) -- [#2865](https://github.com/facebook/docusaurus/pull/2865) docs(v2): description field in frontmatter of blog post ([@lex111](https://github.com/lex111)) -- [#2839](https://github.com/facebook/docusaurus/pull/2839) docs(v2): \_index docs page does not show a sidebar ([@aeneasr](https://github.com/aeneasr)) -- [#2852](https://github.com/facebook/docusaurus/pull/2852) misc: move runme demo in block quote about v2 ([@lex111](https://github.com/lex111)) -- [#2842](https://github.com/facebook/docusaurus/pull/2842) docs(v2): Update ZEIT to Vercel ([@Nishikoh](https://github.com/Nishikoh)) - -#### :house: Internal - -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` - - [#2948](https://github.com/facebook/docusaurus/pull/2948) refactor(v2): legacy export = syntax ([@slorber](https://github.com/slorber)) -- `docusaurus-init`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-utils`, `docusaurus` - - [#2922](https://github.com/facebook/docusaurus/pull/2922) misc(v2): better dx: yarn clear, yarn watch, yarn serve ([@slorber](https://github.com/slorber)) -- Other - - [#2929](https://github.com/facebook/docusaurus/pull/2929) chore(v2): Run E2E tests in CI ([@SamChou19815](https://github.com/SamChou19815)) - - [#2899](https://github.com/facebook/docusaurus/pull/2899) chore(deps): bump websocket-extensions from 0.1.3 to 0.1.4 ([@dependabot[bot]](https://github.com/apps/dependabot)) - - [#2897](https://github.com/facebook/docusaurus/pull/2897) refactor(v2): synchronize yarn/npm command on site ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-bootstrap` - - [#2931](https://github.com/facebook/docusaurus/pull/2931) chore(v2): remove unused hooks from bootstrap theme ([@fanny](https://github.com/fanny)) -- `docusaurus-1.x`, `docusaurus-plugin-content-docs` - - [#2906](https://github.com/facebook/docusaurus/pull/2906) chore(v2): fix async tests ([@slorber](https://github.com/slorber)) -- `docusaurus-theme-classic` - - [#2858](https://github.com/facebook/docusaurus/pull/2858) refactor(v2): add missing main landmark for needed pages ([@lex111](https://github.com/lex111)) - -#### :running_woman: Performance - -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-sitemap` - - [#2936](https://github.com/facebook/docusaurus/pull/2936) perf(v2): convert synchronous filewrite to asynchronous ([@moonrailgun](https://github.com/moonrailgun)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#2900](https://github.com/facebook/docusaurus/pull/2900) chore(v2): replace Clipboard with copy-text-to-clipboard ([@lex111](https://github.com/lex111)) -- `docusaurus-init`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#2895](https://github.com/facebook/docusaurus/pull/2895) chore(v2): replace classnames with clsx ([@lex111](https://github.com/lex111)) - -#### Committers: 18 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Anshul Goyal ([@anshulrgoyal](https://github.com/anshulrgoyal)) -- Drew Alexander ([@Drewbi](https://github.com/Drewbi)) -- Fanny ([@fanny](https://github.com/fanny)) -- Guillaume Jacquart ([@guillaumejacquart](https://github.com/guillaumejacquart)) -- Joe Previte ([@jsjoeio](https://github.com/jsjoeio)) -- Joel Marcey ([@JoelMarcey](https://github.com/JoelMarcey)) -- Koki Nishihara ([@Nishikoh](https://github.com/Nishikoh)) -- Paul Glezen ([@pglezen](https://github.com/pglezen)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Teik Jun ([@teikjun](https://github.com/teikjun)) -- Tom Brien ([@TomBrien](https://github.com/TomBrien)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) -- [@belokonm](https://github.com/belokonm) -- hackerman ([@aeneasr](https://github.com/aeneasr)) -- moonrailgun ([@moonrailgun](https://github.com/moonrailgun)) -- tetunori ([@tetunori](https://github.com/tetunori)) - -## 2.0.0-alpha.57 (2020-06-18) - -Bad release, check ## 2.0.0-alpha.58 - -## 2.0.0-alpha.56 (2020-05-28) - -#### :boom: Breaking Change - -- If you refer to modules (plugins) in your config file in a string form, you will need to replace them with `require.resolve` calls, for example: - -```diff -- plugins: ['@docusaurus/plugin-google-analytics'] -+ plugins: [require.resolve('@docusaurus/plugin-google-analytics')] -``` - -- `docusaurus-theme-classic` - - [#2818](https://github.com/facebook/docusaurus/pull/2818) feat(v2): automatically add base url to logo link ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#2791](https://github.com/facebook/docusaurus/pull/2791) refactor(v2): show search icon only on mobiles ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#2780](https://github.com/facebook/docusaurus/pull/2780) feat(v2): open external links in new tab by default ([@jknoxville](https://github.com/jknoxville)) - -#### :rocket: New Feature - -- `docusaurus-types`, `docusaurus` - - [#2770](https://github.com/facebook/docusaurus/pull/2770) feat(v2): allow deploy without building website ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#2818](https://github.com/facebook/docusaurus/pull/2818) feat(v2): automatically add base url to logo link ([@lex111](https://github.com/lex111)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#2645](https://github.com/facebook/docusaurus/pull/2645) fix(v2): enable scrolling for sidebar menu only ([@lex111](https://github.com/lex111)) - - [#2800](https://github.com/facebook/docusaurus/pull/2800) fix(v2): make proper h1 font size on mobiles ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#2788](https://github.com/facebook/docusaurus/pull/2788) fix(v2): use `require.resolve` for all webpack presets and plugins ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus-plugin-content-docs` - - [#2785](https://github.com/facebook/docusaurus/pull/2785) fix(v2): do not show sidebar on reserved docs home page ([@lex111](https://github.com/lex111)) - - [#2777](https://github.com/facebook/docusaurus/pull/2777) fix(v2): check for docs homepage correctly ([@lex111](https://github.com/lex111)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#2820](https://github.com/facebook/docusaurus/pull/2820) chore(v2): upgrade Infima to 0.2.0-alpha.12 ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-search-algolia` - - [#2814](https://github.com/facebook/docusaurus/pull/2814) refactor(v2): align search icon to center on mobiles ([@lex111](https://github.com/lex111)) - - [#2799](https://github.com/facebook/docusaurus/pull/2799) refactor(v2): increase search input on medium screens ([@lex111](https://github.com/lex111)) -- `docusaurus-init` - - [#2802](https://github.com/facebook/docusaurus/pull/2802) misc: minor improvements for init templates ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#2791](https://github.com/facebook/docusaurus/pull/2791) refactor(v2): show search icon only on mobiles ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#2783](https://github.com/facebook/docusaurus/pull/2783) refactor(v2): make external links more secure ([@lex111](https://github.com/lex111)) - -#### :memo: Documentation - -- [#2809](https://github.com/facebook/docusaurus/pull/2809) docs(v2): add mention on DocSearch when you run the crawler on your own ([@s-pace](https://github.com/s-pace)) - -#### :house: Internal - -- [#2778](https://github.com/facebook/docusaurus/pull/2778) fix(v2): do not highlight root docs path in navbar ([@lex111](https://github.com/lex111)) - -#### Committers: 8 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- James McShane ([@jmcshane](https://github.com/jmcshane)) -- John Knox ([@jknoxville](https://github.com/jknoxville)) -- Kasper Bøgebjerg Pedersen ([@kasperp](https://github.com/kasperp)) -- Muhammad Ali ([@mrmuhammadali](https://github.com/mrmuhammadali)) -- Piotr Baran ([@piotros](https://github.com/piotros)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Sylvain Pace ([@s-pace](https://github.com/s-pace)) - -## 2.0.0-alpha.55 (2020-05-19) - -#### :boom: Breaking Change - -- `infima` - - - The following Infima classes have been renamed for consistency: - - - `page-item` → `pagination__item` - - `pagination-nav__link--label` → `pagination-nav__label` - - `pagination-nav__link--sublabel` → `pagination-nav__sublabel` - - `tab-item` → `tabs__item` - - `tab-item--active` → `tabs__item--active` - - If you have swizzled components, you need to replace these class names. - -- `docusaurus` - - - [#2764](https://github.com/facebook/docusaurus/pull/2764) feat(v2): allow import SVG images ([@lex111](https://github.com/lex111)) - -#### :rocket: New Feature - -- `docusaurus` - - [#2764](https://github.com/facebook/docusaurus/pull/2764) feat(v2): allow import SVG images ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#2690](https://github.com/facebook/docusaurus/pull/2690) feat(v2): allow activeBaseTest in NavLink ([@nebrelbug](https://github.com/nebrelbug)) - - [#2694](https://github.com/facebook/docusaurus/pull/2694) feat(v2): add canonical URL to `` ([@jcomack](https://github.com/jcomack)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#2652](https://github.com/facebook/docusaurus/pull/2652) feat(v2): allow home page for docs ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-search-algolia`, `docusaurus` - - [#2756](https://github.com/facebook/docusaurus/pull/2756) feat(v2): add search page 🔎 ([@lex111](https://github.com/lex111)) - -#### :bug: Bug Fix - -- `docusaurus-plugin-content-docs`, `docusaurus-utils` - - [#2701](https://github.com/facebook/docusaurus/pull/2701) fix(v2): remove Markdown syntax from excerpt ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#2765](https://github.com/facebook/docusaurus/pull/2765) fix(v2): remove invalid attr from mobile nav links ([@lex111](https://github.com/lex111)) - - [#2760](https://github.com/facebook/docusaurus/pull/2760) fix(v2): move anchor link to right of heading ([@lex111](https://github.com/lex111)) - - [#2758](https://github.com/facebook/docusaurus/pull/2758) fix(v2): remove extra top margin of tab item ([@lex111](https://github.com/lex111)) - - [#2759](https://github.com/facebook/docusaurus/pull/2759) fix(v2): restore hiding of docs toc ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-search-algolia` - - [#2762](https://github.com/facebook/docusaurus/pull/2762) fix(v2): avoid duplication search input in navbar ([@lex111](https://github.com/lex111)) -- `lqip-loader` - - [#2693](https://github.com/facebook/docusaurus/pull/2693) fix(v2): add support ES Module to lqip-loader ([@ykzts](https://github.com/ykzts)) -- `docusaurus-init` - - [#2751](https://github.com/facebook/docusaurus/pull/2751) fix(v2): fix index page features.length when 0 ([@jdeniau](https://github.com/jdeniau)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#2773](https://github.com/facebook/docusaurus/pull/2773) chore(v2): upgrade Infima to 0.2.0-alpha.11 ([@lex111](https://github.com/lex111)) - - [#2766](https://github.com/facebook/docusaurus/pull/2766) refactor(v2): remove extra active CSS class for menu item links ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-live-codeblock` - - [#2767](https://github.com/facebook/docusaurus/pull/2767) refactor(v2): add support for dark mode to live code blocks ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-search-algolia` - - [#2761](https://github.com/facebook/docusaurus/pull/2761) refactor(v2): improve UX of search page ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-bootstrap`, `docusaurus-theme-classic` - - [#2729](https://github.com/facebook/docusaurus/pull/2729) chore(v2): upgrade Infima to 0.2.0-alpha.10 ([@lex111](https://github.com/lex111)) -- `docusaurus-utils` - - [#2696](https://github.com/facebook/docusaurus/pull/2696) refactor(v2): make semicolon optional in imports for excerpt ([@lex111](https://github.com/lex111)) - -#### :memo: Documentation - -- [#2768](https://github.com/facebook/docusaurus/pull/2768) docs(v2): various improvements ([@lex111](https://github.com/lex111)) -- [#2670](https://github.com/facebook/docusaurus/pull/2670) docs(v2): add deployment workflow manual for GitHub Actions ([@artemkovalyov](https://github.com/artemkovalyov)) - -#### :house: Internal - -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus` - - [#2464](https://github.com/facebook/docusaurus/pull/2464) refactor(v2): add @theme-init alias to give access to initial components ([@lex111](https://github.com/lex111)) - -#### :running_woman: Performance - -- `docusaurus` - - [#2684](https://github.com/facebook/docusaurus/pull/2684) refactor(v2): replace EJS with Eta for SSR generation ([@nebrelbug](https://github.com/nebrelbug)) - -#### Committers: 13 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Artem Kovalov ([@artemkovalyov](https://github.com/artemkovalyov)) -- Ben Gubler ([@nebrelbug](https://github.com/nebrelbug)) -- Fanny ([@fanny](https://github.com/fanny)) -- Jimmy ([@jcomack](https://github.com/jcomack)) -- Jonny Nabors ([@jonnynabors](https://github.com/jonnynabors)) -- Julien Deniau ([@jdeniau](https://github.com/jdeniau)) -- Marco Moretti ([@marcosvega91](https://github.com/marcosvega91)) -- Rajiv Singh ([@iamrajiv](https://github.com/iamrajiv)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Taylor Reece ([@taylorreece](https://github.com/taylorreece)) -- Yamagishi Kazutoshi ([@ykzts](https://github.com/ykzts)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) - -## 2.0.0-alpha.54 (2020-04-28) - -**HOTFIX for 2.0.0-alpha.53**. - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#2688](https://github.com/facebook/docusaurus/pull/2688) fix(v2): add default value for options in theme classic ([@lex111](https://github.com/lex111)) -- `docusaurus-module-type-aliases` - - [#2687](https://github.com/facebook/docusaurus/pull/2687) fix(v2): Add all webpack module aliases to type declaration file ([@SamChou19815](https://github.com/SamChou19815)) - -#### :memo: Documentation - -- [#2680](https://github.com/facebook/docusaurus/pull/2680) docs(v2): add swizzle example ([@jsjoeio](https://github.com/jsjoeio)) - -#### Committers: 3 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Joe Previte ([@jsjoeio](https://github.com/jsjoeio)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) - -## 2.0.0-alpha.53 (2020-04-27) - -**HOTFIX for 2.0.0-alpha.51**. - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#2676](https://github.com/facebook/docusaurus/pull/2676) fix(v2): allow build website without custom css ([@lex111](https://github.com/lex111)) - -#### Committers: 1 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) - -## 2.0.0-alpha.51 (2020-04-27) - -#### :boom: Breaking Change - -- `infima` - - The following infima variables have been renamed for consistency: - - `--ifm-font-base-color` → `--ifm-font-color-base` - - `--ifm-font-base-color-inverse` → `--ifm-font-color-base-inverse` - - `--ifm-font-color-secondary` → `--ifm-font-color-secondary` - -#### :rocket: New Feature - -- `docusaurus-theme-classic` - - [#2660](https://github.com/facebook/docusaurus/pull/2660) feat(v2): add ability to specify CSS class for navbar item ([@lex111](https://github.com/lex111)) - - [#2597](https://github.com/facebook/docusaurus/pull/2597) feat(v2): add ability set dark mode by default ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#2665](https://github.com/facebook/docusaurus/pull/2665) feat(v2): add fallback to BrowserOnly component ([@lex111](https://github.com/lex111)) -- `docusaurus-types`, `docusaurus` - - [#2630](https://github.com/facebook/docusaurus/pull/2630) feat(v2): add CLI option for polling ([@TomBrien](https://github.com/TomBrien)) -- `docusaurus-init` - - [#2541](https://github.com/facebook/docusaurus/pull/2541) feat(v2): add showReadingTime and editUrl to the templates ([@fanny](https://github.com/fanny)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-utils` - - [#2524](https://github.com/facebook/docusaurus/pull/2524) feat(v2): add edit url in post page ([@fanny](https://github.com/fanny)) -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` - - [#2531](https://github.com/facebook/docusaurus/pull/2531) feat(v2): add blog post estimated reading time ([@JoseRenan](https://github.com/JoseRenan)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#2672](https://github.com/facebook/docusaurus/pull/2672) fix(v2): add a11y support for dropdown ([@lex111](https://github.com/lex111)) - - [#2649](https://github.com/facebook/docusaurus/pull/2649) fix(v2): hide sidebar after click on child item ([@lex111](https://github.com/lex111)) - - [#2631](https://github.com/facebook/docusaurus/pull/2631) fix(v2): hide doc sidebar on mobiles ([@lex111](https://github.com/lex111)) - - [#2626](https://github.com/facebook/docusaurus/pull/2626) fix(v2): make border right of doc sidebar equals doc page ([@lex111](https://github.com/lex111)) - - [#2625](https://github.com/facebook/docusaurus/pull/2625) fix(v2): disable tab focus on collapsed doc sidebar items ([@lex111](https://github.com/lex111)) - - [#2602](https://github.com/facebook/docusaurus/pull/2602) fix(v2): inherit color for announcement bar close icon ([@lex111](https://github.com/lex111)) - - [#2582](https://github.com/facebook/docusaurus/pull/2582) fix(v2): remove horizontal scroll on docs page ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#2666](https://github.com/facebook/docusaurus/pull/2666) chore(v2): upgrade prism-react-renderer to latest version ([@lex111](https://github.com/lex111)) - - [#2533](https://github.com/facebook/docusaurus/pull/2533) fix(v2): add rounded corners in code blocks properly ([@lex111](https://github.com/lex111)) -- `docusaurus-1.x`, `docusaurus-init-1.x`, `docusaurus-init`, `docusaurus-plugin-content-docs`, `docusaurus` - - [#2661](https://github.com/facebook/docusaurus/pull/2661) chore: upgrade shelljs to 0.8.4 ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-preset-classic`, `docusaurus-theme-classic` - - [#2642](https://github.com/facebook/docusaurus/pull/2642) fix(v2): use remark-admonitions separately in each plugin instead of in preset only ([@lex111](https://github.com/lex111)) -- `docusaurus-utils` - - [#2380](https://github.com/facebook/docusaurus/pull/2380) fix(v2): ignore import declarations in excerpt ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-sitemap` - - [#2616](https://github.com/facebook/docusaurus/pull/2616) fix(v2): don't include 404 page in sitemaps ([@RDIL](https://github.com/RDIL)) - - [#2530](https://github.com/facebook/docusaurus/pull/2530) fix(v2): Use `writeFileSync` to write generated sitemap.xml to avoid early termination ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus` - - [#2558](https://github.com/facebook/docusaurus/pull/2558) fix(v2): properly link top-level github pages sites in deploy command ([@RDIL](https://github.com/RDIL)) - - [#2580](https://github.com/facebook/docusaurus/pull/2580) fix(v2): do not process anchor links by router ([@lex111](https://github.com/lex111)) - - [#2579](https://github.com/facebook/docusaurus/pull/2579) fix(v2): treat mailto and tel links properly ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog` - - [#2540](https://github.com/facebook/docusaurus/pull/2540) fix(v2): use synchronous write for generate blog feeds ([@lex111](https://github.com/lex111)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#2656](https://github.com/facebook/docusaurus/pull/2656) refactor(v2): lose focus of active sidebar item after click on it ([@lex111](https://github.com/lex111)) - - [#2627](https://github.com/facebook/docusaurus/pull/2627) refactor(v2): extract scroll position detection into separate hook ([@lex111](https://github.com/lex111)) - - [#2595](https://github.com/facebook/docusaurus/pull/2595) refactor(v2): make margin top on blog pages as on other pages ([@lex111](https://github.com/lex111)) - - [#2588](https://github.com/facebook/docusaurus/pull/2588) refactor(v2): remove redundant container on docs page ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus` - - [#2585](https://github.com/facebook/docusaurus/pull/2585) refactor(v2): use nav link component only where needed ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#2556](https://github.com/facebook/docusaurus/pull/2556) refactor(v2): enhance CLI experience ([@RDIL](https://github.com/RDIL)) - - [#2529](https://github.com/facebook/docusaurus/pull/2529) refactor(v2): replace few Lodash methods with native counterparts ([@Simek](https://github.com/Simek)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#2534](https://github.com/facebook/docusaurus/pull/2534) refactor(v2): make better code blocks ([@lex111](https://github.com/lex111)) - - [#2526](https://github.com/facebook/docusaurus/pull/2526) fix(v2): make code block nicer again ([@yangshun](https://github.com/yangshun)) -- `docusaurus-plugin-content-docs` - - [#2519](https://github.com/facebook/docusaurus/pull/2519) chore(v2): use single method Lodash packages in docs plugin ([@Simek](https://github.com/Simek)) - -#### :memo: Documentation - -- [#2659](https://github.com/facebook/docusaurus/pull/2659) fix(docs): mention that appID is optional ([@s-pace](https://github.com/s-pace)) -- [#2596](https://github.com/facebook/docusaurus/pull/2596) docs(v2): remove duplicated package.json in installation directory structure ([@jaylees14](https://github.com/jaylees14)) -- [#2572](https://github.com/facebook/docusaurus/pull/2572) docs(v2): mention that `plugin-ideal-image` only perform compression on a production build ([@Noah-Silvera](https://github.com/Noah-Silvera)) -- [#2570](https://github.com/facebook/docusaurus/pull/2570) docs(v2): fix syntax error for @docusaurus/plugin-ideal-image example ([@Noah-Silvera](https://github.com/Noah-Silvera)) -- [#2566](https://github.com/facebook/docusaurus/pull/2566) docs(v2): be more polite ([@lex111](https://github.com/lex111)) -- [#2559](https://github.com/facebook/docusaurus/pull/2559) doc(v2): remove legacy blog metadata ([@RDIL](https://github.com/RDIL)) -- [#2549](https://github.com/facebook/docusaurus/pull/2549) docs(v2): command for swizzling all components ([@fanny](https://github.com/fanny)) -- [#2547](https://github.com/facebook/docusaurus/pull/2547) docs(v2): Fix typo in team page ([@SamChou19815](https://github.com/SamChou19815)) -- [#2545](https://github.com/facebook/docusaurus/pull/2545) docs(v2): add community pages ([@yangshun](https://github.com/yangshun)) -- [#2521](https://github.com/facebook/docusaurus/pull/2521) docs(v2): useThemeContext hook ([@lex111](https://github.com/lex111)) - -#### :house: Internal - -- `docusaurus-types`, `docusaurus` - - [#2578](https://github.com/facebook/docusaurus/pull/2578) refactor(v2): Convert docusaurus-core to TypeScript ([@SamChou19815](https://github.com/SamChou19815)) -- Other - - [#2569](https://github.com/facebook/docusaurus/pull/2569) docs(v2): showcase user Tourmaline ([@watzon](https://github.com/watzon)) - - [#2553](https://github.com/facebook/docusaurus/pull/2553) misc(v2): remove deprecated/useless lerna field ([@slorber](https://github.com/slorber)) -- `docusaurus-1.x`, `lqip-loader` - - [#2563](https://github.com/facebook/docusaurus/pull/2563) chore(v2): fix lint, tweak lqip-loader utils comment ([@Simek](https://github.com/Simek)) -- `lqip-loader` - - [#2561](https://github.com/facebook/docusaurus/pull/2561) chore(v2): add lqip-loader tests, clarify loader code, improve README ([@Simek](https://github.com/Simek)) -- `docusaurus-plugin-ideal-image`, `lqip-loader` - - [#2544](https://github.com/facebook/docusaurus/pull/2544) refactor(v2): import lqip-loader to monorepo, fix build on Node 13, fix lint-staged ([@Simek](https://github.com/Simek)) -- `docusaurus-init` - - [#2542](https://github.com/facebook/docusaurus/pull/2542) chore(v2): update Prettier config ([@lex111](https://github.com/lex111)) -- `docusaurus-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-sitemap`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus`, `stylelint-copyright` - - [#2538](https://github.com/facebook/docusaurus/pull/2538) chore(v2): upgrade devDependencies ([@yangshun](https://github.com/yangshun)) -- `docusaurus-utils` - - [#2536](https://github.com/facebook/docusaurus/pull/2536) refactor(v2): replace Lodash with single methods packages in utils ([@Simek](https://github.com/Simek)) -- `docusaurus` - - [#2535](https://github.com/facebook/docusaurus/pull/2535) refactor(v2): replace Lodash with single methods packages in core ([@Simek](https://github.com/Simek)) - -#### Committers: 18 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Anayo Oleru ([@AnayoOleru](https://github.com/AnayoOleru)) -- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) -- Chris Watson ([@watzon](https://github.com/watzon)) -- Fanny ([@fanny](https://github.com/fanny)) -- Jay Lees ([@jaylees14](https://github.com/jaylees14)) -- Joe Previte ([@jsjoeio](https://github.com/jsjoeio)) -- José Renan ([@JoseRenan](https://github.com/JoseRenan)) -- Kamil Kisiela ([@kamilkisiela](https://github.com/kamilkisiela)) -- Kristóf Poduszló ([@kripod](https://github.com/kripod)) -- Mehmet Yatkı ([@yatki](https://github.com/yatki)) -- Noah Silvera ([@Noah-Silvera](https://github.com/Noah-Silvera)) -- Reece Dunham ([@RDIL](https://github.com/RDIL)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Sylvain Pace ([@s-pace](https://github.com/s-pace)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Tom Brien ([@TomBrien](https://github.com/TomBrien)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) - -## 2.0.0-alpha.50 (2020-04-02) - -**HOTFIX for 2.0.0-alpha.49**. - -#### :bug: Bug Fix - -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#2509](https://github.com/facebook/docusaurus/pull/2509) fix(v2): synchronize code block components changes ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#2498](https://github.com/facebook/docusaurus/pull/2498) fix(v2): blog item styling ([@yangshun](https://github.com/yangshun)) - - [#2489](https://github.com/facebook/docusaurus/pull/2489) fix(v2): fix HTML issues nav dropdown and highlight docs item ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#2496](https://github.com/facebook/docusaurus/pull/2496) fix(v2): do not force terminate building when running deploy command ([@lex111](https://github.com/lex111)) -- `docusaurus-utils` - - [#2497](https://github.com/facebook/docusaurus/pull/2497) fix(v2): unbreak blog-only mode routing by deplicating starting forward slashes ([@SamChou19815](https://github.com/SamChou19815)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#2505](https://github.com/facebook/docusaurus/pull/2505) fix(v2): tweak colors for announcement bar ([@yangshun](https://github.com/yangshun)) - - [#2504](https://github.com/facebook/docusaurus/pull/2504) refactor(v2): improve announcement bar ([@lex111](https://github.com/lex111)) - - [#2495](https://github.com/facebook/docusaurus/pull/2495) refactor(v2): update HTML markup of pagination for better a11y ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#2502](https://github.com/facebook/docusaurus/pull/2502) fix(v2): make code block nicer ([@yangshun](https://github.com/yangshun)) -- `docusaurus-plugin-content-docs`, `docusaurus` - - [#2490](https://github.com/facebook/docusaurus/pull/2490) fix(v2): use lodash instead of array-map-polyfill ([@lex111](https://github.com/lex111)) - -#### :memo: Documentation - -- `docusaurus-theme-classic` - - [#2500](https://github.com/facebook/docusaurus/pull/2500) docs(v2): misc docs updates ([@yangshun](https://github.com/yangshun)) - -#### :house: Internal - -- [#2486](https://github.com/facebook/docusaurus/pull/2486) misc: add instructions about test release ([@lex111](https://github.com/lex111)) - -#### Committers: 5 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Can Gencer ([@cangencer](https://github.com/cangencer)) -- Richard Chan ([@iWun](https://github.com/iWun)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) - -## 2.0.0-alpha.49 (2020-04-01) - -#### :rocket: New Feature - -- `docusaurus-theme-classic` - - [#2487](https://github.com/facebook/docusaurus/pull/2487) feat(v2): nav dropdown ([@yangshun](https://github.com/yangshun)) - - [#2456](https://github.com/facebook/docusaurus/pull/2456) feat(v2): support comments for code highlighting ([@elviswolcott](https://github.com/elviswolcott)) - - [#2330](https://github.com/facebook/docusaurus/pull/2330) feat(v2): add announcement bar ([@lex111](https://github.com/lex111)) - - [#2440](https://github.com/facebook/docusaurus/pull/2440) feat(v2): make clickable sidebar logo ([@lex111](https://github.com/lex111)) - - [#2366](https://github.com/facebook/docusaurus/pull/2366) feat(v2): support syncing tab choices ([@SamChou19815](https://github.com/SamChou19815)) -- `docusaurus` - - [#2323](https://github.com/facebook/docusaurus/pull/2323) feat(v2): add a way to exclude components from build-time prerendering ([@lex111](https://github.com/lex111)) - - [#2469](https://github.com/facebook/docusaurus/pull/2469) feat(v2): add TypeScript support for theme components ([@SamChou19815](https://github.com/SamChou19815)) - - [#2455](https://github.com/facebook/docusaurus/pull/2455) feat(v2): add @theme-original alias to give access to pre-swizzled components ([@yangshun](https://github.com/yangshun)) - - [#2438](https://github.com/facebook/docusaurus/pull/2438) feat(v2): add version to page's generated meta tags ([@lex111](https://github.com/lex111)) -- `docusaurus-types`, `docusaurus` - - [#2474](https://github.com/facebook/docusaurus/pull/2474) feat(v2): add ability to create unminimized bundles ([@lex111](https://github.com/lex111)) - - [#2417](https://github.com/facebook/docusaurus/pull/2417) feat(v2): allow custom output directory for build ([@ZachJW34](https://github.com/ZachJW34)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#2346](https://github.com/facebook/docusaurus/pull/2346) feat(v2): add filename in CodeBlock ([@KohheePeace](https://github.com/KohheePeace)) -- `docusaurus-plugin-content-docs`, `docusaurus` - - [#2444](https://github.com/facebook/docusaurus/pull/2444) feat(v2): allow nested sidebar category shorthand syntax ([@slorber](https://github.com/slorber)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#2483](https://github.com/facebook/docusaurus/pull/2483) fix(v2): do not render sidebar logo if used sticky navbar ([@lex111](https://github.com/lex111)) - - [#2475](https://github.com/facebook/docusaurus/pull/2475) fix(v2): make correct Open Graph title for doc page ([@lex111](https://github.com/lex111)) - - [#2436](https://github.com/facebook/docusaurus/pull/2436) fix(v2): update twitter:card to summary_large_image ([@lex111](https://github.com/lex111)) - - [#2434](https://github.com/facebook/docusaurus/pull/2434) fix(v2): add support dark logo for sidebar logo ([@lex111](https://github.com/lex111)) - - [#2420](https://github.com/facebook/docusaurus/pull/2420) fix(v2): fix external URL for og:image tag ([@38elements](https://github.com/38elements)) -- `docusaurus-theme-live-codeblock` - - [#2480](https://github.com/facebook/docusaurus/pull/2480) fix(v2): various improvements for accessibility ([@lex111](https://github.com/lex111)) -- `docusaurus-mdx-loader`, `docusaurus-theme-classic` - - [#2479](https://github.com/facebook/docusaurus/pull/2479) chore(v2): upgrade MDX to 1.5.8 ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#2476](https://github.com/facebook/docusaurus/pull/2476) fix(v2): improve code block scroll accessibility ([@lex111](https://github.com/lex111)) - - [#2442](https://github.com/facebook/docusaurus/pull/2442) fix(v2): various improvements for accessibility ([@lex111](https://github.com/lex111)) -- `docusaurus-preset-classic`, `docusaurus-theme-classic` - - [#2477](https://github.com/facebook/docusaurus/pull/2477) chore(v2): upgrade remark-admonitions for a11y fixes ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#2462](https://github.com/facebook/docusaurus/pull/2462) fix(v2): do not force terminate building when bundle analyzer is on ([@lex111](https://github.com/lex111)) - - [#2393](https://github.com/facebook/docusaurus/pull/2393) fix(v2): normalize location for route matching ([@rlamana](https://github.com/rlamana)) - - [#2443](https://github.com/facebook/docusaurus/pull/2443) fix(v2): always exit after successful build ([@mohrash92](https://github.com/mohrash92)) - - [#2437](https://github.com/facebook/docusaurus/pull/2437) fix(v2): do not force terminate building if client bundle failed in development mode ([@lex111](https://github.com/lex111)) - - [#2424](https://github.com/facebook/docusaurus/pull/2424) fix(v2): make correct internal link check ([@lex111](https://github.com/lex111)) -- `docusaurus-preset-classic` - - [#2451](https://github.com/facebook/docusaurus/pull/2451) fix(v2): pass options to remark-admonitions ([@elviswolcott](https://github.com/elviswolcott)) -- `docusaurus-mdx-loader` - - [#2426](https://github.com/facebook/docusaurus/pull/2426) fix(v2): remove HTML from heading slug ([@lex111](https://github.com/lex111)) -- `docusaurus-utils` - - [#2405](https://github.com/facebook/docusaurus/pull/2405) fix(v2): properly dedupe forward slashes in the entire URL path ([@rlamana](https://github.com/rlamana)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#2485](https://github.com/facebook/docusaurus/pull/2485) refactor(v2): remove unnecessary X-UA-Compatible meta tag ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog` - - [#2460](https://github.com/facebook/docusaurus/pull/2460) refactor(v2): use single method package instead of whole Lodash package in blog plugin ([@Simek](https://github.com/Simek)) -- Other - - [#2428](https://github.com/facebook/docusaurus/pull/2428) polish(v2): use npm-to-yarn for the npm2yarn remark plugin ([@nebrelbug](https://github.com/nebrelbug)) - -#### :memo: Documentation - -- Other - - [#2478](https://github.com/facebook/docusaurus/pull/2478) docs(v2): mark that in dev server some features may not work ([@lex111](https://github.com/lex111)) - - [#2472](https://github.com/facebook/docusaurus/pull/2472) docs(v2): fix typo in deployment docs ([@GermaVinsmoke](https://github.com/GermaVinsmoke)) - - [#2423](https://github.com/facebook/docusaurus/pull/2423) docs(v2): add Sass/SCSS under the styling section ([@rlamana](https://github.com/rlamana)) - - [#2446](https://github.com/facebook/docusaurus/pull/2446) docs(v2): add docusaurus-plugin-sass to community plugins ([@rlamana](https://github.com/rlamana)) - - [#2408](https://github.com/facebook/docusaurus/pull/2408) docs(v2): suggest Surge for quick deployment ([@fakela](https://github.com/fakela)) - - [#2401](https://github.com/facebook/docusaurus/pull/2401) docs(v2): add resources page ([@yangshun](https://github.com/yangshun)) - - [#2413](https://github.com/facebook/docusaurus/pull/2413) docs(v2): include appId key for Algolia ([@TheodoreChu](https://github.com/TheodoreChu)) - - [#2411](https://github.com/facebook/docusaurus/pull/2411) docs:(v2): add Netlify configuration warning ([@bravo-kernel](https://github.com/bravo-kernel)) - - [#2397](https://github.com/facebook/docusaurus/pull/2397) docs(v2):update alpha version to current version ([@fakela](https://github.com/fakela)) - - [#2395](https://github.com/facebook/docusaurus/pull/2395) docs(v2): clarify instructions on docs-only mode ([@phoqe](https://github.com/phoqe)) -- `docusaurus-init` - - [#2458](https://github.com/facebook/docusaurus/pull/2458) fix(v2): expand broken admonitions ([@elviswolcott](https://github.com/elviswolcott)) - -#### :house: Internal - -- `docusaurus` - - [#2461](https://github.com/facebook/docusaurus/pull/2461) chore(v2): upgrade react-dev-utils ([@lex111](https://github.com/lex111)) -- Other - - [#2450](https://github.com/facebook/docusaurus/pull/2450) docs(v2): Adding Motion Layout to Docusaurus users ([@jeffersonlicet](https://github.com/jeffersonlicet)) - - [#2450](https://github.com/facebook/docusaurus/pull/2450) docs(v2): Adding Motion Layout to Docusaurus users ([@jeffersonlicet](https://github.com/jeffersonlicet)) - - [#2439](https://github.com/facebook/docusaurus/pull/2439) polish(v2): add logo for dark mode ([@lex111](https://github.com/lex111)) - - [#2435](https://github.com/facebook/docusaurus/pull/2435) fix(v2): fix aspect ratio for Open Graph image ([@lex111](https://github.com/lex111)) - - [#2433](https://github.com/facebook/docusaurus/pull/2433) chore(v2): ignore JetBrains editors .iml files ([@slorber](https://github.com/slorber)) - - [#2416](https://github.com/facebook/docusaurus/pull/2416) docs(v2): Add Build Tracker to Showcase page ([@paularmstrong](https://github.com/paularmstrong)) - - [#2388](https://github.com/facebook/docusaurus/pull/2388) docs(v1): showcase user Day.js ([@iamkun](https://github.com/iamkun)) -- `stylelint-copyright` - - [#2415](https://github.com/facebook/docusaurus/pull/2415) misc: improve stylelint rule ([@ayshiff](https://github.com/ayshiff)) - -#### Committers: 24 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) -- Ben Gubler ([@nebrelbug](https://github.com/nebrelbug)) -- Elvis Wolcott ([@elviswolcott](https://github.com/elviswolcott)) -- Fanny ([@fanny](https://github.com/fanny)) -- Favour Kelvin ([@fakela](https://github.com/fakela)) -- Jefferson Licet ([@jeffersonlicet](https://github.com/jeffersonlicet)) -- Kohhee Peace ([@KohheePeace](https://github.com/KohheePeace)) -- Linus Långberg ([@phoqe](https://github.com/phoqe)) -- Luke Collier ([@lukecollier](https://github.com/lukecollier)) -- Nisar Hassan Naqvi ([@nisarhassan12](https://github.com/nisarhassan12)) -- Paul Armstrong ([@paularmstrong](https://github.com/paularmstrong)) -- Ramón Lamana ([@rlamana](https://github.com/rlamana)) -- Rémi Doreau ([@ayshiff](https://github.com/ayshiff)) -- Sam Zhou ([@SamChou19815](https://github.com/SamChou19815)) -- Sébastien Lorber ([@slorber](https://github.com/slorber)) -- Theodore Chu ([@TheodoreChu](https://github.com/TheodoreChu)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) -- [@38elements](https://github.com/38elements) -- [@GermaVinsmoke](https://github.com/GermaVinsmoke) -- [@ZachJW34](https://github.com/ZachJW34) -- [@bravo-kernel](https://github.com/bravo-kernel) -- [@iamkun](https://github.com/iamkun) -- [@mohrash92](https://github.com/mohrash92) - -## 2.0.0-alpha.48 (2020-03-08) - -**HOTFIX for 2.0.0-alpha.44**. - -#### :bug: Bug Fix - -- Other - - [#2383](https://github.com/facebook/docusaurus/pull/2383) fix(v2): specify proper version for stylelint-copyright ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#2382](https://github.com/facebook/docusaurus/pull/2382) fix(v2): add missing preset-typescript dependency ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#2386](https://github.com/facebook/docusaurus/pull/2386) fix(v2): add missing prismjs dependency and Noop component ([@lex111](https://github.com/lex111)) - -#### Committers: 1 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) - -## 2.0.0-alpha.44 (2020-03-08) - -#### :rocket: New Feature - -- `docusaurus-theme-classic` - - [#2250](https://github.com/facebook/docusaurus/pull/2250) feat(v2): add support specify new languages for Prism ([@lex111](https://github.com/lex111)) - - [#2344](https://github.com/facebook/docusaurus/pull/2344) feat(v2): allow specifying custom target for logo link ([@lex111](https://github.com/lex111)) - - [#2327](https://github.com/facebook/docusaurus/pull/2327) feat(v2): add ability to use HTML in footer copyright ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog` - - [#2335](https://github.com/facebook/docusaurus/pull/2335) feat(v2): add draft feature to blog posts ([@lex111](https://github.com/lex111)) -- `docusaurus-init`, `docusaurus-theme-classic` - - [#2303](https://github.com/facebook/docusaurus/pull/2303) docs(v2): Nav links activeBasePath ([@yangshun](https://github.com/yangshun)) -- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus` - - [#2296](https://github.com/facebook/docusaurus/pull/2296) feat(v2): add ExecutionEnvironment API ([@yangshun](https://github.com/yangshun)) - -#### :bug: Bug Fix - -- `docusaurus` - - [#2345](https://github.com/facebook/docusaurus/pull/2345) fix(v2): force terminate building if client bundle failed ([@lex111](https://github.com/lex111)) - - [#2310](https://github.com/facebook/docusaurus/pull/2310) fix(v2): add @babel/preset-typescript to babel-loader ([@deniaz](https://github.com/deniaz)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#2371](https://github.com/facebook/docusaurus/pull/2371) fix(v2): remove line break from end of code blocks ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog` - - [#2326](https://github.com/facebook/docusaurus/pull/2326) fix(v2): linkify blog posts ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#2324](https://github.com/facebook/docusaurus/pull/2324) fix(v2): properly set dark mode logo on build-time prerendering ([@lex111](https://github.com/lex111)) - - [#2325](https://github.com/facebook/docusaurus/pull/2325) fix(v2): switch a toggle when system theme changed ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-pages`, `docusaurus-utils` - - [#2334](https://github.com/facebook/docusaurus/pull/2334) fix(v2): make proper path to pages in TS ([@lex111](https://github.com/lex111)) -- Other - - [#2316](https://github.com/facebook/docusaurus/pull/2316) fix(v2): properly scale logo on IE 11 ([@lex111](https://github.com/lex111)) - -#### :nail_care: Polish - -- `docusaurus-theme-search-algolia` - - [#2376](https://github.com/facebook/docusaurus/pull/2376) refactor(v2): clean up and improve Algolia styles ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia` - - [#2372](https://github.com/facebook/docusaurus/pull/2372) chore(v2): upgrade Infima and remark-admonitions ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#2367](https://github.com/facebook/docusaurus/pull/2367) refactor(v2): increase CSS specificity on application container ([@lex111](https://github.com/lex111)) -- `docusaurus-init`, `stylelint-copyright` - - [#2363](https://github.com/facebook/docusaurus/pull/2363) fix(v2): improve stylelint copyright header rule ([@yangshun](https://github.com/yangshun)) -- `docusaurus-types`, `docusaurus` - - [#2342](https://github.com/facebook/docusaurus/pull/2342) chore(v2): mark tagline field as optional ([@lex111](https://github.com/lex111)) - -#### :memo: Documentation - -- [#2378](https://github.com/facebook/docusaurus/pull/2378) docs(v2): add section for docs-only mode ([@phoqe](https://github.com/phoqe)) -- [#2357](https://github.com/facebook/docusaurus/pull/2357) docs(v2): fix getPathsToWatch() example syntax in lifecycle APIs ([@rlamana](https://github.com/rlamana)) -- [#2351](https://github.com/facebook/docusaurus/pull/2351) docs(v2): add examples to plugin usage doc ([@Noah-Silvera](https://github.com/Noah-Silvera)) -- [#2343](https://github.com/facebook/docusaurus/pull/2343) docs(v2): fix typo in remark-admonitions example ([@hassanfarid](https://github.com/hassanfarid)) -- [#2340](https://github.com/facebook/docusaurus/pull/2340) docs(v2): mention about disabling Jekyll when using GitHub pages ([@amilajack](https://github.com/amilajack)) -- [#2338](https://github.com/facebook/docusaurus/pull/2338) docs(v2): guide on upgrading Docusaurus within a project ([@TheodoreChu](https://github.com/TheodoreChu)) -- [#2313](https://github.com/facebook/docusaurus/pull/2313) docs(v2): move the quotes to remark admonitions ([@Zhencha0Cai](https://github.com/Zhencha0Cai)) -- [#2307](https://github.com/facebook/docusaurus/pull/2307) docs(v1): fix Windows instructions for GitHub Pages publishing ([@jartuso](https://github.com/jartuso)) -- [#2300](https://github.com/facebook/docusaurus/pull/2300) docs(v2): make blog plugin config example valid ([@balloob](https://github.com/balloob)) -- [#2289](https://github.com/facebook/docusaurus/pull/2289) docs(v2): add instructions on Travis CI deployment ([@mohamedsgap](https://github.com/mohamedsgap)) - -#### :house: Internal - -- Other - - [#2369](https://github.com/facebook/docusaurus/pull/2369) misc: mention about v2 in README file ([@lex111](https://github.com/lex111)) - - [#2368](https://github.com/facebook/docusaurus/pull/2368) misc: add note about edits in versioned docs ([@lex111](https://github.com/lex111)) - - [#2333](https://github.com/facebook/docusaurus/pull/2333) docs: update use of npm/yarn in contributing.md ([@jsjoeio](https://github.com/jsjoeio)) - - [#2328](https://github.com/facebook/docusaurus/pull/2328) docs(v2): remove unwanted black line from DocSearch showcase image ([@s-pace](https://github.com/s-pace)) - - [#2319](https://github.com/facebook/docusaurus/pull/2319) docs(v2): showcase user Algolia ([@scottilee](https://github.com/scottilee)) -- `docusaurus-init` - - [#2322](https://github.com/facebook/docusaurus/pull/2322) docs(v2): fix misc styling ([@lex111](https://github.com/lex111)) - -#### Committers: 16 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Amila Welihinda ([@amilajack](https://github.com/amilajack)) -- Hassan Farid ([@hassanfarid](https://github.com/hassanfarid)) -- Joe Previte ([@jsjoeio](https://github.com/jsjoeio)) -- Linus Långberg ([@phoqe](https://github.com/phoqe)) -- Mohamed Abdel Nasser ([@mohamedsgap](https://github.com/mohamedsgap)) -- Noah Silvera ([@Noah-Silvera](https://github.com/Noah-Silvera)) -- Paulus Schoutsen ([@balloob](https://github.com/balloob)) -- Ramón Lamana ([@rlamana](https://github.com/rlamana)) -- Robert ([@deniaz](https://github.com/deniaz)) -- Scott Lee ([@scottilee](https://github.com/scottilee)) -- Sylvain Pace ([@s-pace](https://github.com/s-pace)) -- Theodore Chu ([@TheodoreChu](https://github.com/TheodoreChu)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) -- Zhenchao Cai ([@Zhencha0Cai](https://github.com/Zhencha0Cai)) -- [@jartuso](https://github.com/jartuso) - -## 2.0.0-alpha.43 (2020-02-18) - -**HOTFIX for 2.0.0-alpha.41**. - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#2292](https://github.com/facebook/docusaurus/pull/2292) chore(v2): update Infima to 0.2.0-alpha.4 ([@yangshun](https://github.com/yangshun)) - - [#2291](https://github.com/facebook/docusaurus/pull/2291) fix(v2): fix build and deps install ([@lex111](https://github.com/lex111)) - -#### Committers: 2 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) - -## 2.0.0-alpha.41 (2020-02-16) - -#### :rocket: New Feature - -- `docusaurus-init`, `docusaurus-preset-classic`, `docusaurus-theme-classic` - - [#2224](https://github.com/facebook/docusaurus/pull/2224) feat(v2): add remark-admonitions to @docusaurus/preset-classic ([@elviswolcott](https://github.com/elviswolcott)) -- `docusaurus-theme-classic`, `docusaurus` - - [#2263](https://github.com/facebook/docusaurus/pull/2263) feat(v2): pluralize posts on tag's page ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#2261](https://github.com/facebook/docusaurus/pull/2261) feat(v2): allow to specify different logo for dark mode ([@lex111](https://github.com/lex111)) - - [#2253](https://github.com/facebook/docusaurus/pull/2253) feat(v2): allow specify custom link for logo ([@lex111](https://github.com/lex111)) - - [#2255](https://github.com/facebook/docusaurus/pull/2255) feat(v2): add site title to meta title ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-pages`, `docusaurus-utils`, `docusaurus` - - [#2221](https://github.com/facebook/docusaurus/pull/2221) feat(v2): allow for TypeScript pages and components ([@jonathanrdelgado](https://github.com/jonathanrdelgado)) - -#### :boom: Breaking Change - -- `docusaurus-theme-classic` - - [#2235](https://github.com/facebook/docusaurus/pull/2235) fix(v2): show doc sidebar on pages with case-sensitive paths ([@lex111](https://github.com/lex111)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#2285](https://github.com/facebook/docusaurus/pull/2285) fix(v2): fix codeblock copy button not including blank lines ([@KohheePeace](https://github.com/KohheePeace)) - - [#2241](https://github.com/facebook/docusaurus/pull/2241) fix(v2): make code blocks scrollable ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#2259](https://github.com/facebook/docusaurus/pull/2259) fix(v2): use site title if enabled blog-only mode ([@lex111](https://github.com/lex111)) - - [#2248](https://github.com/facebook/docusaurus/pull/2248) fix(v2): adjust correct behavior of navbar when active anchor ([@lex111](https://github.com/lex111)) - - [#2235](https://github.com/facebook/docusaurus/pull/2235) fix(v2): show doc sidebar on pages with case-sensitive paths ([@lex111](https://github.com/lex111)) - - [#2162](https://github.com/facebook/docusaurus/pull/2162) fix(v2): unify anchor behavior ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-search-algolia` - - [#2262](https://github.com/facebook/docusaurus/pull/2262) fix(v2): remove focus on search input when hovering over it ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` - - [#2240](https://github.com/facebook/docusaurus/pull/2240) fix(v2): hide read more button on non-truncated posts ([@lex111](https://github.com/lex111)) -- `docusaurus` - - [#2237](https://github.com/facebook/docusaurus/pull/2237) fix(v2): include base url in 404 route ([@lex111](https://github.com/lex111)) -- `docusaurus-mdx-loader` - - [#2236](https://github.com/facebook/docusaurus/pull/2236) fix(v2): escape link text in TOC ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-live-codeblock` - - [#2227](https://github.com/facebook/docusaurus/pull/2227) fix(v2): render correct theme for live code blocks on SSR ([@lex111](https://github.com/lex111)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#2254](https://github.com/facebook/docusaurus/pull/2254) refactor(v2): avoid to use raw theme values ([@lex111](https://github.com/lex111)) - -#### :memo: Documentation - -- [#2281](https://github.com/facebook/docusaurus/pull/2281) docs: update windows deploy command ([@OndrejNepozitek](https://github.com/OndrejNepozitek)) -- [#2257](https://github.com/facebook/docusaurus/pull/2257) docs(v2): require using JSX flavored style objects in mdx ([@wgao19](https://github.com/wgao19)) -- [#2251](https://github.com/facebook/docusaurus/pull/2251) docs(v2): collapsible categories in sidebar ([@lex111](https://github.com/lex111)) -- [#2218](https://github.com/facebook/docusaurus/pull/2218) docs(v2): update link to available prism themes ([@jsjoeio](https://github.com/jsjoeio)) -- [#2216](https://github.com/facebook/docusaurus/pull/2216) docs(v2): fix plugin-content-docs config comment typo ([@sdowding](https://github.com/sdowding)) - -#### :house: Internal - -- Other - - [#2256](https://github.com/facebook/docusaurus/pull/2256) fix(v2): add title for Feedback page ([@lex111](https://github.com/lex111)) - - [#2246](https://github.com/facebook/docusaurus/pull/2246) docs(v2): add Benthos to showcase ([@Jeffail](https://github.com/Jeffail)) - - [#2242](https://github.com/facebook/docusaurus/pull/2242) docs(v1): showcase user Jafar ([@galhavivi](https://github.com/galhavivi)) - - [#2238](https://github.com/facebook/docusaurus/pull/2238) docs(v1): showcase Dime ([@hbulens](https://github.com/hbulens)) - - [#2233](https://github.com/facebook/docusaurus/pull/2233) docs(v2): showcase user supabase ([@awalias](https://github.com/awalias)) - - [#2226](https://github.com/facebook/docusaurus/pull/2226) docs(v1): showcase user Adapt.js ([@mterrel](https://github.com/mterrel)) - - [#2225](https://github.com/facebook/docusaurus/pull/2225) docs(v1): add The Diff Podcast to users ([@JoelMarcey](https://github.com/JoelMarcey)) - - [#2219](https://github.com/facebook/docusaurus/pull/2219) chore(v1): Updated users list, removing sites not using docusaurus ([@jjwill](https://github.com/jjwill)) -- `docusaurus-theme-classic`, `docusaurus` - - [#2239](https://github.com/facebook/docusaurus/pull/2239) chore(eslint): require curly brackets on all blocks ([@lex111](https://github.com/lex111)) - -#### Committers: 18 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Ashley Jeffs ([@Jeffail](https://github.com/Jeffail)) -- Elie Dutheil ([@edwandr](https://github.com/edwandr)) -- Elvis Wolcott ([@elviswolcott](https://github.com/elviswolcott)) -- Evan Rubinton ([@erubi](https://github.com/erubi)) -- Gal Havivi ([@galhavivi](https://github.com/galhavivi)) -- Hanseung Yoo ([@trustyoo86](https://github.com/trustyoo86)) -- Hendrik Bulens ([@hbulens](https://github.com/hbulens)) -- JavaScript Joe ([@jsjoeio](https://github.com/jsjoeio)) -- Joel Marcey ([@JoelMarcey](https://github.com/JoelMarcey)) -- Jonathan Delgado ([@jonathanrdelgado](https://github.com/jonathanrdelgado)) -- Joshua Williams ([@jjwill](https://github.com/jjwill)) -- KohheePeace ([@KohheePeace](https://github.com/KohheePeace)) -- Mark Terrel ([@mterrel](https://github.com/mterrel)) -- Ondřej Nepožitek ([@OndrejNepozitek](https://github.com/OndrejNepozitek)) -- Scott Dowding ([@sdowding](https://github.com/sdowding)) -- Wei Gao ([@wgao19](https://github.com/wgao19)) -- [@awalias](https://github.com/awalias) - -## 2.0.0-alpha.40 (2019-12-25) - -#### :rocket: New Feature - -- `docusaurus-theme-classic` - - [#2117](https://github.com/facebook/docusaurus/pull/2117) feat(v2): auto switch theme depending on the system theme ([@lex111](https://github.com/lex111)) - - [#2055](https://github.com/facebook/docusaurus/pull/2055) feat(v2): hide navbar on scroll ([@lex111](https://github.com/lex111)) - -#### :bug: Bug Fix - -- `docusaurus` - - [#2145](https://github.com/facebook/docusaurus/pull/2145) fix(v2): remove style-loader, use minicssextract in both dev & prod ([@endiliey](https://github.com/endiliey)) - - [#2122](https://github.com/facebook/docusaurus/pull/2122) fix(v2): dont collapse whitespace in minified html ([@endiliey](https://github.com/endiliey)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` - - [#2105](https://github.com/facebook/docusaurus/pull/2105) fix(v2): move metadata export after compiling MDX to avoid weird MDX parsing error. ([@endiliey](https://github.com/endiliey)) -- `docusaurus-theme-classic` - - [#2113](https://github.com/facebook/docusaurus/pull/2113) fix(v2): set stored theme only if it exists ([@lex111](https://github.com/lex111)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#2129](https://github.com/facebook/docusaurus/pull/2129) fix(v2): disable scroll while mobile menu open ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic`, `docusaurus` - - [#2127](https://github.com/facebook/docusaurus/pull/2127) refactor(v2): toggle data-theme with vanilla js instead of react helmet ([@endiliey](https://github.com/endiliey)) -- `docusaurus-theme-search-algolia`, `docusaurus` - - [#2125](https://github.com/facebook/docusaurus/pull/2125) feat(v2): lazy load algolia css so its not render blocking ([@endiliey](https://github.com/endiliey)) - -#### :memo: Documentation - -- Other - - [#2135](https://github.com/facebook/docusaurus/pull/2135) docs(v1): add space between "out" and "Docusaurus" ([@TransmissionsDev](https://github.com/TransmissionsDev)) - - [#2128](https://github.com/facebook/docusaurus/pull/2128) docs(v1): showcase user Shrine ([@janko](https://github.com/janko)) - - [#2110](https://github.com/facebook/docusaurus/pull/2110) docs(v2): fix pages routing inaccurate info ([@endiliey](https://github.com/endiliey)) - - [#2106](https://github.com/facebook/docusaurus/pull/2106) fix(v2): add missing hyphen in color generator ([@lex111](https://github.com/lex111)) - - [#2104](https://github.com/facebook/docusaurus/pull/2104) feat(v2): add color generator for primary colors ([@yangshun](https://github.com/yangshun)) - - [#2103](https://github.com/facebook/docusaurus/pull/2103) docs: mention about moving docs directory into website ([@yangshun](https://github.com/yangshun)) -- `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock` - - [#2114](https://github.com/facebook/docusaurus/pull/2114) fix(v2): add syntax highlight to generated colors ([@lex111](https://github.com/lex111)) - -#### :house: Internal - -- Other - - [#2126](https://github.com/facebook/docusaurus/pull/2126) docs: promote Docusaurus 2 usage ([@yangshun](https://github.com/yangshun)) - - [#2119](https://github.com/facebook/docusaurus/pull/2119) fix(v2): align GH button in vertical center ([@lex111](https://github.com/lex111)) -- `docusaurus-init` - - [#2124](https://github.com/facebook/docusaurus/pull/2124) feat(v2): add Facebook Docusaurus 2 template ([@yangshun](https://github.com/yangshun)) -- `docusaurus` - - [#2111](https://github.com/facebook/docusaurus/pull/2111) feat(v2): explicit babel/runtime version ([@endiliey](https://github.com/endiliey)) -- `docusaurus-1.x`, `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-live-codeblock`, `docusaurus` - - [#2102](https://github.com/facebook/docusaurus/pull/2102) misc: add command to run prettier on docs ([@yangshun](https://github.com/yangshun)) - -#### :running_woman: Performance - -- `docusaurus` - - [#2118](https://github.com/facebook/docusaurus/pull/2118) perf(v2): reduce HTML payload by eliminating chunk-map ([@endiliey](https://github.com/endiliey)) - - [#2116](https://github.com/facebook/docusaurus/pull/2116) feat(v2): minify html ([@endiliey](https://github.com/endiliey)) - -#### Committers: 6 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Endi ([@endiliey](https://github.com/endiliey)) -- Janko Marohnić ([@janko](https://github.com/janko)) -- Nick McCurdy ([@nickmccurdy](https://github.com/nickmccurdy)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) -- t11s ([@TransmissionsDev](https://github.com/TransmissionsDev)) - -## 2.0.0-alpha.39 (2019-12-07) - -#### :bug: Bug Fix - -- `docusaurus` - - [#2099](https://github.com/facebook/docusaurus/pull/2099) fix(v2): escape import path on windows ([@endiliey](https://github.com/endiliey)) -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs` - - [#2095](https://github.com/facebook/docusaurus/pull/2095) fix(v2): metadata error if markdown does not have ending line ([@endiliey](https://github.com/endiliey)) - -#### :house: Internal - -- Other - - [#2100](https://github.com/facebook/docusaurus/pull/2100) chore(CI): docusaurus build on Windows with GitHub actions ([@endiliey](https://github.com/endiliey)) -- `docusaurus` - - [#2096](https://github.com/facebook/docusaurus/pull/2096) feat(v2): better & nice looking error overlay ([@endiliey](https://github.com/endiliey)) - -#### Committers: 1 - -- Endi ([@endiliey](https://github.com/endiliey)) - -## 2.0.0-alpha.38 (2019-12-06) - -#### :boom: Breaking Change - -- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-utils` - - [#2088](https://github.com/facebook/docusaurus/pull/2088) perf(v2): smaller bundlesize by embedding metadata to content ([@endiliey](https://github.com/endiliey)) - -If you have swizzled any Docs/Blog component that depends on metadata, you'll have to update. If you haven't, no action is needed. - -For example, if you've swizzled `@theme/DocItem`. You'll have to update - -```diff -- const {metadata, content: DocContent} = props; -+ const {content: DocContent} = props; -+ const {metadata} = DocContent; -``` - -#### :bug: Bug Fix - -- `docusaurus` - - [#2086](https://github.com/facebook/docusaurus/pull/2086) fix(v2): windows compatibility regression ([@endiliey](https://github.com/endiliey)) -- `docusaurus-plugin-ideal-image` - - [#2074](https://github.com/facebook/docusaurus/pull/2074) fix(v2): fix plugin-ideal-image breaking website (exports not defined) ([@endiliey](https://github.com/endiliey)) - -#### :nail_care: Polish - -- `docusaurus-mdx-loader` - - [#2085](https://github.com/facebook/docusaurus/pull/2085) misc(v2): update mdx loader plugin README ([@shivangna](https://github.com/shivangna)) - -#### :house: Internal - -- `docusaurus-1.x` - - [#2087](https://github.com/facebook/docusaurus/pull/2087) fix(v1): add key to versions.map in versions.js ([@FeynmanDNA](https://github.com/FeynmanDNA)) - - [#2083](https://github.com/facebook/docusaurus/pull/2083) refactor(v1): fix props for ProjectTitle ([@FeynmanDNA](https://github.com/FeynmanDNA)) -- `docusaurus` - - [#2081](https://github.com/facebook/docusaurus/pull/2081) refactor(v2): move scripts/stylesheets injection to server side ([@endiliey](https://github.com/endiliey)) - - [#2080](https://github.com/facebook/docusaurus/pull/2080) refactor(v2): minor code refactoring on component creator ([@endiliey](https://github.com/endiliey)) - -#### :running_woman: Performance - -- `docusaurus-utils` - - [#2089](https://github.com/facebook/docusaurus/pull/2089) perf(v2): improve dev build time by not overwriting file if possible ([@endiliey](https://github.com/endiliey)) -- `docusaurus-theme-search-algolia` - - [#2079](https://github.com/facebook/docusaurus/pull/2079) perf(v2): algolia search result no longer cause full page refresh ([@endiliey](https://github.com/endiliey)) - - [#2076](https://github.com/facebook/docusaurus/pull/2076) perf(v2): load algolia JS only when user interacts with search ([@endiliey](https://github.com/endiliey)) - -#### Committers: 4 - -- Endi ([@endiliey](https://github.com/endiliey)) -- KYY ([@FeynmanDNA](https://github.com/FeynmanDNA)) -- Shivangna Kaistha ([@shivangna](https://github.com/shivangna)) -- kaichu ([@qshiwu](https://github.com/qshiwu)) - -## 2.0.0-alpha.37 (2019-12-01) - -#### :boom: Breaking Change - -- `docusaurus-init`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-classic`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-search-algolia`, `docusaurus-utils`, `docusaurus` - - [#2045](https://github.com/facebook/docusaurus/pull/2045) breaking(v2): minimum required nodejs version 8.9-> 8.10 so we can use es2017 ([@endiliey](https://github.com/endiliey)) - -#### :rocket: New Feature - -- `docusaurus-theme-classic`, `docusaurus` - - [#2069](https://github.com/facebook/docusaurus/pull/2069) feat(v2): support prefers-color-scheme & fix dark mode FOUC on refresh ([@endiliey](https://github.com/endiliey)) -- `docusaurus-plugin-content-blog` - - [#2000](https://github.com/facebook/docusaurus/pull/2000) feat(v2): add meta RSS/Atom feed links to head ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` - - [#2057](https://github.com/facebook/docusaurus/pull/2057) feat(v2): injectHtmlTags API to inject head and/or body html tags ([@endiliey](https://github.com/endiliey)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-sitemap`, `docusaurus-theme-classic`, `docusaurus` - - [#2032](https://github.com/facebook/docusaurus/pull/2032) feat(v2): allow non sidebar category to be first item of sidebar ([@endiliey](https://github.com/endiliey)) -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - - [#1983](https://github.com/facebook/docusaurus/pull/1983) feat(v2): docs versioning ❄️🔥 ([@endiliey](https://github.com/endiliey)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic`, `docusaurus` - - [#2069](https://github.com/facebook/docusaurus/pull/2069) feat(v2): support prefers-color-scheme & fix dark mode FOUC on refresh ([@endiliey](https://github.com/endiliey)) -- `docusaurus-mdx-loader` - - [#2067](https://github.com/facebook/docusaurus/pull/2067) fix(v2): toc should not be broken for heading with html inline code ([@endiliey](https://github.com/endiliey)) -- `docusaurus-theme-classic` - - [#2064](https://github.com/facebook/docusaurus/pull/2064) fix(v2): markdown reference to file should not be page not found ([@endiliey](https://github.com/endiliey)) - - [#2061](https://github.com/facebook/docusaurus/pull/2061) fix(v2): fix docs sidebar highlighting if link is partially matched ([@endiliey](https://github.com/endiliey)) -- `docusaurus` - - [#2042](https://github.com/facebook/docusaurus/pull/2042) fix(v2): remove css order warning if css imports are not sorted ([@endiliey](https://github.com/endiliey)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#2066](https://github.com/facebook/docusaurus/pull/2066) refactor(v2): add title attribute to anchor link ([@lex111](https://github.com/lex111)) - - [#1990](https://github.com/facebook/docusaurus/pull/1990) refactor(v2): make better a11y for tabs ([@lex111](https://github.com/lex111)) - - [#2034](https://github.com/facebook/docusaurus/pull/2034) feat(v2): style sidebar on overflow ([@endiliey](https://github.com/endiliey)) - -#### :memo: Documentation - -- Other - - [#2068](https://github.com/facebook/docusaurus/pull/2068) docs(v2): quick proofread docs ([@endiliey](https://github.com/endiliey)) - - [#2047](https://github.com/facebook/docusaurus/pull/2047) docs(v2): add manual migration guide for versioning ([@endiliey](https://github.com/endiliey)) - - [#2036](https://github.com/facebook/docusaurus/pull/2036) docs(v2): Reorganize migration guide ([@wgao19](https://github.com/wgao19)) - - [#2052](https://github.com/facebook/docusaurus/pull/2052) fix(v2): make proper spelling of Yarn in tabs ([@lex111](https://github.com/lex111)) - - [#2040](https://github.com/facebook/docusaurus/pull/2040) docs(v2): showcase user vector.dev :) ([@binarylogic](https://github.com/binarylogic)) - - [#2038](https://github.com/facebook/docusaurus/pull/2038) docs(v2): add documentation on versioning ([@endiliey](https://github.com/endiliey)) - - [#2037](https://github.com/facebook/docusaurus/pull/2037) docs(v2): display yarn and npm command on website ([@endiliey](https://github.com/endiliey)) - - [#2051](https://github.com/facebook/docusaurus/pull/2051) docs(v2): more examples on lifecycle apis, cleanup ([@endiliey](https://github.com/endiliey)) - -#### :house: Internal - -- `docusaurus-plugin-content-blog` - - [#2072](https://github.com/facebook/docusaurus/pull/2072) refactor(v2): stronger typing for blog plugin ([@endiliey](https://github.com/endiliey)) -- `docusaurus` - - [#2060](https://github.com/facebook/docusaurus/pull/2060) fix(v2): clean generated manifest from previous build so we dont use the wrong one ([@endiliey](https://github.com/endiliey)) - - [#2033](https://github.com/facebook/docusaurus/pull/2033) refactor(v2): move unused generated files out from build folder ([@endiliey](https://github.com/endiliey)) -- `docusaurus-types`, `docusaurus` - - [#2043](https://github.com/facebook/docusaurus/pull/2043) refactor(v2): stronger typing for route gen ([@endiliey](https://github.com/endiliey)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-ideal-image`, `docusaurus-types`, `docusaurus` - - [#2044](https://github.com/facebook/docusaurus/pull/2044) chore(v2): bump deps ([@endiliey](https://github.com/endiliey)) -- `docusaurus-init`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-docs`, `docusaurus` - - [#2029](https://github.com/facebook/docusaurus/pull/2029) chore(v2): bump deps and remove unused deps ([@endiliey](https://github.com/endiliey)) - -#### :running_woman: Performance - -- `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag` - - [#2070](https://github.com/facebook/docusaurus/pull/2070) perf(v2): more performant gtag and analytics plugin ([@endiliey](https://github.com/endiliey)) -- `docusaurus` - - [#2046](https://github.com/facebook/docusaurus/pull/2046) perf(v2): use webpack future version of asset emitting logic to free memory ([@endiliey](https://github.com/endiliey)) - - [#2039](https://github.com/facebook/docusaurus/pull/2039) perf(v2): replace unnecessary json stringify(string) with inline string ([@endiliey](https://github.com/endiliey)) - - [#2035](https://github.com/facebook/docusaurus/pull/2035) perf(v2): use @babel/runtime plugin to reduce codesize ([@endiliey](https://github.com/endiliey)) -- `docusaurus-plugin-content-docs` - - [#2054](https://github.com/facebook/docusaurus/pull/2054) perf(v2): unblock metadata processing when possible ([@endiliey](https://github.com/endiliey)) - -#### Committers: 5 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Binary Logic ([@binarylogic](https://github.com/binarylogic)) -- Dongwoo Gim ([@gimdongwoo](https://github.com/gimdongwoo)) -- Endi ([@endiliey](https://github.com/endiliey)) -- Wei Gao ([@wgao19](https://github.com/wgao19)) - -## 2.0.0-alpha.36 (2019-11-22) - -#### :boom: Breaking Change - -- `docusaurus-init`, `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` - - [#1989](https://github.com/facebook/docusaurus/pull/1989) misc(v2): change blog front matter to snake_case ([@yangshun](https://github.com/yangshun)) - -#### :rocket: New Feature - -- `docusaurus-plugin-content-docs`, `docusaurus-theme-classic` - - [#2012](https://github.com/facebook/docusaurus/pull/2012) feat(v2): allow hiding docs table of contents ([@yangshun](https://github.com/yangshun)) - -#### :bug: Bug Fix - -- `docusaurus` - - [#2007](https://github.com/facebook/docusaurus/pull/2007) feat(v2): only create one css file to avoid code-split css loading problem ([@endiliey](https://github.com/endiliey)) -- `docusaurus-theme-classic` - - [#2005](https://github.com/facebook/docusaurus/pull/2005) fix(v2): adjust first-level heading offset ([@lex111](https://github.com/lex111)) - -#### :nail_care: Polish - -- `docusaurus-theme-classic` - - [#2013](https://github.com/facebook/docusaurus/pull/2013) refactor(v2): split out dark mode toggle so it is easily swizzle-able ([@endiliey](https://github.com/endiliey)) - - [#2017](https://github.com/facebook/docusaurus/pull/2017) feat(v2): style right sidebar scrollbar when overflow ([@endiliey](https://github.com/endiliey)) - - [#2003](https://github.com/facebook/docusaurus/pull/2003) refactor(v2): improve semantic markup of blog ([@lex111](https://github.com/lex111)) - -#### :house: Internal - -- `docusaurus` - - [#2024](https://github.com/facebook/docusaurus/pull/2024) test(v2): babel exclude transpilation logic to prevent regression ([@endiliey](https://github.com/endiliey)) - - [#2014](https://github.com/facebook/docusaurus/pull/2014) feat(v2): add meta generator docusaurus ([@endiliey](https://github.com/endiliey)) -- `docusaurus-mdx-loader`, `docusaurus-plugin-ideal-image` - - [#2015](https://github.com/facebook/docusaurus/pull/2015) chore(v2): bump & remove unused deps ([@endiliey](https://github.com/endiliey)) -- Other - - [#2009](https://github.com/facebook/docusaurus/pull/2009) misc(v2): branding update ([@yangshun](https://github.com/yangshun)) - -#### :memo: Documentation - -- [#2010](https://github.com/facebook/docusaurus/pull/2010) docs(v2): misc updates ([@yangshun](https://github.com/yangshun)) - -#### Committers: 3 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Endi ([@endiliey](https://github.com/endiliey)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) - -## 2.0.0-alpha.35 (2019-11-17) - -#### :rocket: New Feature - -- `docusaurus-theme-classic` - - [#1965](https://github.com/facebook/docusaurus/pull/1965) feat(v2): add ability specify link in footer logo ([@lex111](https://github.com/lex111)) - -#### :bug: Bug Fix - -- `docusaurus-mdx-loader`, `docusaurus-theme-classic` - - [#1992](https://github.com/facebook/docusaurus/pull/1992) fix(v2): static phrasing content should be rendered correctly in TOC ([@endiliey](https://github.com/endiliey)) -- `docusaurus-theme-classic` - - [#1999](https://github.com/facebook/docusaurus/pull/1999) fix(v2): remove hashbang when click on category ([@lex111](https://github.com/lex111)) - - [#1962](https://github.com/facebook/docusaurus/pull/1962) fix(v2): make not clickable post title on post item page ([@lex111](https://github.com/lex111)) - - [#1980](https://github.com/facebook/docusaurus/pull/1980) fix(v2): remove invalid label attribute of footer links ([@lex111](https://github.com/lex111)) - - [#1978](https://github.com/facebook/docusaurus/pull/1978) fix(v2): use regular div instead of main tag for wrapper layout page ([@lex111](https://github.com/lex111)) - - [#1975](https://github.com/facebook/docusaurus/pull/1975) fix(v2): move header inside article tag in doc page ([@lex111](https://github.com/lex111)) - - [#1974](https://github.com/facebook/docusaurus/pull/1974) fix(v2): remove invalid attributes of nav links ([@lex111](https://github.com/lex111)) - - [#1963](https://github.com/facebook/docusaurus/pull/1963) fix(v2): remove empty containers when no data in blog pages ([@lex111](https://github.com/lex111)) - - [#1966](https://github.com/facebook/docusaurus/pull/1966) fix(v2): remove duplicate meta tags ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs` - - [#1994](https://github.com/facebook/docusaurus/pull/1994) fix(v2): throw error if first level item of a sidebar is not category ([@endiliey](https://github.com/endiliey)) - -#### :nail_care: Polish - -- `docusaurus-theme-search-algolia` - - [#2001](https://github.com/facebook/docusaurus/pull/2001) fix(v2): improve UI of search ([@lex111](https://github.com/lex111)) -- `docusaurus-theme-classic` - - [#1991](https://github.com/facebook/docusaurus/pull/1991) fix(v2): remove accessible anchors via keyboard ([@lex111](https://github.com/lex111)) - - [#1987](https://github.com/facebook/docusaurus/pull/1987) refactor(v2): replace h1 tag with h2 in blog list pages ([@lex111](https://github.com/lex111)) - - [#1981](https://github.com/facebook/docusaurus/pull/1981) fix(v2): use tag time for showing last update of doc item ([@lex111](https://github.com/lex111)) - - [#1977](https://github.com/facebook/docusaurus/pull/1977) feat(v2): add aria-label to read more links for a11y ([@lex111](https://github.com/lex111)) - - [#1964](https://github.com/facebook/docusaurus/pull/1964) fix(v2): use tag time for showing post item date ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-docs` - - [#1994](https://github.com/facebook/docusaurus/pull/1994) fix(v2): throw error if first level item of a sidebar is not category ([@endiliey](https://github.com/endiliey)) -- Other - - [#1986](https://github.com/facebook/docusaurus/pull/1986) fix(v2): remove obsolete iframe attributes ([@lex111](https://github.com/lex111)) -- `docusaurus-init` - - [#1982](https://github.com/facebook/docusaurus/pull/1982) feat(v2): add FB link to footer ([@lex111](https://github.com/lex111)) -- `docusaurus-plugin-content-blog` - - [#1968](https://github.com/facebook/docusaurus/pull/1968) refactor(v2): simplify blog truncate function ([@endiliey](https://github.com/endiliey)) - -#### :memo: Documentation - -- Other - - [#1988](https://github.com/facebook/docusaurus/pull/1988) docs(v2): fix syntax highlighting for YML code blocks ([@lex111](https://github.com/lex111)) - - [#1976](https://github.com/facebook/docusaurus/pull/1976) docs(v2): Add section to blog document about feed location ([@vinnytheviking](https://github.com/vinnytheviking)) - - [#1970](https://github.com/facebook/docusaurus/pull/1970) docs(v2): update configureWebpack utility functions ([@jamiedavenport](https://github.com/jamiedavenport)) -- `docusaurus-1.x` - - [#1961](https://github.com/facebook/docusaurus/pull/1961) docs(v1): remove exclusive language ([@ericcarboni](https://github.com/ericcarboni)) - -#### :house: Internal - -- Other - - [#2002](https://github.com/facebook/docusaurus/pull/2002) fix(v2): fix browser window menu icon on smaller screen ([@lex111](https://github.com/lex111)) - - [#1986](https://github.com/facebook/docusaurus/pull/1986) fix(v2): remove obsolete iframe attributes ([@lex111](https://github.com/lex111)) -- `docusaurus-init` - - [#1982](https://github.com/facebook/docusaurus/pull/1982) feat(v2): add FB link to footer ([@lex111](https://github.com/lex111)) -- `docusaurus-1.x`, `docusaurus-init-1.x`, `docusaurus-init`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-ideal-image`, `docusaurus-types`, `docusaurus` - - [#1985](https://github.com/facebook/docusaurus/pull/1985) chore(v2): update dependencies ([@endiliey](https://github.com/endiliey)) - -#### :running_woman: Performance - -- `docusaurus` - - [#1979](https://github.com/facebook/docusaurus/pull/1979) perf(v2): reduce main bundle size by using es5 if possible ([@endiliey](https://github.com/endiliey)) - -#### Committers: 6 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Endi ([@endiliey](https://github.com/endiliey)) -- Eric Carboni ([@ericcarboni](https://github.com/ericcarboni)) -- Jamie Davenport ([@jamiedavenport](https://github.com/jamiedavenport)) -- Nick McCormick ([@kenning](https://github.com/kenning)) -- Vincent van der Walt ([@vinnytheviking](https://github.com/vinnytheviking)) - -## 2.0.0-alpha.34 (2019-11-11) - -#### :rocket: New Feature - -- `docusaurus-theme-classic` - - [#1956](https://github.com/facebook/docusaurus/pull/1956) feat(v2): add ability hide dark mode toggle ([@lex111](https://github.com/lex111)) - -#### :boom: Breaking Change - -- `docusaurus-plugin-content-docs` - - [#1958](https://github.com/facebook/docusaurus/pull/1958) breaking(v2): editUrl should point to website instead of docsDir ([@endiliey](https://github.com/endiliey)) - -#### :bug: Bug Fix - -- `docusaurus-theme-classic` - - [#1959](https://github.com/facebook/docusaurus/pull/1959) fix(v2): useTOC hooks should not be called in each nested children ([@endiliey](https://github.com/endiliey)) - -#### :nail_care: Polish - -- `docusaurus-plugin-content-docs`, `docusaurus` - - [#1957](https://github.com/facebook/docusaurus/pull/1957) refactor(v2): avoid synchronous/ blocking operation when possible ([@endiliey](https://github.com/endiliey)) - -#### :memo: Documentation - -- [#1953](https://github.com/facebook/docusaurus/pull/1953) fix(v2): update Infima website URL ([@yangshun](https://github.com/yangshun)) - -#### :house: Internal - -- `docusaurus-1.x`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` - - [#1955](https://github.com/facebook/docusaurus/pull/1955) chore: bump dev dependencies ([@endiliey](https://github.com/endiliey)) -- Other - - [#1952](https://github.com/facebook/docusaurus/pull/1952) chore(v2): add lerna-changelog ([@endiliey](https://github.com/endiliey)) - -#### :running_woman: Performance - -- `docusaurus-plugin-content-docs`, `docusaurus-utils`, `docusaurus` - - [#1951](https://github.com/facebook/docusaurus/pull/1951) perf(v2): skip runtime fileHash cache in prod & get timestamp asynchronously ([@endiliey](https://github.com/endiliey)) - - [#1950](https://github.com/facebook/docusaurus/pull/1950) perf(v2): more efficient hot reload & consistent filegen ([@endiliey](https://github.com/endiliey)) - -#### Committers: 3 - -- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) -- Endi ([@endiliey](https://github.com/endiliey)) -- Yangshun Tay ([@yangshun](https://github.com/yangshun)) - -## 2.0.0-alpha.33 (2019-11-08) - -#### Features - -- Table of contents is now highlighted depending on current active headings. (thanks to awesome @SantiagoGdaR) [#1896](https://github.com/facebook/docusaurus/pull/1896) -- Official blog plugin can now generate feed for blog posts. (thanks to awesome @moozzyk) [#1916](https://github.com/facebook/docusaurus/pull/1916) -- **BREAKING** `prismTheme` is renamed to `theme` as part new `prism` object in `themeConfig` field in your `docusaurus.config.js`. Eg: - ```diff - themeConfig: { - - prismTheme: require('prism-react-renderer/themes/dracula'), - + prism: { - + theme: require('prism-react-renderer/themes/dracula'), - + }, - }, - ``` -- Added new `prism` option `defaultLanguage` that is used if the language is not specified in code blocks. [#1910](https://github.com/facebook/docusaurus/pull/1910) - -#### Fixes - -- Fix babel/env not picking the correct browserslist configuration during development. When running `docusaurus start`, `process.env.NODE_ENV` is now consistently set to `development`. -- Ensure routes config generation to be more consistent in ordering. Nested routes should be placed last in routes.js. This will allow user to create `src/pages/docs.js` to create custom docs page for `/docs` or even `src/pages/docs/super.js` to create page for `/docs/super/`; -- Fix watcher does not trigger reload on windows. -- Fix build compilation error if exists only one code tab. -- Add minor padding to docs container so that hash-link won't be cut off. - -#### Others - -- Misc dependency upgrades. -- Stability improvement (more tests) & refactoring on docs plugin to prevent regression. - -## 2.0.0-alpha.32 (2019-11-04) - -#### Features - -- Add `` component for client side redirect. Example Usage: - -```js -import React from 'react'; -import {Redirect} from '@docusaurus/router'; - -function Home() { - return ; -} -``` - -- Allow user to add custom HTML to footer items. [#1905](https://github.com/facebook/docusaurus/pull/1905) -- Added code block line highlighting feature (thanks @lex111)! If you have previously swizzled the `CodeBlock` theme component, it is recommended to update your source code to have this feature. ([#1860](https://github.com/facebook/Docusaurus/issues/1860)) - -#### Bug Fixes - -- Fix `@theme/Tabs` component to be able to create tabs with only one item. -- Fix MDX `@theme/Heading` component. If there is no id, it should not create anchor link. -- Fixed a bug in which if `themeConfig.algolia` is not defined, the custom searchbar won't appear. If you've swizzled Algolia `SearchBar` component before, please update your source code otherwise CSS might break. See [#1909](https://github.com/facebook/docusaurus/pull/1909/files) for reference. - -```js -- -+
-``` - -- Slightly adjust search icon position to be more aligned on small width device. ([#1893](https://github.com/facebook/Docusaurus/issues/1893)) -- Fix algolia styling bug, previously search suggestion result is sometimes hidden. ([#1915](https://github.com/facebook/Docusaurus/issues/1915)) -- Changed the way we read the `USE_SSH` env variable during deployment to be the same as in v1. -- Fix accessing `docs/` or `/docs/xxxx` that does not match any existing doc page should return 404 (Not found) page, not blank page. ([#1903](https://github.com/facebook/Docusaurus/issues/1903)) -- Prioritize `@docusaurus/core` dependencies/ node_modules over user's node_modules. This fix a bug whereby if user has core-js@3 on its own node_modules but docusaurus depends on core-js@2, we previously encounter `Module not found: core-js/modules/xxxx` (because core-js@3 doesn't have that). -- Fix a bug where docs plugin add `/docs` route even if docs folder is empty. We also improved docs plugin test coverage to 100% for stability before working on docs versioning. ([#1912](https://github.com/facebook/Docusaurus/issues/1912)) - -#### Performance Improvement - -- Reduce memory usage consumption. ([#1900](https://github.com/facebook/Docusaurus/issues/1900)) -- Significantly reduce main bundle size and initial HTML payload on production build. Generated files from webpack is also shorter in name. ([#1898](https://github.com/facebook/Docusaurus/issues/1898)) -- Simplify blog metadata. Previously, accessing `/blog/post-xxx` will request for next and prev blog post metadata too aside from target post metadata. We should only request target post metadata. ([#1908](https://github.com/facebook/Docusaurus/issues/1908)) - -#### Others - -- Convert sitemap plugin to TypeScript. ([#1894](https://github.com/facebook/Docusaurus/issues/1894)) -- Refactor dark mode toggle into a hook. ([#1899](https://github.com/facebook/Docusaurus/issues/1899)) - -## 2.0.0-alpha.31 (2019-10-26) - -- Footer is now sticky/ pinned to the bottom of the viewport in desktop browsers. -- Footer is now also displayed in docs page for consistency. -- Remove empty doc sidebar container if sidebar for a particular doc page does not exist. Otherwise, it will cause an additional empty space. -- Default PostCSS loader now only polyfills stage 3+ features (previously it was stage 2) like Create React App. Stage 2 CSS is considered relatively unstable and subject to change while Stage 3 features will likely become a standard. -- Fix search bar focus bug. When you put the focus on search input, previously the focus will remain although we have clicked to other area outside of the search input. -- New themeConfig option `sidebarCollapsible`. It is on by default. If explicitly set to `false`, all doc items in sidebar is expanded. Otherwise, it will still be a collapsible sidebar. -- Disable adding hashes to the generated class names of CSS modules in dev mode. Generating unique identifiers takes some time, which can be saved since including paths to files in class names is enough to avoid collisions. -- Fix showing sidebar category with empty items. -- Update infima from 0.2.0-alpha.2 to 0.2.0-alpha.3 - - Fix pagination nav and right sidebar color contrast ratio - - Fix sidebar arrow color in dark mode - - Fix footer mobile issue - - Increase sidebar width - - etc - -## 2.0.0-alpha.30 (2019-10-22) - -- Fix babel transpilation include/exclude logic to be more efficient. This also fix a very weird bug `TypeError: Cannot assign to read only property 'exports' of object '#'`.([#1868](https://github.com/facebook/docusaurus/pull/1868)) - -If you are still encountering the error. Please check whether you use `module.exports` for your `.js` file instead of doing `export` (mixing CJS and ES). See https://github.com/webpack/webpack/issues/4039#issuecomment-477779322 and https://github.com/webpack/webpack/issues/4039#issuecomment-273804003 for more context. - -## 2.0.0-alpha.29 (2019-10-21) - -**HOTFIX for 2.0.0-alpha.28**. - -- Fix missing `core-js` dependencies on `@docusaurus/core`. -- Fix wrong `@babel/env` preset configuration that causes build compilation error. -- New UI for webpack compilation progress bar. - -## 2.0.0-alpha.28 (2019-10-21) - -- Further reduce memory usage to avoid heap memory allocation failure. -- Fix `keywords` frontmatter for SEO not working properly. -- Fix `swizzle` command not passing context properly to theme packages. -- Add `extendCli` api for plugins. This will allow plugin to further extend Docusaurus CLI. -- Fix `swizzle` command not being able to swizzle single js file. -- Fix logo URL in footer to be appended with baseUrl automatically. -- Add the option `--no-open` for `start` command. -- Set `@babel/env` useBuiltins to `usage`. This will automatically use browserlist and import polyfills required. -- Modified TerserWebpackPlugin `terserOptions` for better cross-browser compatibility. -- **BREAKING** `withBaseUrl` is renamed to `useBaseUrl` because its a React Hooks. Make sure you import/rename it correctly. Eg: `import useBaseUrl from '@docusaurus/useBaseUrl`; -- Fix potential security vulnerability because we're exposing the directory structure of the host machine. -- Upgrade dependencies. - -## 2.0.0-alpha.27 (2019-10-14) - -- Add `@theme/Tabs` which can be used to implement multi-language code tabs. -- Implement `custom_edit_url` and `hide_title` markdown header for docusaurus v1 feature parity. -- Reduce memory usage and slightly faster production build. -- Misc dependency upgrades. - -## 2.0.0-alpha.26 (2019-10-12) - -- Docs, pages plugin is rewritten in TypeScript -- Docs improvements and tweaks - - Improved metadata which results in smaller bundle size. - - Docs sidebar can now be more than one level deep, theoretically up to infinity - - Collapsible docs sidebar! - - Make doc page title larger - - Add `editUrl` option (URL for editing) to docs plugin. If this field is set, there will be an "Edit this page" link for each doc page. Example: 'https://github.com/facebook/docusaurus/edit/master/docs' - - Add `showLastUpdateTime` and `showLastUpdateAuthor` options to docs plugin to further achieve v1 parity of showing last update data for a particular doc -- Slight tweaks to the Blog components - blog title is larger now -- Code Blocks - - Change default theme from Night Owl to Palenight - - Slight tweaks to playground/preview components -- Add `scripts` and `stylesheets` field to `docusaurus.config.js` -- More documentation... - -## 2.0.0-alpha.25 (2019-10-01) - -- Blog plugin is rewritten in TypeScript and can now support CJK -- Upgrade key direct dependencies such as webpack, mdx and babel to latest -- Do not escape html and body attributes -- For devices with very small viewport width, the searchbar is replaced with a search icon. On tap of the search icon the searchbar is expanded and the text beside the logo is hidden and remains hidden while the search bar is expanded. -- Add `date` frontMatter support for blog plugin -- Add `truncateMarker` option to blog plugin, support string or regex. -- Webpack `optimization.removeAvailableModules` is now disabled for performance gain. See https://github.com/webpack/webpack/releases/tag/v4.38.0 for more context. - -## 2.0.0-alpha.24 (2019-07-24) - -- Remove unused metadata for pages. This minimize number of http request & smaller bundle size. -- Upgrade dependencies of css-loader from 2.x to 3.x. CSS modules localIdentName hash now only use the last 4 characters instead of 8. -- Fix broken markdown linking replacement for mdx files -- Fix potential security vulnerability because we're exposing the directory structure of the host machine. Instead of absolute path, we use relative path from site directory. Resulting in shorter webpack chunk naming and smaller bundle size. -- Use contenthash instead of chunkhash for better long term caching -- Allow user to customize generated heading from MDX. Swizzle `@theme/Heading` - -## 2.0.0-alpha.23 (2019-07-21) - -- Fix docusaurus route config generation for certain edge case - -## 2.0.0-alpha.22 (2019-07-20) - -- Add missing dependencies on `@docusaurus/preset-classic` -- New plugin `@docusaurus/plugin-ideal-image` to generate an almost ideal image (responsive, lazy-loading, and low quality placeholder) -- Better Twitter/discord image preview. Previously the size is too zoomed -- Allow prism syntax highlighting theme customization. Refer to https://docusaurus.io/docs/markdown-features#syntax-highlighting -- CSS is now autoprefixed using postcss -- Faster, lighter webpack bundle size -- `@docusaurus/theme-live-codeblock` is now much smaller in size and no longer only load on viewport -- Blog markdown files now support using the id field to specify the path - -## 2.0.0-alpha.21 (2019-07-14) - -- Fix babel-loader not transpiling docusaurus package - -## 2.0.0-alpha.20 (2019-07-14) - -- Add copy codeblock button -- Add Google analytics and Google gtag plugins. -- Move source components to `/src`. Please create a `website/src` directory and move your `/pages` and `/theme` code into it. This is to make it easier to integrate your website with external build/static analysis tooling (you can now just pass in `src/**/*.js` as the path to process). -- Adde more documentation thanks to @wgao19. -- Deprecate the current docs plugin. The docs plugin as of 2.0.0-alpha.19 is heavily based on V1 specifications and we intend to create a better one that fixes some of the inconsistencies in V1. If you have swizzled any doc components, you will have to update their names. You are highly encourages to not swizzle the legacy doc components until we have completed the new docs plugin. -- Separate v2 init command to new package @docusaurus/init -- Render 404.html page -- Improve SEO -- Clicking on the logo in the mobile sliding navigation will now bring you to the homepage. -- Performance - - Disable webpack output pathinfo. Webpack has the ability to generate path info in the output bundle. However, this puts garbage collection pressure on projects that bundle thousands of modules. Not very useful for our case - - Drop cache-loader in CI and test environment because it has an initial overhead. We always start from scratch in vm instance like CI so cache-loader is useless - - Better splitchunks and babel default webpack config - -## 2.0.0-alpha.19 (2019-06-07) - -- Add a sensible default for browserslist config. -- UI - - Add sun and moon emoji to the dark mode toggle. - - Mobile responsive menu. - - Right table of contents for docs is now sticky. -- Plugins - - Change plugin definitions from classes to functions. Refer to the new plugin docs. - - Implement Clients module API. - - Change format within `docusaurus.config.js` to be like presets. -- Deps - - Infima CSS is now locked down to specific versions and not relying upon the CDN which reads from trunk. - - Update dependencies to latest -- Customize/ Override infima CSS variables by passing options into the classic preset. - -``` -presets: [ - [ - '@docusaurus/preset-classic', - { - theme: { - customCss: require.resolve('./css/custom.css'), - }, - ... - }, - ], -], -``` - -- Allow passing remark and rehype plugins to mdx-loader for docs and blog plugin -- Move themes component of docs and blog to be part of theme-classic -- Use composition style for prism syntax highlighting instead of doing it via rehype plugin -- Pass MDXProvider to docs and blog. To change the provided MDX components, run `docusaurus swizzle @docusaurus/theme-classic MDXComponents` -- Add @docusaurus/theme-livecodeblock plugin -- Better run-time code generation & webpack splitchunks optimization -- Minify css for production build -- Fix weird scrolling problem when navigating to a route with a `hash` location - -## V2 Changelog (2019-04-10) - -### `siteConfig.js` changes - -- `siteConfig.js` renamed to `docusaurus.config.js`. -- Remove the following config options: - - `docsUrl`. Use the plugin option on `docusaurus-plugin-content-docs` instead. - - `customDocsPath`. Use the plugin option on `docusaurus-plugin-content-docs` instead. - - `sidebars.json` now has to be explicitly loaded by users and passed into the plugin option on `docusaurus-plugin-content-docs`. - - `headerLinks` doc, page, blog is deprecated and has been to moved into `themeConfig` under the name `navbar`. The syntax is now: - -```js -themeConfig: { - navbar: { - title: 'Docusaurus', - logo: { - alt: 'Docusaurus Logo', - src: 'img/docusaurus.svg', - }, - links: [ - {to: 'docs/introduction', label: 'Docs', position: 'left'}, - {to: 'blog', label: 'Blog', position: 'left'}, - {to: 'feedback', label: 'Feedback', position: 'left'}, - { - href: 'https://github.com/facebook/docusaurus', - label: 'GitHub', - position: 'right', - }, - ], - }, -} -``` - -### Migration Guide - -_Work in Progress_ - -### Presets - -- Add presets for plugins that follow the [Babel preset convention](https://babeljs.io/docs/en/presets). diff --git a/website/src/plugins/changelog/index.ts b/website/src/plugins/changelog/index.ts index 46f5f08efb..da009a7c2c 100644 --- a/website/src/plugins/changelog/index.ts +++ b/website/src/plugins/changelog/index.ts @@ -8,131 +8,42 @@ import path from 'path'; import fs from 'fs-extra'; import pluginContentBlog from '@docusaurus/plugin-content-blog'; -import {aliasedSitePath, docuHash, normalizeUrl} from '@docusaurus/utils'; +import { + aliasedSitePath, + docuHash, + normalizeUrl, + safeGlobby, +} from '@docusaurus/utils'; +import {createBlogFiles, toChangelogEntries} from './utils'; export {validateOptions} from '@docusaurus/plugin-content-blog'; -/** - * Multiple versions may be published on the same day, causing the order to be - * the reverse. Therefore, our publish time has a "fake hour" to order them. - */ -// TODO may leak small amount of memory in multi-locale builds -const publishTimes = new Set(); +const MonorepoRoot = path.resolve(path.join(__dirname, '../../../..')); -type Author = {name: string; url: string; alias: string; imageURL: string}; +const ChangelogFilePattern = 'CHANGELOG(-v[0-9]*)?.md'; -type AuthorsMap = Record; - -type ChangelogEntry = { - title: string; - content: string; - authors: Author[]; -}; - -function parseAuthor(committerLine: string): Author { - const groups = committerLine.match( - /- (?:(?.*?) \()?\[@(?.*)\]\((?.*?)\)\)?/, - )!.groups as {name: string; alias: string; url: string}; - - return { - ...groups, - name: groups.name ?? groups.alias, - imageURL: `https://github.com/${groups.alias}.png`, - }; -} - -function parseAuthors(content: string): Author[] { - const committersContent = content.match(/## Committers: \d.*/s)?.[0]; - if (!committersContent) { - return []; - } - const committersLines = committersContent.match(/- .*/g)!; - - const authors = committersLines - .map(parseAuthor) - .sort((a, b) => a.url.localeCompare(b.url)); - - return authors; -} - -function createAuthorsMap(changelogEntries: ChangelogEntry[]): AuthorsMap { - const allAuthors = changelogEntries.flatMap((entry) => entry.authors); - const authorsMap: AuthorsMap = {}; - allAuthors?.forEach((author) => { - authorsMap[author.alias] = author; +async function getChangelogFiles() { + const files = await safeGlobby([ChangelogFilePattern], { + cwd: MonorepoRoot, }); - return authorsMap; -} - -function toChangelogEntry(sectionContent: string): ChangelogEntry | null { - const title = sectionContent - .match(/\n## .*/)?.[0] - .trim() - .replace('## ', ''); - if (!title) { - return null; + // As of today, there are 2 changelog files + // and this is only going to increase + if (files.length < 2) { + throw new Error( + "Looks like the changelog plugin didn't detect Docusaurus changelog files", + ); } - const content = sectionContent - .replace(/\n## .*/, '') - .trim() - .replace('running_woman', 'running'); - - const authors = parseAuthors(content); - - let hour = 20; - const date = title.match(/ \((?.*)\)/)?.groups!.date; - while (publishTimes.has(`${date}T${hour}:00`)) { - hour -= 1; - } - publishTimes.add(`${date}T${hour}:00`); - - return { - authors, - title: title.replace(/ \(.*\)/, ''), - content: `--- -mdx: - format: md -date: ${`${date}T${hour}:00`}${ - authors.length > 0 - ? ` -authors: -${authors.map((author) => ` - '${author.alias}'`).join('\n')}` - : '' - } ---- - -# ${title.replace(/ \(.*\)/, '')} - - - -${content.replace(/####/g, '##')}`, - }; + // Note: the returned file order doesn't matter. + return files; } -function toChangelogEntries(fileContent: string): ChangelogEntry[] { - return fileContent - .split(/(?=\n## )/) - .map(toChangelogEntry) - .filter((s): s is ChangelogEntry => s !== null); +function readChangelogFile(filename: string) { + return fs.readFile(path.join(MonorepoRoot, filename), 'utf-8'); } -async function createBlogFiles( - generateDir: string, - changelogEntries: ChangelogEntry[], -) { - await Promise.all( - changelogEntries.map((changelogEntry) => - fs.outputFile( - path.join(generateDir, `${changelogEntry.title}.md`), - changelogEntry.content, - ), - ), - ); - - await fs.outputFile( - path.join(generateDir, 'authors.json'), - JSON.stringify(createAuthorsMap(changelogEntries), null, 2), - ); +async function loadChangelogEntries(changelogFiles: string[]) { + const filesContent = await Promise.all(changelogFiles.map(readChangelogFile)); + return toChangelogEntries(filesContent); } const ChangelogPlugin: typeof pluginContentBlog = @@ -145,14 +56,14 @@ const ChangelogPlugin: typeof pluginContentBlog = blogListComponent: '@theme/ChangelogList', blogPostComponent: '@theme/ChangelogPage', }); - const changelogPath = path.join(__dirname, '../../../../CHANGELOG.md'); + const changelogFiles = await getChangelogFiles(); + return { ...blogPlugin, name: 'changelog-plugin', async loadContent() { - const fileContent = await fs.readFile(changelogPath, 'utf-8'); - const changelogEntries = toChangelogEntries(fileContent); + const changelogEntries = await loadChangelogEntries(changelogFiles); // We have to create intermediate files here // Unfortunately Docusaurus doesn't have yet any concept of virtual file @@ -199,8 +110,7 @@ const ChangelogPlugin: typeof pluginContentBlog = }, getPathsToWatch() { - // Don't watch the generated dir - return [changelogPath]; + return [path.join(MonorepoRoot, ChangelogFilePattern)]; }, }; }; diff --git a/website/src/plugins/changelog/utils.ts b/website/src/plugins/changelog/utils.ts new file mode 100644 index 0000000000..c6b54cdea4 --- /dev/null +++ b/website/src/plugins/changelog/utils.ts @@ -0,0 +1,134 @@ +/** + * 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 fs from 'fs-extra'; +import path from 'path'; + +/** + * Multiple versions may be published on the same day, causing the order to be + * the reverse. Therefore, our publish time has a "fake hour" to order them. + */ +// TODO may leak small amount of memory in multi-locale builds +const publishTimes = new Set(); + +type Author = {name: string; url: string; alias: string; imageURL: string}; + +type AuthorsMap = Record; + +type ChangelogEntry = { + title: string; + content: string; + authors: Author[]; +}; + +function parseAuthor(committerLine: string): Author { + const groups = committerLine.match( + /- (?:(?.*?) \()?\[@(?.*)\]\((?.*?)\)\)?/, + )!.groups as {name: string; alias: string; url: string}; + + return { + ...groups, + name: groups.name ?? groups.alias, + imageURL: `https://github.com/${groups.alias}.png`, + }; +} + +function parseAuthors(content: string): Author[] { + const committersContent = content.match(/## Committers: \d.*/s)?.[0]; + if (!committersContent) { + return []; + } + const committersLines = committersContent.match(/- .*/g)!; + + const authors = committersLines + .map(parseAuthor) + .sort((a, b) => a.url.localeCompare(b.url)); + + return authors; +} + +export function createAuthorsMap( + changelogEntries: ChangelogEntry[], +): AuthorsMap { + const allAuthors = changelogEntries.flatMap((entry) => entry.authors); + const authorsMap: AuthorsMap = {}; + allAuthors?.forEach((author) => { + authorsMap[author.alias] = author; + }); + return authorsMap; +} + +function toChangelogEntry(sectionContent: string): ChangelogEntry | null { + const title = sectionContent + .match(/\n## .*/)?.[0] + .trim() + .replace('## ', ''); + if (!title) { + return null; + } + const content = sectionContent + .replace(/\n## .*/, '') + .trim() + .replace('running_woman', 'running'); + + const authors = parseAuthors(content); + + let hour = 20; + const date = title.match(/ \((?.*)\)/)?.groups!.date; + while (publishTimes.has(`${date}T${hour}:00`)) { + hour -= 1; + } + publishTimes.add(`${date}T${hour}:00`); + + return { + authors, + title: title.replace(/ \(.*\)/, ''), + content: `--- +mdx: + format: md +date: ${`${date}T${hour}:00`}${ + authors.length > 0 + ? ` +authors: +${authors.map((author) => ` - '${author.alias}'`).join('\n')}` + : '' + } +--- + +# ${title.replace(/ \(.*\)/, '')} + + + +${content.replace(/####/g, '##')}`, + }; +} + +export function toChangelogEntries(filesContent: string[]): ChangelogEntry[] { + return filesContent + .flatMap((content) => content.split(/(?=\n## )/)) + .map(toChangelogEntry) + .filter((s): s is ChangelogEntry => s !== null); +} + +export async function createBlogFiles( + generateDir: string, + changelogEntries: ChangelogEntry[], +): Promise { + await Promise.all( + changelogEntries.map((changelogEntry) => + fs.outputFile( + path.join(generateDir, `${changelogEntry.title}.md`), + changelogEntry.content, + ), + ), + ); + + await fs.outputFile( + path.join(generateDir, 'authors.json'), + JSON.stringify(createAuthorsMap(changelogEntries), null, 2), + ); +} From 1592094206794de85c1b93adc03c4437b3b7acaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Wed, 25 Jun 2025 11:11:38 +0200 Subject: [PATCH 024/103] fix(theme): Fix footnote ref scrolling behind the navbar when footnote back reference clicked (#11289) --- .../src/theme-classic.d.ts | 4 +- .../src/theme/MDXComponents/A.tsx | 14 ------- .../src/theme/MDXComponents/A/index.tsx | 42 +++++++++++++++++++ .../theme/MDXComponents/A/styles.module.css | 20 +++++++++ 4 files changed, 65 insertions(+), 15 deletions(-) delete mode 100644 packages/docusaurus-theme-classic/src/theme/MDXComponents/A.tsx create mode 100644 packages/docusaurus-theme-classic/src/theme/MDXComponents/A/index.tsx create mode 100644 packages/docusaurus-theme-classic/src/theme/MDXComponents/A/styles.module.css diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index a23b1bd8aa..c801c97e79 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -1040,7 +1040,9 @@ declare module '@theme/SkipToContent' { declare module '@theme/MDXComponents/A' { import type {ComponentProps, ReactNode} from 'react'; - export interface Props extends ComponentProps<'a'> {} + export interface Props extends ComponentProps<'a'> { + 'data-footnote-ref'?: true; + } export default function MDXA(props: Props): ReactNode; } diff --git a/packages/docusaurus-theme-classic/src/theme/MDXComponents/A.tsx b/packages/docusaurus-theme-classic/src/theme/MDXComponents/A.tsx deleted file mode 100644 index 75fe616e66..0000000000 --- a/packages/docusaurus-theme-classic/src/theme/MDXComponents/A.tsx +++ /dev/null @@ -1,14 +0,0 @@ -/** - * 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, {type ReactNode} from 'react'; -import Link from '@docusaurus/Link'; -import type {Props} from '@theme/MDXComponents/A'; - -export default function MDXA(props: Props): ReactNode { - return ; -} diff --git a/packages/docusaurus-theme-classic/src/theme/MDXComponents/A/index.tsx b/packages/docusaurus-theme-classic/src/theme/MDXComponents/A/index.tsx new file mode 100644 index 0000000000..21e4dac8bd --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/MDXComponents/A/index.tsx @@ -0,0 +1,42 @@ +/** + * 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, {type ReactNode} from 'react'; +import clsx from 'clsx'; +import Link from '@docusaurus/Link'; +import {useThemeConfig} from '@docusaurus/theme-common'; +import type {Props} from '@theme/MDXComponents/A'; +import styles from './styles.module.css'; + +function isFootnoteRef(props: Props) { + return props['data-footnote-ref'] === true; +} + +function FootnoteRefLink(props: Props) { + const { + navbar: {hideOnScroll}, + } = useThemeConfig(); + return ( + + ); +} + +export default function MDXA(props: Props): ReactNode { + if (isFootnoteRef(props)) { + return ; + } + return ; +} diff --git a/packages/docusaurus-theme-classic/src/theme/MDXComponents/A/styles.module.css b/packages/docusaurus-theme-classic/src/theme/MDXComponents/A/styles.module.css new file mode 100644 index 0000000000..295757363a --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/MDXComponents/A/styles.module.css @@ -0,0 +1,20 @@ +/** + * 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. + */ + +/* +When the navbar is sticky, ensure that on footnote click, +the browser does not scroll to the ref behind the navbar +See https://github.com/facebook/docusaurus/issues/11232 +See also headings case https://x.com/JoshWComeau/status/1332015868725891076 + */ +.footnoteRefStickyNavbar { + scroll-margin-top: calc(var(--ifm-navbar-height) + 0.5rem); +} + +.footnoteRefHideOnScrollNavbar { + scroll-margin-top: 0.5rem; +} From 385102df9fce96f99e0e487f18b06391b3a5abd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Wed, 25 Jun 2025 15:34:44 +0200 Subject: [PATCH 025/103] chore: upgrade website to Rspack 1.4 + fix Rspack internal performance tracing (#11290) --- .gitignore | 1 + package.json | 3 + .../docusaurus-bundler/src/currentBundler.ts | 4 +- project-words.txt | 2 + yarn.lock | 232 +++++++++++------- 5 files changed, 147 insertions(+), 95 deletions(-) diff --git a/.gitignore b/.gitignore index 5776519d88..9d136d1c17 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,7 @@ website/i18n/**/* .netlify website/rspack-tracing.json +website/rspack-tracing.pftrace website/bundler-cpu-profile.json website/profile.json.gz diff --git a/package.json b/package.json index 0e9d63abf9..757120cb54 100644 --- a/package.json +++ b/package.json @@ -129,5 +129,8 @@ "stylelint-config-standard": "^29.0.0", "typescript": "~5.8.2" }, + "resolutions": { + "@rspack/core": "1.4.0-rc.0" + }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/packages/docusaurus-bundler/src/currentBundler.ts b/packages/docusaurus-bundler/src/currentBundler.ts index 7d23d82860..d0bf5607e9 100644 --- a/packages/docusaurus-bundler/src/currentBundler.ts +++ b/packages/docusaurus-bundler/src/currentBundler.ts @@ -129,8 +129,8 @@ export async function registerBundlerTracing({ await Rspack.experiments.globalTrace.register( filter, - 'chrome', - './rspack-tracing.json', + 'perfetto', + './rspack-tracing.pftrace', ); console.info(`Rspack tracing registered, filter=${filter}`); diff --git a/project-words.txt b/project-words.txt index 48a0ac9321..467a8d0a2d 100644 --- a/project-words.txt +++ b/project-words.txt @@ -215,6 +215,8 @@ Paraiso paraiso pathinfo paularmstrong +perfetto +pftrace philpl Pipeable playbtn diff --git a/yarn.lock b/yarn.lock index 76c94272a1..a1684cb125 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2062,6 +2062,28 @@ dependencies: loader-utils "^2.0.0" +"@emnapi/core@^1.4.3": + version "1.4.3" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.3.tgz#9ac52d2d5aea958f67e52c40a065f51de59b77d6" + integrity sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g== + dependencies: + "@emnapi/wasi-threads" "1.0.2" + tslib "^2.4.0" + +"@emnapi/runtime@^1.4.3": + version "1.4.3" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.3.tgz#c0564665c80dc81c448adac23f9dfbed6c838f7d" + integrity sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ== + dependencies: + tslib "^2.4.0" + +"@emnapi/wasi-threads@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz#977f44f844eac7d6c138a415a123818c655f874c" + integrity sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA== + dependencies: + tslib "^2.4.0" + "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -2576,48 +2598,57 @@ dependencies: langium "3.3.1" -"@module-federation/error-codes@0.14.3": - version "0.14.3" - resolved "https://registry.yarnpkg.com/@module-federation/error-codes/-/error-codes-0.14.3.tgz#e6b5c380240f5650bcf67a1906b22271b891d2c5" - integrity sha512-sBJ3XKU9g5Up31jFeXPFsD8AgORV7TLO/cCSMuRewSfgYbG/3vSKLJmfHrO6+PvjZSb9VyV2UaF02ojktW65vw== +"@module-federation/error-codes@0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@module-federation/error-codes/-/error-codes-0.15.0.tgz#1e3ae45186a4034d806875cc61dd721b3826f462" + integrity sha512-CFJSF+XKwTcy0PFZ2l/fSUpR4z247+Uwzp1sXVkdIfJ/ATsnqf0Q01f51qqSEA6MYdQi6FKos9FIcu3dCpQNdg== -"@module-federation/runtime-core@0.14.3": - version "0.14.3" - resolved "https://registry.yarnpkg.com/@module-federation/runtime-core/-/runtime-core-0.14.3.tgz#434025c1304278e30bbc024aaeab086d80f9e196" - integrity sha512-xMFQXflLVW/AJTWb4soAFP+LB4XuhE7ryiLIX8oTyUoBBgV6U2OPghnFljPjeXbud72O08NYlQ1qsHw1kN/V8Q== +"@module-federation/runtime-core@0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@module-federation/runtime-core/-/runtime-core-0.15.0.tgz#353113beee4fc50aeb85c1214202214a995ac4b4" + integrity sha512-RYzI61fRDrhyhaEOXH3AgIGlHiot0wPFXu7F43cr+ZnTi+VlSYWLdlZ4NBuT9uV6JSmH54/c+tEZm5SXgKR2sQ== dependencies: - "@module-federation/error-codes" "0.14.3" - "@module-federation/sdk" "0.14.3" + "@module-federation/error-codes" "0.15.0" + "@module-federation/sdk" "0.15.0" -"@module-federation/runtime-tools@0.14.3": - version "0.14.3" - resolved "https://registry.yarnpkg.com/@module-federation/runtime-tools/-/runtime-tools-0.14.3.tgz#fa1414b449cbe5fb6dcbde4ed02c85e0cdcc758b" - integrity sha512-QBETX7iMYXdSa3JtqFlYU+YkpymxETZqyIIRiqg0gW+XGpH3jgU68yjrme2NBJp7URQi/CFZG8KWtfClk0Pjgw== +"@module-federation/runtime-tools@0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@module-federation/runtime-tools/-/runtime-tools-0.15.0.tgz#b84bd87f7722e572438c06f3ce3f244ada287234" + integrity sha512-kzFn3ObUeBp5vaEtN1WMxhTYBuYEErxugu1RzFUERD21X3BZ+b4cWwdFJuBDlsmVjctIg/QSOoZoPXRKAO0foA== dependencies: - "@module-federation/runtime" "0.14.3" - "@module-federation/webpack-bundler-runtime" "0.14.3" + "@module-federation/runtime" "0.15.0" + "@module-federation/webpack-bundler-runtime" "0.15.0" -"@module-federation/runtime@0.14.3": - version "0.14.3" - resolved "https://registry.yarnpkg.com/@module-federation/runtime/-/runtime-0.14.3.tgz#fc9142c093001c67a0fcacaf53d4eb5749e9bbd6" - integrity sha512-7ZHpa3teUDVhraYdxQGkfGHzPbjna4LtwbpudgzAxSLLFxLDNanaxCuSeIgSM9c+8sVUNC9kvzUgJEZB0krPJw== +"@module-federation/runtime@0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@module-federation/runtime/-/runtime-0.15.0.tgz#8ea3fd190211f78e95f5a7b32f0ed3a428c2ea91" + integrity sha512-dTPsCNum9Bhu3yPOcrPYq0YnM9eCMMMNB1wuiqf1+sFbQlNApF0vfZxooqz3ln0/MpgE0jerVvFsLVGfqvC9Ug== dependencies: - "@module-federation/error-codes" "0.14.3" - "@module-federation/runtime-core" "0.14.3" - "@module-federation/sdk" "0.14.3" + "@module-federation/error-codes" "0.15.0" + "@module-federation/runtime-core" "0.15.0" + "@module-federation/sdk" "0.15.0" -"@module-federation/sdk@0.14.3": - version "0.14.3" - resolved "https://registry.yarnpkg.com/@module-federation/sdk/-/sdk-0.14.3.tgz#a03e37f1cb018283542cfc66a87e7a37e39cfe1a" - integrity sha512-THJZMfbXpqjQOLblCQ8jjcBFFXsGRJwUWE9l/Q4SmuCSKMgAwie7yLT0qSGrHmyBYrsUjAuy+xNB4nfKP0pnGw== +"@module-federation/sdk@0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@module-federation/sdk/-/sdk-0.15.0.tgz#31e0b1e443e9e5761345e298ba5e49eab273e51d" + integrity sha512-PWiYbGcJrKUD6JZiEPihrXhV3bgXdll4bV7rU+opV7tHaun+Z0CdcawjZ82Xnpb8MCPGmqHwa1MPFeUs66zksw== -"@module-federation/webpack-bundler-runtime@0.14.3": - version "0.14.3" - resolved "https://registry.yarnpkg.com/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.14.3.tgz#2d6bf63e93f626a2f5e469bc57fb5bcc098fee37" - integrity sha512-hIyJFu34P7bY2NeMIUHAS/mYUHEY71VTAsN0A0AqEJFSVPszheopu9VdXq0VDLrP9KQfuXT8SDxeYeJXyj0mgA== +"@module-federation/webpack-bundler-runtime@0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.15.0.tgz#50d8d863e310f53829e4c5cf8bd41ef94e682ff1" + integrity sha512-i+3wu2Ljh2TmuUpsnjwZVupOVqV50jP0ndA8PSP4gwMKlgdGeaZ4VH5KkHAXGr2eiYUxYLMrJXz1+eILJqeGDg== dependencies: - "@module-federation/runtime" "0.14.3" - "@module-federation/sdk" "0.14.3" + "@module-federation/runtime" "0.15.0" + "@module-federation/sdk" "0.15.0" + +"@napi-rs/wasm-runtime@^0.2.11": + version "0.2.11" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz#192c1610e1625048089ab4e35bc0649ce478500e" + integrity sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA== + dependencies: + "@emnapi/core" "^1.4.3" + "@emnapi/runtime" "^1.4.3" + "@tybys/wasm-util" "^0.9.0" "@netlify/functions@^1.6.0": version "1.6.0" @@ -3273,73 +3304,81 @@ fs-extra "^11.1.1" lodash "^4.17.21" -"@rspack/binding-darwin-arm64@1.3.15": - version "1.3.15" - resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.3.15.tgz#8deb8845dbb6285e40dd329b9ad13fcbaf6be8f4" - integrity sha512-f+DnVRENRdVe+ufpZeqTtWAUDSTnP48jVo7x9KWsXf8XyJHUi+eHKEPrFoy1HvL1/k5yJ3HVnFBh1Hb9cNIwSg== +"@rspack/binding-darwin-arm64@1.4.0-rc.0": + version "1.4.0-rc.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.4.0-rc.0.tgz#f594417f088dd71c3524df42ee60b5ce89276f9e" + integrity sha512-4fJ577AVWSHHsY+FEozxhYpnSGZmIneusFhIpbkf7l3x8hh5SdL6hE2y3lNeE9BHgjHPfdMJogoz/VNYcTWG/A== -"@rspack/binding-darwin-x64@1.3.15": - version "1.3.15" - resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.3.15.tgz#a7dc05a5d278c2c1fd920987afb0b839311bff89" - integrity sha512-TfUvEIBqYUT2OK01BYXb2MNcZeZIhAnJy/5aj0qV0uy4KlvwW63HYcKWa1sFd4Ac7bnGShDkanvP3YEuHOFOyg== +"@rspack/binding-darwin-x64@1.4.0-rc.0": + version "1.4.0-rc.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.4.0-rc.0.tgz#c8e3cbca13019985d3002ac3695b4318d7cab8c2" + integrity sha512-6r4l/2VhPuHrQrDYazQl4GNTSPvPPXEZwee2fYVO6YeWiPPJFNAUyIT0DjXtAMuJ2zDBOH0DkJ6dqkLf9/kn8Q== -"@rspack/binding-linux-arm64-gnu@1.3.15": - version "1.3.15" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.3.15.tgz#31a29d4aac66fd92232bccbb2be0273362e1d6f2" - integrity sha512-D/YjYk9snKvYm1Elotq8/GsEipB4ZJWVv/V8cZ+ohhFNOPzygENi6JfyI06TryBTQiN0/JDZqt/S9RaWBWnMqw== +"@rspack/binding-linux-arm64-gnu@1.4.0-rc.0": + version "1.4.0-rc.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.4.0-rc.0.tgz#f2d11e5a811e5edcc7d315b91d88b2938b635d4a" + integrity sha512-K6VLea9StRkOltXqyxNzKeNR3cAFsOpHoNDc8lg0zZNAr1Rn1f+8THqFlWfDV1djXvhM/LsBM+rG97yQFYh/zg== -"@rspack/binding-linux-arm64-musl@1.3.15": - version "1.3.15" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.3.15.tgz#f8bdc956f6ef644b1c469d20ecc3849415f3e71b" - integrity sha512-lJbBsPMOiR0hYPCSM42yp7QiZjfo0ALtX7ws2wURpsQp3BMfRVAmXU3Ixpo2XCRtG1zj8crHaCmAWOJTS0smsA== +"@rspack/binding-linux-arm64-musl@1.4.0-rc.0": + version "1.4.0-rc.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.4.0-rc.0.tgz#bb778478e0470ffef8a6c671f383de5b5566ad98" + integrity sha512-/xAgd0ObvI9ggJWMHDI8WHFCeuqi7gMnzdeN8QWO82dzlwO/0rgBqQkULS1hUDlV47Hh03BwjUz9sbuXCnelqg== -"@rspack/binding-linux-x64-gnu@1.3.15": - version "1.3.15" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.3.15.tgz#5dd39fd59eb5d3f8e353110f3ed40e00242c73f8" - integrity sha512-qGB8ucHklrzNg6lsAS36VrBsCbOw0acgpQNqTE5cuHWrp1Pu3GFTRiFEogenxEmzoRbohMZt0Ev5grivrcgKBQ== +"@rspack/binding-linux-x64-gnu@1.4.0-rc.0": + version "1.4.0-rc.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.4.0-rc.0.tgz#903ff50274557c9abb5f632128c5d76ae07495f8" + integrity sha512-2u6ytaatpksqUfEn16M/8ppkYaurQpPgZ7cCy3iFpVi6w+7loXWz0X+xklsuBH8H0ie4CZkLmiJIhkW2hFn8KA== -"@rspack/binding-linux-x64-musl@1.3.15": - version "1.3.15" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.3.15.tgz#32c2bb197568cca841a26ecea019590bc0e2ce56" - integrity sha512-qRn6e40fLQP+N2rQD8GAj/h4DakeTIho32VxTIaHRVuzw68ZD7VmKkwn55ssN370ejmey35ZdoNFNE12RBrMZA== +"@rspack/binding-linux-x64-musl@1.4.0-rc.0": + version "1.4.0-rc.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.4.0-rc.0.tgz#17a1b03d62980c61a22dc25d34254251e636bbb7" + integrity sha512-ilSb6GDz/0A+qlnPFZJuw9DtFH/ENf09f7raXxye3faZw/GH8aJ9H3X8VNeMR1QrYwFFk8LLB402EtZHETyz7Q== -"@rspack/binding-win32-arm64-msvc@1.3.15": - version "1.3.15" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.3.15.tgz#75c1b04d2ea08b49f480825ad57d8ca82acaf6d9" - integrity sha512-7uJ7dWhO1nWXJiCss6Rslz8hoAxAhFpwpbWja3eHgRb7O4NPHg6MWw63AQSI2aFVakreenfu9yXQqYfpVWJ2dA== - -"@rspack/binding-win32-ia32-msvc@1.3.15": - version "1.3.15" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.3.15.tgz#56093d8818d68cd270ba63bddffd38dbd50957f7" - integrity sha512-UsaWTYCjDiSCB0A0qETgZk4QvhwfG8gCrO4SJvA+QSEWOmgSai1YV70prFtLLIiyT9mDt1eU3tPWl1UWPRU/EQ== - -"@rspack/binding-win32-x64-msvc@1.3.15": - version "1.3.15" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.3.15.tgz#eb404ff76ea9da045173e6efccc6b7f276fd6960" - integrity sha512-ZnDIc9Es8EF94MirPDN+hOMt7tkb8nMEbRJFKLMmNd0ElNPgsql+1cY5SqyGRH1hsKB87KfSUQlhFiKZvzbfIg== - -"@rspack/binding@1.3.15": - version "1.3.15" - resolved "https://registry.yarnpkg.com/@rspack/binding/-/binding-1.3.15.tgz#535fa1f14d173fb72a2d8bb7df10906827e77185" - integrity sha512-utNPuJglLO5lW9XbwIqjB7+2ilMo6JkuVLTVdnNVKU94FW7asn9F/qV+d+MgjUVqU1QPCGm0NuGO9xhbgeJ7pg== - optionalDependencies: - "@rspack/binding-darwin-arm64" "1.3.15" - "@rspack/binding-darwin-x64" "1.3.15" - "@rspack/binding-linux-arm64-gnu" "1.3.15" - "@rspack/binding-linux-arm64-musl" "1.3.15" - "@rspack/binding-linux-x64-gnu" "1.3.15" - "@rspack/binding-linux-x64-musl" "1.3.15" - "@rspack/binding-win32-arm64-msvc" "1.3.15" - "@rspack/binding-win32-ia32-msvc" "1.3.15" - "@rspack/binding-win32-x64-msvc" "1.3.15" - -"@rspack/core@^1.3.15": - version "1.3.15" - resolved "https://registry.yarnpkg.com/@rspack/core/-/core-1.3.15.tgz#22bce959aa386c3f38021af6ee6a94339896ffd2" - integrity sha512-QuElIC8jXSKWAp0LSx18pmbhA7NiA5HGoVYesmai90UVxz98tud0KpMxTVCg+0lrLrnKZfCWN9kwjCxM5pGnrA== +"@rspack/binding-wasm32-wasi@1.4.0-rc.0": + version "1.4.0-rc.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.4.0-rc.0.tgz#1cef3b3b8831e1cb453665fa1b0094376e76d8e9" + integrity sha512-NsnAfBrQDlZTgudxG2YNgnOsZgaE4Vqm1pM0OXWd6NOhSGwGQ6T/rka99dHiUTxxAb6AOqI/avVn1NYsPHsqIQ== dependencies: - "@module-federation/runtime-tools" "0.14.3" - "@rspack/binding" "1.3.15" + "@napi-rs/wasm-runtime" "^0.2.11" + +"@rspack/binding-win32-arm64-msvc@1.4.0-rc.0": + version "1.4.0-rc.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.4.0-rc.0.tgz#4269ed6f9dabffd85d2b154bc6b91bba04e55b50" + integrity sha512-dT7FZz0dbWKzb3Ka6OD0TkOhGS/qC2/tWJ98nIxXMFCW2ZcULJhwcnRe95KBEwVDzwHgcTTzVa3fUFuTmcL87w== + +"@rspack/binding-win32-ia32-msvc@1.4.0-rc.0": + version "1.4.0-rc.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.4.0-rc.0.tgz#c3c421e7406c6b49fc9aeec9c5643fe5acb99049" + integrity sha512-0Q8+vWvT6zZPkNqaUvBIfXUSC3ZHsu/2on1bX9bGWLVfG4Or1QWY9vNA3vPX8DsK3XiHwixX+iLo95tmQgasNw== + +"@rspack/binding-win32-x64-msvc@1.4.0-rc.0": + version "1.4.0-rc.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.4.0-rc.0.tgz#c785db3b6c931ec31f689ecc5b974328ea813564" + integrity sha512-bsKJGM6Tu6aqyt6QTDEPL0BCtJ/HWHF3phdCP9XBUcmlSvjIwemekTs/QO/k2ZKXQ93j9Sz8J92WWmNQp0Mp8w== + +"@rspack/binding@1.4.0-rc.0": + version "1.4.0-rc.0" + resolved "https://registry.yarnpkg.com/@rspack/binding/-/binding-1.4.0-rc.0.tgz#3001e857fc4848ab6d1224e87845739df1bed963" + integrity sha512-kBEzks6RymjBLYF84TkUP895yCqqlodHDmBsWKbJGOokNKx+0ohnoWxXws5oZca/j9DSKCdEsA8VyROtqdMujw== + optionalDependencies: + "@rspack/binding-darwin-arm64" "1.4.0-rc.0" + "@rspack/binding-darwin-x64" "1.4.0-rc.0" + "@rspack/binding-linux-arm64-gnu" "1.4.0-rc.0" + "@rspack/binding-linux-arm64-musl" "1.4.0-rc.0" + "@rspack/binding-linux-x64-gnu" "1.4.0-rc.0" + "@rspack/binding-linux-x64-musl" "1.4.0-rc.0" + "@rspack/binding-wasm32-wasi" "1.4.0-rc.0" + "@rspack/binding-win32-arm64-msvc" "1.4.0-rc.0" + "@rspack/binding-win32-ia32-msvc" "1.4.0-rc.0" + "@rspack/binding-win32-x64-msvc" "1.4.0-rc.0" + +"@rspack/core@1.4.0-rc.0", "@rspack/core@^1.3.15": + version "1.4.0-rc.0" + resolved "https://registry.yarnpkg.com/@rspack/core/-/core-1.4.0-rc.0.tgz#1ecb66b34971e20acf552e6e9d38aa063840fee9" + integrity sha512-yO4AP7sgptepks2kNLFvLipdonGv6OKDUIKEl0c7SpbBmPEspd3vsYxE/T5hruFVDnq0GPEePKA1GOjRCKGR8A== + dependencies: + "@module-federation/runtime-tools" "0.15.0" + "@rspack/binding" "1.4.0-rc.0" "@rspack/lite-tapable" "1.0.1" "@rspack/lite-tapable@1.0.1": @@ -3747,6 +3786,13 @@ "@tufjs/canonical-json" "1.0.0" minimatch "^9.0.0" +"@tybys/wasm-util@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.9.0.tgz#3e75eb00604c8d6db470bf18c37b7d984a0e3355" + integrity sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw== + dependencies: + tslib "^2.4.0" + "@types/acorn@^4.0.0": version "4.0.6" resolved "https://registry.yarnpkg.com/@types/acorn/-/acorn-4.0.6.tgz#d61ca5480300ac41a7d973dd5b84d0a591154a22" From 0f7cf285a3d93ea7371a24712a8321ec0f8b06d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Wed, 25 Jun 2025 16:17:01 +0200 Subject: [PATCH 026/103] chore(website): use local SVGs for footer badges (argos + netlify) (#11291) --- website/docusaurus.config.ts | 4 ++-- website/static/img/footer/badge-argos.svg | 1 + website/static/img/footer/badge-netlify.svg | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 website/static/img/footer/badge-argos.svg create mode 100644 website/static/img/footer/badge-netlify.svg diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index 47eddc851a..7ed001e3e0 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -831,14 +831,14 @@ export default async function createConfigAsync() { { html: ` - Deploys by Netlify + Deploys by Netlify `, }, { html: ` - Covered by Argos + Covered by Argos `, }, diff --git a/website/static/img/footer/badge-argos.svg b/website/static/img/footer/badge-argos.svg new file mode 100644 index 0000000000..a3be471aec --- /dev/null +++ b/website/static/img/footer/badge-argos.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/website/static/img/footer/badge-netlify.svg b/website/static/img/footer/badge-netlify.svg new file mode 100644 index 0000000000..2edda22502 --- /dev/null +++ b/website/static/img/footer/badge-netlify.svg @@ -0,0 +1 @@ + \ No newline at end of file From b0df38d31788d68663e637e90698d174dd1d18b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 26 Jun 2025 15:36:46 +0200 Subject: [PATCH 027/103] feat(create-docusaurus): use respectPrefersColorScheme in init template (#11293) --- .../templates/classic-typescript/docusaurus.config.ts | 3 +++ .../create-docusaurus/templates/classic/docusaurus.config.js | 3 +++ 2 files changed, 6 insertions(+) diff --git a/packages/create-docusaurus/templates/classic-typescript/docusaurus.config.ts b/packages/create-docusaurus/templates/classic-typescript/docusaurus.config.ts index 1ef4506097..671bab5472 100644 --- a/packages/create-docusaurus/templates/classic-typescript/docusaurus.config.ts +++ b/packages/create-docusaurus/templates/classic-typescript/docusaurus.config.ts @@ -71,6 +71,9 @@ const config: Config = { themeConfig: { // Replace with your project's social card image: 'img/docusaurus-social-card.jpg', + colorMode: { + respectPrefersColorScheme: true, + }, navbar: { title: 'My Site', logo: { diff --git a/packages/create-docusaurus/templates/classic/docusaurus.config.js b/packages/create-docusaurus/templates/classic/docusaurus.config.js index 124755d17f..be91f221b4 100644 --- a/packages/create-docusaurus/templates/classic/docusaurus.config.js +++ b/packages/create-docusaurus/templates/classic/docusaurus.config.js @@ -79,6 +79,9 @@ const config = { ({ // Replace with your project's social card image: 'img/docusaurus-social-card.jpg', + colorMode: { + respectPrefersColorScheme: true, + }, navbar: { title: 'My Site', logo: { From d9d7e855c248e86b05ee86821622a631b802b56e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 26 Jun 2025 17:10:41 +0200 Subject: [PATCH 028/103] feat(faster): Upgrade to Rspack 1.4 (#11294) --- package.json | 3 - packages/docusaurus-faster/package.json | 2 +- packages/docusaurus/src/webpack/base.ts | 56 ++++++----- yarn.lock | 118 ++++++++++++------------ 4 files changed, 87 insertions(+), 92 deletions(-) diff --git a/package.json b/package.json index 757120cb54..0e9d63abf9 100644 --- a/package.json +++ b/package.json @@ -129,8 +129,5 @@ "stylelint-config-standard": "^29.0.0", "typescript": "~5.8.2" }, - "resolutions": { - "@rspack/core": "1.4.0-rc.0" - }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/packages/docusaurus-faster/package.json b/packages/docusaurus-faster/package.json index 86127a48e2..0fe018b679 100644 --- a/packages/docusaurus-faster/package.json +++ b/packages/docusaurus-faster/package.json @@ -19,7 +19,7 @@ "license": "MIT", "dependencies": { "@docusaurus/types": "3.8.1", - "@rspack/core": "^1.3.15", + "@rspack/core": "^1.4.0", "@swc/core": "^1.7.39", "@swc/html": "^1.7.39", "browserslist": "^4.24.2", diff --git a/packages/docusaurus/src/webpack/base.ts b/packages/docusaurus/src/webpack/base.ts index 32e75f3953..3479d0041f 100644 --- a/packages/docusaurus/src/webpack/base.ts +++ b/packages/docusaurus/src/webpack/base.ts @@ -161,38 +161,36 @@ export async function createBaseConfig({ function getExperiments(): Configuration['experiments'] { if (props.currentBundler.name === 'rspack') { - const PersistentCacheAttributes = process.env - .DOCUSAURUS_NO_PERSISTENT_CACHE - ? {} - : { - cache: { - type: 'persistent', - // Rspack doesn't have "cache.name" like Webpack - // This is not ideal but work around is to merge name/version - // See https://github.com/web-infra-dev/rspack/pull/8920#issuecomment-2658938695 - version: `${getCacheName()}-${getCacheVersion()}`, - buildDependencies: getCacheBuildDependencies(), - }, - }; - // TODO find a way to type this - return { - // This is mostly useful in dev - // See https://rspack.dev/config/experiments#experimentsincremental - // Produces warnings in production builds - // See https://github.com/web-infra-dev/rspack/pull/8311#issuecomment-2476014664 - // We use the same integration as Rspress, with ability to disable - // See https://github.com/web-infra-dev/rspress/pull/1631 - // See https://github.com/facebook/docusaurus/issues/10646 - // @ts-expect-error: Rspack-only, not available in Webpack typedefs - incremental: !isProd && !process.env.DISABLE_RSPACK_INCREMENTAL, + const experiments: any = {}; - // TODO re-enable later, there's an Rspack performance issue - // see https://github.com/facebook/docusaurus/pull/11178 - parallelCodeSplitting: false, + if (!process.env.DOCUSAURUS_NO_PERSISTENT_CACHE) { + experiments.cache = { + type: 'persistent', + // Rspack doesn't have "cache.name" like Webpack + // This is not ideal but work around is to merge name/version + // See https://github.com/web-infra-dev/rspack/pull/8920#issuecomment-2658938695 + version: `${getCacheName()}-${getCacheVersion()}`, + buildDependencies: getCacheBuildDependencies(), + }; + } - ...PersistentCacheAttributes, - }; + if (process.env.DISABLE_RSPACK_INCREMENTAL) { + // Enabled by default since Rspack 1.4 + console.log('Rspack incremental disabled'); + experiments.incremental = false; + } + + if (process.env.ENABLE_RSPACK_LAZY_COMPILATION) { + console.log('Rspack lazyCompilation enabled'); + experiments.lazyCompilation = true; + } + + // TODO re-enable later, there's an Rspack performance issue + // see https://github.com/facebook/docusaurus/pull/11178 + experiments.parallelCodeSplitting = false; + + return experiments; } return undefined; } diff --git a/yarn.lock b/yarn.lock index a1684cb125..b1d51b9392 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3304,81 +3304,81 @@ fs-extra "^11.1.1" lodash "^4.17.21" -"@rspack/binding-darwin-arm64@1.4.0-rc.0": - version "1.4.0-rc.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.4.0-rc.0.tgz#f594417f088dd71c3524df42ee60b5ce89276f9e" - integrity sha512-4fJ577AVWSHHsY+FEozxhYpnSGZmIneusFhIpbkf7l3x8hh5SdL6hE2y3lNeE9BHgjHPfdMJogoz/VNYcTWG/A== +"@rspack/binding-darwin-arm64@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.4.0.tgz#e6af3cc2dad3f0e38655f959f8783f26e7766ac5" + integrity sha512-fOvbe71PAu9mM4f9KYssielLlTaQ0RcaS6fARkOuQRS3HfmZnAcMJA9kDkMAWBdsHQSW2RPHLji0Ng7lumAFvg== -"@rspack/binding-darwin-x64@1.4.0-rc.0": - version "1.4.0-rc.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.4.0-rc.0.tgz#c8e3cbca13019985d3002ac3695b4318d7cab8c2" - integrity sha512-6r4l/2VhPuHrQrDYazQl4GNTSPvPPXEZwee2fYVO6YeWiPPJFNAUyIT0DjXtAMuJ2zDBOH0DkJ6dqkLf9/kn8Q== +"@rspack/binding-darwin-x64@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.4.0.tgz#1cf3b935dccead1a145eed72ca746000d5a6fde8" + integrity sha512-1U7u5LdB+FwC90i3U9WDNeQoD8xoCfQBZPI0M6nB8pBCLW3HIP6Lzd60hTSKPuWOW6ZuXroUGoRG0z/ba8QlNg== -"@rspack/binding-linux-arm64-gnu@1.4.0-rc.0": - version "1.4.0-rc.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.4.0-rc.0.tgz#f2d11e5a811e5edcc7d315b91d88b2938b635d4a" - integrity sha512-K6VLea9StRkOltXqyxNzKeNR3cAFsOpHoNDc8lg0zZNAr1Rn1f+8THqFlWfDV1djXvhM/LsBM+rG97yQFYh/zg== +"@rspack/binding-linux-arm64-gnu@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.4.0.tgz#2c33af789717b89a773bd9fdff2b3f1907f4253e" + integrity sha512-XYOfmHDYo88jruqAtyjklTqrNeixigP2QjsiZDiB0YvRQyaoLTw3hZ7RvhJbVruxFibwF75yiMlMD9LJgDTxrg== -"@rspack/binding-linux-arm64-musl@1.4.0-rc.0": - version "1.4.0-rc.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.4.0-rc.0.tgz#bb778478e0470ffef8a6c671f383de5b5566ad98" - integrity sha512-/xAgd0ObvI9ggJWMHDI8WHFCeuqi7gMnzdeN8QWO82dzlwO/0rgBqQkULS1hUDlV47Hh03BwjUz9sbuXCnelqg== +"@rspack/binding-linux-arm64-musl@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.4.0.tgz#ea9dc16b431afc3a77dc5ce57963197a47cc3934" + integrity sha512-IvQNw3wN5Dro1CeT4f95W7R/ZAKREcsf9s0Kqk4NtBhaPxcEf+nV72mMDBzPUakEI/g32e5Evb91w3y0EFWhIg== -"@rspack/binding-linux-x64-gnu@1.4.0-rc.0": - version "1.4.0-rc.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.4.0-rc.0.tgz#903ff50274557c9abb5f632128c5d76ae07495f8" - integrity sha512-2u6ytaatpksqUfEn16M/8ppkYaurQpPgZ7cCy3iFpVi6w+7loXWz0X+xklsuBH8H0ie4CZkLmiJIhkW2hFn8KA== +"@rspack/binding-linux-x64-gnu@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.4.0.tgz#dae15219743b7c885b1fa8e296b2b6b65e3b2d6a" + integrity sha512-b71w0Iflh/7gvwrpdfJYC4FsCb84mQen3YDYtiBF7VWdXKTN5OzWoibX/3i68l3HBncCf0vmWRr9XFrdejEZEg== -"@rspack/binding-linux-x64-musl@1.4.0-rc.0": - version "1.4.0-rc.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.4.0-rc.0.tgz#17a1b03d62980c61a22dc25d34254251e636bbb7" - integrity sha512-ilSb6GDz/0A+qlnPFZJuw9DtFH/ENf09f7raXxye3faZw/GH8aJ9H3X8VNeMR1QrYwFFk8LLB402EtZHETyz7Q== +"@rspack/binding-linux-x64-musl@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.4.0.tgz#ad2aab3ae6dbc0bfa1e089d992d35216831e4d05" + integrity sha512-aGanEWtYRBiuS6RdI3rOwcV/tetq5duyYRmm/i1RoGAyfGp7vtoPpKVl7PP/hODWp3lZ9PVn3FhxsEaV7LY36Q== -"@rspack/binding-wasm32-wasi@1.4.0-rc.0": - version "1.4.0-rc.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.4.0-rc.0.tgz#1cef3b3b8831e1cb453665fa1b0094376e76d8e9" - integrity sha512-NsnAfBrQDlZTgudxG2YNgnOsZgaE4Vqm1pM0OXWd6NOhSGwGQ6T/rka99dHiUTxxAb6AOqI/avVn1NYsPHsqIQ== +"@rspack/binding-wasm32-wasi@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.4.0.tgz#cda5fe008b250d62d90f276d58f23d4cf030f57a" + integrity sha512-3LMP/bs/qCQw7Os/Y9HXVZ15TyXhngM1EQtX0ULJLPdOaX5yO/znXwdzRCI03T8i3MIZxno9EdgHlg1FNt4Puw== dependencies: "@napi-rs/wasm-runtime" "^0.2.11" -"@rspack/binding-win32-arm64-msvc@1.4.0-rc.0": - version "1.4.0-rc.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.4.0-rc.0.tgz#4269ed6f9dabffd85d2b154bc6b91bba04e55b50" - integrity sha512-dT7FZz0dbWKzb3Ka6OD0TkOhGS/qC2/tWJ98nIxXMFCW2ZcULJhwcnRe95KBEwVDzwHgcTTzVa3fUFuTmcL87w== +"@rspack/binding-win32-arm64-msvc@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.4.0.tgz#a8ae10945f82695ccf637f87db51fbcd12000f02" + integrity sha512-cduBQqs8bGMFui7gpq+NlMOq1lr78jCvfUNEvZ59hU9xIx3Xewq1yQRNKuCikx24HJCtKRgzYdSMKMpUwnNNMg== -"@rspack/binding-win32-ia32-msvc@1.4.0-rc.0": - version "1.4.0-rc.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.4.0-rc.0.tgz#c3c421e7406c6b49fc9aeec9c5643fe5acb99049" - integrity sha512-0Q8+vWvT6zZPkNqaUvBIfXUSC3ZHsu/2on1bX9bGWLVfG4Or1QWY9vNA3vPX8DsK3XiHwixX+iLo95tmQgasNw== +"@rspack/binding-win32-ia32-msvc@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.4.0.tgz#730f2c834aa6bb7afa97651e25060ceb6e2a9fbb" + integrity sha512-ZNWutTwz4iL/9QD0rYk+JKpes5Nx+bQys5aBVM2z/BefvWInw+3beeIRV6SgY8UiO5jc5GEwmdwdv8duzUrhbg== -"@rspack/binding-win32-x64-msvc@1.4.0-rc.0": - version "1.4.0-rc.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.4.0-rc.0.tgz#c785db3b6c931ec31f689ecc5b974328ea813564" - integrity sha512-bsKJGM6Tu6aqyt6QTDEPL0BCtJ/HWHF3phdCP9XBUcmlSvjIwemekTs/QO/k2ZKXQ93j9Sz8J92WWmNQp0Mp8w== +"@rspack/binding-win32-x64-msvc@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.4.0.tgz#7556a823d3dccd9951698aeca45398474b916b13" + integrity sha512-pNwpjFCVYQpmA156GgjEqnHly3UZqNXYCJPkouAnUvVE9m0Xoo9May7v7ovKUH4ayySTryL42Ii8tL4iStyJuA== -"@rspack/binding@1.4.0-rc.0": - version "1.4.0-rc.0" - resolved "https://registry.yarnpkg.com/@rspack/binding/-/binding-1.4.0-rc.0.tgz#3001e857fc4848ab6d1224e87845739df1bed963" - integrity sha512-kBEzks6RymjBLYF84TkUP895yCqqlodHDmBsWKbJGOokNKx+0ohnoWxXws5oZca/j9DSKCdEsA8VyROtqdMujw== +"@rspack/binding@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rspack/binding/-/binding-1.4.0.tgz#b07a41443c82467ad53e909683c0346481e3af56" + integrity sha512-Kex9H6w44oTYzaQK/goV/BhUJoeWL8rPI1symDjRRvSK4ca/P4OceHvlQzfU0WGg2VKnhTAxH3+KMlpYQFabOQ== optionalDependencies: - "@rspack/binding-darwin-arm64" "1.4.0-rc.0" - "@rspack/binding-darwin-x64" "1.4.0-rc.0" - "@rspack/binding-linux-arm64-gnu" "1.4.0-rc.0" - "@rspack/binding-linux-arm64-musl" "1.4.0-rc.0" - "@rspack/binding-linux-x64-gnu" "1.4.0-rc.0" - "@rspack/binding-linux-x64-musl" "1.4.0-rc.0" - "@rspack/binding-wasm32-wasi" "1.4.0-rc.0" - "@rspack/binding-win32-arm64-msvc" "1.4.0-rc.0" - "@rspack/binding-win32-ia32-msvc" "1.4.0-rc.0" - "@rspack/binding-win32-x64-msvc" "1.4.0-rc.0" + "@rspack/binding-darwin-arm64" "1.4.0" + "@rspack/binding-darwin-x64" "1.4.0" + "@rspack/binding-linux-arm64-gnu" "1.4.0" + "@rspack/binding-linux-arm64-musl" "1.4.0" + "@rspack/binding-linux-x64-gnu" "1.4.0" + "@rspack/binding-linux-x64-musl" "1.4.0" + "@rspack/binding-wasm32-wasi" "1.4.0" + "@rspack/binding-win32-arm64-msvc" "1.4.0" + "@rspack/binding-win32-ia32-msvc" "1.4.0" + "@rspack/binding-win32-x64-msvc" "1.4.0" -"@rspack/core@1.4.0-rc.0", "@rspack/core@^1.3.15": - version "1.4.0-rc.0" - resolved "https://registry.yarnpkg.com/@rspack/core/-/core-1.4.0-rc.0.tgz#1ecb66b34971e20acf552e6e9d38aa063840fee9" - integrity sha512-yO4AP7sgptepks2kNLFvLipdonGv6OKDUIKEl0c7SpbBmPEspd3vsYxE/T5hruFVDnq0GPEePKA1GOjRCKGR8A== +"@rspack/core@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rspack/core/-/core-1.4.0.tgz#40edc101bf81b7b85b7c96971c1a4a5035c782f9" + integrity sha512-eIzbMYdrpJLjfkelKFLpxUObuv2gAmAuebUJmXeyf2OlFT/DGgoWRDGOVX4MpIHgcE1XCi27sqvOdRU4HA7Zgw== dependencies: "@module-federation/runtime-tools" "0.15.0" - "@rspack/binding" "1.4.0-rc.0" + "@rspack/binding" "1.4.0" "@rspack/lite-tapable" "1.0.1" "@rspack/lite-tapable@1.0.1": From da0853681658a804ef79f8a654a7e649d0ee2e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 3 Jul 2025 13:40:00 +0200 Subject: [PATCH 029/103] feat(docs): sidebar item `key` attribute - fix docs translations key conflicts (#11228) --- .../src/__tests__/props.test.ts | 127 ++++++++++++- .../src/__tests__/translations.test.ts | 147 ++++++++++++++- .../src/props.ts | 5 +- .../__snapshots__/generator.test.ts.snap | 1 + .../src/sidebars/__tests__/generator.test.ts | 1 + .../src/sidebars/__tests__/validation.test.ts | 172 +++++++++++++++--- .../src/sidebars/generator.ts | 1 + .../src/sidebars/types.ts | 7 +- .../src/sidebars/validation.ts | 2 + .../src/translations.ts | 85 ++++++--- .../tests/Conflicts/_category_.json | 8 + .../category-index-name/_category_.json | 8 + .../category-index-name/alpha/_category_.json | 6 + .../alpha/test/_category_.json | 9 + .../category-index-name/alpha/test/test.md | 4 + .../category-index-name/beta/_category_.json | 6 + .../beta/test/_category_.json | 9 + .../category-index-name/beta/test/test.md | 4 + .../tests/Conflicts/sidebar-label/doc1.mdx | 7 + .../tests/Conflicts/sidebar-label/doc2.mdx | 7 + website/_dogfooding/docs-tests-sidebars.js | 20 +- website/docs/guides/docs/sidebar/index.mdx | 40 +++- website/docs/guides/docs/sidebar/items.mdx | 15 +- 23 files changed, 632 insertions(+), 59 deletions(-) create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/_category_.json create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/_category_.json create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/alpha/_category_.json create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/alpha/test/_category_.json create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/alpha/test/test.md create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/beta/_category_.json create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/beta/test/_category_.json create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/beta/test/test.md create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/sidebar-label/doc1.mdx create mode 100644 website/_dogfooding/_docs tests/tests/Conflicts/sidebar-label/doc2.mdx diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/props.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/props.test.ts index 960727f01f..09f2ca20b4 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/props.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/props.test.ts @@ -5,7 +5,12 @@ * LICENSE file in the root directory of this source tree. */ -import {toSidebarDocItemLinkProp, toTagDocListProp} from '../props'; +import {fromPartial} from '@total-typescript/shoehorn'; +import { + toSidebarDocItemLinkProp, + toSidebarsProp, + toTagDocListProp, +} from '../props'; describe('toTagDocListProp', () => { type Params = Parameters[0]; @@ -132,3 +137,123 @@ describe('toSidebarDocItemLinkProp', () => { ).toBe(false); }); }); + +describe('toSidebarsProp', () => { + type Params = Parameters[0]; + + it('works', () => { + const params: Params = { + docs: [ + fromPartial({ + id: 'doc-id-1', + permalink: '/doc-1', + title: 'Doc 1 title', + frontMatter: {}, + }), + ], + sidebars: { + mySidebar: [ + { + type: 'link', + label: 'Example link', + key: 'link-example-key', + href: 'https://example.com', + }, + { + type: 'ref', + label: 'Doc 1 ref', + key: 'ref-with-doc-id-1', + id: 'doc-id-1', + }, + { + type: 'ref', + id: 'doc-id-1', + // no label/key on purpose + }, + { + type: 'category', + label: 'My category', + key: 'my-category-key', + collapsible: false, + collapsed: true, + items: [ + { + type: 'doc', + label: 'Doc 1', + key: 'doc-id-1', + id: 'doc-id-1', + }, + { + type: 'doc', + id: 'doc-id-1', + // no label/key on purpose + }, + ], + }, + ], + }, + }; + + const result = toSidebarsProp(params); + + expect(result).toMatchInlineSnapshot(` + { + "mySidebar": [ + { + "href": "https://example.com", + "key": "link-example-key", + "label": "Example link", + "type": "link", + }, + { + "className": undefined, + "customProps": undefined, + "docId": "doc-id-1", + "href": "/doc-1", + "key": "ref-with-doc-id-1", + "label": "Doc 1 ref", + "type": "link", + "unlisted": undefined, + }, + { + "className": undefined, + "customProps": undefined, + "docId": "doc-id-1", + "href": "/doc-1", + "label": "Doc 1 title", + "type": "link", + "unlisted": undefined, + }, + { + "collapsed": true, + "collapsible": false, + "items": [ + { + "className": undefined, + "customProps": undefined, + "docId": "doc-id-1", + "href": "/doc-1", + "key": "doc-id-1", + "label": "Doc 1", + "type": "link", + "unlisted": undefined, + }, + { + "className": undefined, + "customProps": undefined, + "docId": "doc-id-1", + "href": "/doc-1", + "label": "Doc 1 title", + "type": "link", + "unlisted": undefined, + }, + ], + "key": "my-category-key", + "label": "My category", + "type": "category", + }, + ], + } + `); + }); +}); diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/translations.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/translations.test.ts index 6175606158..45a06c114d 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/translations.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/translations.test.ts @@ -16,6 +16,7 @@ import type { LoadedContent, LoadedVersion, } from '@docusaurus/plugin-content-docs'; +import type {Sidebar} from '../sidebars/types'; function createSampleDoc(doc: Pick): DocMetadata { return { @@ -41,7 +42,7 @@ function createSampleDoc(doc: Pick): DocMetadata { } function createSampleVersion( - version: Pick, + version: Pick & Partial, ): LoadedVersion { return { label: `${version.versionName} label`, @@ -152,6 +153,150 @@ describe('getLoadedContentTranslationFiles', () => { it('returns translation files', () => { expect(getSampleTranslationFiles()).toMatchSnapshot(); }); + + describe('translation key conflicts', () => { + function runTest({withUniqueKeys}: {withUniqueKeys: boolean}) { + const sidebarWithConflicts: Sidebar = [ + { + type: 'doc', + id: 'doc4', + label: 'COMMON LABEL', + translatable: true, + ...(withUniqueKeys && {key: 'key-doc4'}), + }, + { + type: 'doc', + id: 'doc5', + label: 'COMMON LABEL', + translatable: true, + ...(withUniqueKeys && {key: 'key-doc5'}), + }, + { + type: 'ref', + id: 'doc4', + label: 'COMMON LABEL', + translatable: true, + ...(withUniqueKeys && {key: 'key-ref4'}), + }, + { + type: 'ref', + id: 'doc5', + label: 'COMMON LABEL', + translatable: true, + ...(withUniqueKeys && {key: 'key-ref5'}), + }, + { + type: 'category', + label: 'COMMON LABEL', + items: [], + collapsed: false, + collapsible: true, + ...(withUniqueKeys && {key: 'key-cat1'}), + }, + { + type: 'category', + label: 'COMMON LABEL', + items: [], + collapsed: false, + collapsible: true, + ...(withUniqueKeys && {key: 'key-cat2'}), + }, + { + type: 'link', + href: 'https://example.com', + label: 'COMMON LABEL', + ...(withUniqueKeys && {key: 'key-link1'}), + }, + { + type: 'link', + href: 'https://example.com', + label: 'COMMON LABEL', + ...(withUniqueKeys && {key: 'key-link2'}), + }, + ]; + + const version = createSampleVersion({ + versionName: CURRENT_VERSION_NAME, + sidebars: { + sidebarWithConflicts, + }, + }); + return getLoadedContentTranslationFiles({ + loadedVersions: [version], + }); + } + + it('works on sidebar with translation key conflicts resolved by unique sidebar item keys', () => { + expect(runTest({withUniqueKeys: true})).toMatchInlineSnapshot(` + [ + { + "content": { + "sidebar.sidebarWithConflicts.category.key-cat1": { + "description": "The label for category COMMON LABEL in sidebar sidebarWithConflicts", + "message": "COMMON LABEL", + }, + "sidebar.sidebarWithConflicts.category.key-cat2": { + "description": "The label for category COMMON LABEL in sidebar sidebarWithConflicts", + "message": "COMMON LABEL", + }, + "sidebar.sidebarWithConflicts.doc.key-doc4": { + "description": "The label for the doc item COMMON LABEL in sidebar sidebarWithConflicts, linking to the doc doc4", + "message": "COMMON LABEL", + }, + "sidebar.sidebarWithConflicts.doc.key-doc5": { + "description": "The label for the doc item COMMON LABEL in sidebar sidebarWithConflicts, linking to the doc doc5", + "message": "COMMON LABEL", + }, + "sidebar.sidebarWithConflicts.doc.key-ref4": { + "description": "The label for the doc item COMMON LABEL in sidebar sidebarWithConflicts, linking to the doc doc4", + "message": "COMMON LABEL", + }, + "sidebar.sidebarWithConflicts.doc.key-ref5": { + "description": "The label for the doc item COMMON LABEL in sidebar sidebarWithConflicts, linking to the doc doc5", + "message": "COMMON LABEL", + }, + "sidebar.sidebarWithConflicts.link.key-link1": { + "description": "The label for link COMMON LABEL in sidebar sidebarWithConflicts, linking to https://example.com", + "message": "COMMON LABEL", + }, + "sidebar.sidebarWithConflicts.link.key-link2": { + "description": "The label for link COMMON LABEL in sidebar sidebarWithConflicts, linking to https://example.com", + "message": "COMMON LABEL", + }, + "version.label": { + "description": "The label for version current", + "message": "current label", + }, + }, + "path": "current", + }, + ] + `); + }); + + it('throws on sidebar translation key conflicts', () => { + expect(() => runTest({withUniqueKeys: false})) + .toThrowErrorMatchingInlineSnapshot(` + "Multiple docs sidebar items produce the same translation key. + - \`sidebar.sidebarWithConflicts.category.COMMON LABEL\`: 2 duplicates found: + - COMMON LABEL (The label for category COMMON LABEL in sidebar sidebarWithConflicts) + - COMMON LABEL (The label for category COMMON LABEL in sidebar sidebarWithConflicts) + + - \`sidebar.sidebarWithConflicts.link.COMMON LABEL\`: 2 duplicates found: + - COMMON LABEL (The label for link COMMON LABEL in sidebar sidebarWithConflicts, linking to https://example.com) + - COMMON LABEL (The label for link COMMON LABEL in sidebar sidebarWithConflicts, linking to https://example.com) + + - \`sidebar.sidebarWithConflicts.doc.COMMON LABEL\`: 4 duplicates found: + - COMMON LABEL (The label for the doc item COMMON LABEL in sidebar sidebarWithConflicts, linking to the doc doc4) + - COMMON LABEL (The label for the doc item COMMON LABEL in sidebar sidebarWithConflicts, linking to the doc doc5) + - COMMON LABEL (The label for the doc item COMMON LABEL in sidebar sidebarWithConflicts, linking to the doc doc4) + - COMMON LABEL (The label for the doc item COMMON LABEL in sidebar sidebarWithConflicts, linking to the doc doc5) + + To avoid translation key conflicts, use the \`key\` attribute on the sidebar items above to uniquely identify them. + " + `); + }); + }); }); describe('translateLoadedContent', () => { diff --git a/packages/docusaurus-plugin-content-docs/src/props.ts b/packages/docusaurus-plugin-content-docs/src/props.ts index 3f2d00c87c..c7a2eb1040 100644 --- a/packages/docusaurus-plugin-content-docs/src/props.ts +++ b/packages/docusaurus-plugin-content-docs/src/props.ts @@ -41,6 +41,7 @@ export function toSidebarDocItemLinkProp({ const {id, title, permalink, frontMatter, unlisted} = doc; return { type: 'link', + ...(item.key && {key: item.key}), href: permalink, // Front Matter data takes precedence over sidebars.json label: frontMatter.sidebar_label ?? item.label ?? title, @@ -51,7 +52,9 @@ export function toSidebarDocItemLinkProp({ }; } -export function toSidebarsProp(loadedVersion: LoadedVersion): PropSidebars { +export function toSidebarsProp( + loadedVersion: Pick, +): PropSidebars { const docsById = createDocsByIdIndex(loadedVersion.docs); function getDocById(docId: string): DocMetadata { diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/__snapshots__/generator.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/__snapshots__/generator.test.ts.snap index 63430fd363..e4d7132e65 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/__snapshots__/generator.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/__snapshots__/generator.test.ts.snap @@ -47,6 +47,7 @@ exports[`DefaultSidebarItemsGenerator generates complex nested sidebar 1`] = ` "type": "doc", }, ], + "key": "SubGuides-category-unique-key", "label": "SubGuides (metadata file label)", "link": { "description": "subGuides-description", diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/generator.test.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/generator.test.ts index de104a1a25..5072fd80d7 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/generator.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/generator.test.ts @@ -129,6 +129,7 @@ describe('DefaultSidebarItemsGenerator', () => { }, '02-Guides/01-SubGuides': { label: 'SubGuides (metadata file label)', + key: 'SubGuides-category-unique-key', link: { type: 'generated-index', slug: 'subGuides-generated-index-slug', diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/validation.test.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/validation.test.ts index 47055ffce7..042c95d34a 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/validation.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/validation.test.ts @@ -29,10 +29,12 @@ describe('validateSidebars', () => { it('accept valid values', () => { const sidebars: SidebarsConfig = { sidebar1: [ - {type: 'doc', id: 'doc1'}, + {type: 'doc', id: 'doc1', key: 'key-doc1'}, {type: 'doc', id: 'doc2'}, + {type: 'ref', id: 'doc2', key: 'ref-doc2'}, { type: 'category', + key: 'key-cat', label: 'Category', items: [{type: 'doc', id: 'doc3'}], }, @@ -68,6 +70,33 @@ describe('validateSidebars', () => { `); }); + it('sidebar category wrong key', () => { + expect(() => + validateSidebars({ + docs: [ + { + type: 'category', + key: '', + items: [{type: 'doc', id: 'doc1'}], + }, + ], + }), + ).toThrowErrorMatchingInlineSnapshot(` + "{ + "type": "category", + "items": [ + { + "type": "doc", + "id": "doc1" + } + ], + "key" [1]: "" + } + + [1] "key" is not allowed to be empty" + `); + }); + it('sidebars link wrong label', () => { expect(() => validateSidebars({ @@ -90,6 +119,28 @@ describe('validateSidebars', () => { `); }); + it('sidebars link wrong key', () => { + expect(() => + validateSidebars({ + docs: [ + { + type: 'link', + key: false, + href: 'https://github.com', + }, + ], + }), + ).toThrowErrorMatchingInlineSnapshot(` + "{ + "type": "link", + "href": "https://github.com", + "key" [1]: false + } + + [1] "key" must be a string" + `); + }); + it('sidebars link wrong href', () => { expect(() => validateSidebars({ @@ -188,6 +239,35 @@ describe('validateSidebars', () => { `); }); + it('sidebars category wrong key', () => { + expect(() => + validateSidebars({ + docs: [ + { + type: 'category', + label: 'category', + key: 42, + items: [], + }, + + { + type: 'ref', + id: 'hello', + }, + ], + }), + ).toThrowErrorMatchingInlineSnapshot(` + "{ + "type": "category", + "label": "category", + "items": [], + "key" [1]: 42 + } + + [1] "key" must be a string" + `); + }); + it('sidebar category wrong items', () => { expect(() => validateSidebars({ @@ -230,8 +310,8 @@ describe('validateSidebars', () => { const sidebars: SidebarsConfig = { sidebar1: [ { - // @ts-expect-error - test missing value type: 'html', + value: undefined, }, ], }; @@ -251,6 +331,7 @@ describe('validateSidebars', () => { sidebar1: [ { type: 'html', + key: 'html-key', value: '

Hello, World!

', defaultStyle: true, className: 'foo', @@ -262,8 +343,6 @@ describe('validateSidebars', () => { }); describe('validateCategoryMetadataFile', () => { - // TODO add more tests - it('throw for bad value', () => { expect(() => validateCategoryMetadataFile(42), @@ -279,6 +358,7 @@ describe('validateCategoryMetadataFile', () => { const content: CategoryMetadataFile = { className: 'className', label: 'Category Label', + key: 'category-key', description: 'Category Description', link: { type: 'generated-index', @@ -293,24 +373,70 @@ describe('validateCategoryMetadataFile', () => { expect(validateCategoryMetadataFile(content)).toEqual(content); }); - it('rejects permalink', () => { - const content: CategoryMetadataFile = { - className: 'className', - label: 'Category Label', - link: { - type: 'generated-index', - slug: 'slug', - // @ts-expect-error: rejected on purpose - permalink: 'somePermalink', - title: 'title', - description: 'description', - }, - collapsible: true, - collapsed: true, - position: 3, - }; - expect(() => - validateCategoryMetadataFile(content), - ).toThrowErrorMatchingInlineSnapshot(`""link.permalink" is not allowed"`); + describe('label', () => { + it('accepts valid label', () => { + const content: CategoryMetadataFile = {label: 'Category label'}; + expect(validateCategoryMetadataFile(content)).toEqual(content); + }); + + it('throws for number label', () => { + expect(() => + validateCategoryMetadataFile({label: 42}), + ).toThrowErrorMatchingInlineSnapshot(`""label" must be a string"`); + }); + }); + + describe('key', () => { + it('accepts valid key', () => { + const content: CategoryMetadataFile = {key: 'Category key'}; + expect(validateCategoryMetadataFile(content)).toEqual(content); + }); + + it('throws for number key', () => { + expect(() => + validateCategoryMetadataFile({key: 42}), + ).toThrowErrorMatchingInlineSnapshot(`""key" must be a string"`); + }); + }); + + describe('className', () => { + it('accepts valid className', () => { + const content: CategoryMetadataFile = {className: 'category-className'}; + expect(validateCategoryMetadataFile(content)).toEqual(content); + }); + + it('throws for number key', () => { + expect(() => + validateCategoryMetadataFile({className: 42}), + ).toThrowErrorMatchingInlineSnapshot(`""className" must be a string"`); + }); + }); + + describe('link', () => { + it('accepts valid link', () => { + const content: CategoryMetadataFile = { + link: { + type: 'generated-index', + slug: 'slug', + title: 'title', + description: 'desc', + }, + }; + expect(validateCategoryMetadataFile(content)).toEqual(content); + }); + + it('rejects link permalink', () => { + const content: CategoryMetadataFile = { + link: { + type: 'generated-index', + slug: 'slug', + // @ts-expect-error: rejected on purpose + permalink: 'somePermalink', + }, + }; + expect(() => + validateCategoryMetadataFile(content), + ).toThrowErrorMatchingInlineSnapshot(`""link.permalink" is not allowed"`); + }); }); }); diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts index 20383b003a..cbd58d7b5b 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts @@ -252,6 +252,7 @@ Available doc IDs: ...(categoryMetadata?.description && { description: categoryMetadata?.description, }), + ...(categoryMetadata?.key && {key: categoryMetadata?.key}), ...(link && {link}), }; } diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts index 9dbd23415d..550243b90e 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts @@ -19,6 +19,7 @@ import type {Slugger} from '@docusaurus/utils'; type Expand = {[P in keyof T]: T[P]}; export type SidebarItemBase = { + key?: string; className?: string; customProps?: {[key: string]: unknown}; }; @@ -28,8 +29,9 @@ export type SidebarItemDoc = SidebarItemBase & { label?: string; id: string; /** - * This is an internal marker. Items with labels defined in the config needs - * to be translated with JSON + * This is an internal marker set during the sidebar normalization process. + * Docs with labels defined in the config need to be translated with JSON. + * Otherwise, it's preferable to translate the MDX doc title or front matter. */ translatable?: true; }; @@ -215,6 +217,7 @@ export type PropSidebarBreadcrumbsItem = | PropSidebarItemCategory; export type CategoryMetadataFile = { + key?: string; label?: string; position?: number; description?: string; diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/validation.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/validation.ts index 33492dc309..bc1ca47061 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/validation.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/validation.ts @@ -28,6 +28,7 @@ import type { // in normalization const sidebarItemBaseSchema = Joi.object({ + key: Joi.string(), className: Joi.string(), customProps: Joi.object().unknown(), }); @@ -166,6 +167,7 @@ export function validateSidebars(sidebars: { } const categoryMetadataFileSchema = Joi.object({ + key: Joi.string(), label: Joi.string(), description: Joi.string(), position: Joi.number(), diff --git a/packages/docusaurus-plugin-content-docs/src/translations.ts b/packages/docusaurus-plugin-content-docs/src/translations.ts index bc6f8bbb8b..ec35afbe4b 100644 --- a/packages/docusaurus-plugin-content-docs/src/translations.ts +++ b/packages/docusaurus-plugin-content-docs/src/translations.ts @@ -7,6 +7,7 @@ import _ from 'lodash'; import {mergeTranslations} from '@docusaurus/utils'; +import logger from '@docusaurus/logger'; import {CURRENT_VERSION_NAME} from './constants'; import { collectSidebarCategories, @@ -40,20 +41,53 @@ function getVersionFileName(versionName: string): string { return `version-${versionName}`; } +type TranslationMessageEntry = [string, TranslationMessage]; + +function ensureNoSidebarDuplicateEntries( + translationEntries: TranslationMessageEntry[], +): void { + const grouped = _.groupBy(translationEntries, (entry) => entry[0]); + const duplicates = Object.entries(grouped).filter( + (entry) => entry[1].length > 1, + ); + + if (duplicates.length > 0) { + throw new Error(`Multiple docs sidebar items produce the same translation key. +- ${duplicates + .map(([translationKey, entries]) => { + return `${logger.code(translationKey)}: ${logger.num( + entries.length, + )} duplicates found:\n - ${entries + .map((duplicate) => { + const desc = duplicate[1].description; + return `${logger.name(duplicate[1].message)} ${ + desc ? `(${logger.subdue(desc)})` : '' + }`; + }) + .join('\n - ')}`; + }) + .join('\n\n- ')} + +To avoid translation key conflicts, use the ${logger.code( + 'key', + )} attribute on the sidebar items above to uniquely identify them. + `); + } +} + function getSidebarTranslationFileContent( sidebar: Sidebar, sidebarName: string, ): TranslationFileContent { - type TranslationMessageEntry = [string, TranslationMessage]; - const categories = collectSidebarCategories(sidebar); - const categoryContent: TranslationFileContent = Object.fromEntries( - categories.flatMap((category) => { + const categoryEntries: TranslationMessageEntry[] = categories.flatMap( + (category) => { const entries: TranslationMessageEntry[] = []; + const categoryKey = category.key ?? category.label; entries.push([ - `sidebar.${sidebarName}.category.${category.label}`, + `sidebar.${sidebarName}.category.${categoryKey}`, { message: category.label, description: `The label for category ${category.label} in sidebar ${sidebarName}`, @@ -63,7 +97,7 @@ function getSidebarTranslationFileContent( if (category.link?.type === 'generated-index') { if (category.link.title) { entries.push([ - `sidebar.${sidebarName}.category.${category.label}.link.generated-index.title`, + `sidebar.${sidebarName}.category.${categoryKey}.link.generated-index.title`, { message: category.link.title, description: `The generated-index page title for category ${category.label} in sidebar ${sidebarName}`, @@ -72,7 +106,7 @@ function getSidebarTranslationFileContent( } if (category.link.description) { entries.push([ - `sidebar.${sidebarName}.category.${category.label}.link.generated-index.description`, + `sidebar.${sidebarName}.category.${categoryKey}.link.generated-index.description`, { message: category.link.description, description: `The generated-index page description for category ${category.label} in sidebar ${sidebarName}`, @@ -82,36 +116,40 @@ function getSidebarTranslationFileContent( } return entries; - }), + }, ); const links = collectSidebarLinks(sidebar); - const linksContent: TranslationFileContent = Object.fromEntries( - links.map((link) => [ - `sidebar.${sidebarName}.link.${link.label}`, + const linksEntries: TranslationMessageEntry[] = links.map((link) => { + const linkKey = link.key ?? link.label; + return [ + `sidebar.${sidebarName}.link.${linkKey}`, { message: link.label, description: `The label for link ${link.label} in sidebar ${sidebarName}, linking to ${link.href}`, }, - ]), - ); + ]; + }); const docs = collectSidebarDocItems(sidebar) .concat(collectSidebarRefs(sidebar)) .filter((item) => item.translatable); - const docLinksContent: TranslationFileContent = Object.fromEntries( - docs.map((doc) => [ - `sidebar.${sidebarName}.doc.${doc.label!}`, + const docLinksEntries: TranslationMessageEntry[] = docs.map((doc) => { + const docKey = doc.key ?? doc.label!; + return [ + `sidebar.${sidebarName}.doc.${docKey}`, { message: doc.label!, description: `The label for the doc item ${doc.label!} in sidebar ${sidebarName}, linking to the doc ${ doc.id }`, }, - ]), - ); + ]; + }); - return mergeTranslations([categoryContent, linksContent, docLinksContent]); + const allEntries = [...categoryEntries, ...linksEntries, ...docLinksEntries]; + ensureNoSidebarDuplicateEntries(allEntries); + return Object.fromEntries(allEntries); } function translateSidebar({ @@ -150,27 +188,30 @@ function translateSidebar({ return transformSidebarItems(sidebar, (item) => { if (item.type === 'category') { const link = transformSidebarCategoryLink(item); + const categoryKey = item.key ?? item.label; return { ...item, label: - sidebarsTranslations[`sidebar.${sidebarName}.category.${item.label}`] + sidebarsTranslations[`sidebar.${sidebarName}.category.${categoryKey}`] ?.message ?? item.label, ...(link && {link}), }; } if (item.type === 'link') { + const linkKey = item.key ?? item.label; return { ...item, label: - sidebarsTranslations[`sidebar.${sidebarName}.link.${item.label}`] + sidebarsTranslations[`sidebar.${sidebarName}.link.${linkKey}`] ?.message ?? item.label, }; } if ((item.type === 'doc' || item.type === 'ref') && item.translatable) { + const docKey = item.key ?? item.label!; return { ...item, label: - sidebarsTranslations[`sidebar.${sidebarName}.doc.${item.label!}`] + sidebarsTranslations[`sidebar.${sidebarName}.doc.${docKey}`] ?.message ?? item.label, }; } diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/_category_.json b/website/_dogfooding/_docs tests/tests/Conflicts/_category_.json new file mode 100644 index 0000000000..0a0e8395de --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Conflicts", + "link": { + "type": "generated-index", + "title": "Conflicts", + "description": "Testing what happens when docs use similar names" + } +} diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/_category_.json b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/_category_.json new file mode 100644 index 0000000000..ab5ce9583f --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Category Index name conflict", + "link": { + "type": "generated-index", + "title": "Category Index name conflict", + "description": "Testing what happens when 2 category index have the same name" + } +} diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/alpha/_category_.json b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/alpha/_category_.json new file mode 100644 index 0000000000..a1689a31d9 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/alpha/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Alpha", + "link": { + "type": "generated-index" + } +} diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/alpha/test/_category_.json b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/alpha/test/_category_.json new file mode 100644 index 0000000000..dd99960965 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/alpha/test/_category_.json @@ -0,0 +1,9 @@ +{ + "key": "CategoryLabelTest alpha", + "label": "CategoryLabelTest", + "link": { + "type": "generated-index", + "title": "test category in Alpha", + "description": "Test description in Alpha" + } +} diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/alpha/test/test.md b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/alpha/test/test.md new file mode 100644 index 0000000000..4ee22315f8 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/alpha/test/test.md @@ -0,0 +1,4 @@ +--- +--- + +## Test file diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/beta/_category_.json b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/beta/_category_.json new file mode 100644 index 0000000000..86eedaae9f --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/beta/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Beta", + "link": { + "type": "generated-index" + } +} diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/beta/test/_category_.json b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/beta/test/_category_.json new file mode 100644 index 0000000000..e0fad183c6 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/beta/test/_category_.json @@ -0,0 +1,9 @@ +{ + "key": "CategoryLabelTest beta", + "label": "CategoryLabelTest", + "link": { + "type": "generated-index", + "title": "test category in Beta", + "description": "Test description in Beta" + } +} diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/beta/test/test.md b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/beta/test/test.md new file mode 100644 index 0000000000..4ee22315f8 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/category-index-name/beta/test/test.md @@ -0,0 +1,4 @@ +--- +--- + +## Test file diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/sidebar-label/doc1.mdx b/website/_dogfooding/_docs tests/tests/Conflicts/sidebar-label/doc1.mdx new file mode 100644 index 0000000000..b4dd575602 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/sidebar-label/doc1.mdx @@ -0,0 +1,7 @@ +--- +sidebar_label: Doc sidebar label +--- + +# Doc 1 + +Doc 1 diff --git a/website/_dogfooding/_docs tests/tests/Conflicts/sidebar-label/doc2.mdx b/website/_dogfooding/_docs tests/tests/Conflicts/sidebar-label/doc2.mdx new file mode 100644 index 0000000000..3bb0f6b84e --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/Conflicts/sidebar-label/doc2.mdx @@ -0,0 +1,7 @@ +--- +sidebar_label: Doc sidebar label +--- + +# Doc 2 + +Doc 2 diff --git a/website/_dogfooding/docs-tests-sidebars.js b/website/_dogfooding/docs-tests-sidebars.js index 67d4b80300..d8dac0c10e 100644 --- a/website/_dogfooding/docs-tests-sidebars.js +++ b/website/_dogfooding/docs-tests-sidebars.js @@ -8,6 +8,7 @@ /** * @typedef {import('@docusaurus/plugin-content-docs').SidebarsConfig} SidebarsConfig * @typedef {import('@docusaurus/plugin-content-docs/lib/sidebars/types').SidebarItemConfig} SidebarItemConfig + * @typedef {import('@docusaurus/plugin-content-docs/lib/sidebars/types').SidebarItemCategoryConfig} SidebarItemCategoryConfig */ /** @type {SidebarsConfig} */ @@ -63,7 +64,8 @@ const sidebars = { items: [ { type: 'link', - label: 'Link ', + label: 'Link', + key: 'link-key-1', href: 'https://docusaurus.io', }, ], @@ -76,6 +78,7 @@ const sidebars = { { type: 'link', label: 'Link ', + key: 'link-key-2', href: 'https://docusaurus.io', }, ], @@ -182,14 +185,16 @@ function generateHugeSidebarItems() { /** * @param {number} maxLevel * @param {number} currentLevel + * @param {string} parentKey * @returns {SidebarItemConfig[]} */ - function generateRecursive(maxLevel, currentLevel = 0) { + function generateRecursive(maxLevel, currentLevel = 0, parentKey = 'ROOT') { if (currentLevel === maxLevel) { return [ { type: 'link', href: '/', + key: `link-${parentKey}-maxLevel`, label: `Link (level ${currentLevel + 1})`, }, ]; @@ -198,14 +203,23 @@ function generateHugeSidebarItems() { const linkItems = Array.from(Array(linksCount).keys()).map((index) => ({ type: 'link', href: '/', + key: `link-${parentKey}-${index}`, label: `Link ${index} (level ${currentLevel + 1})`, })); const categoryItems = Array.from(Array(categoriesCount).keys()).map( + /** + * @returns {SidebarItemCategoryConfig} + */ (index) => ({ type: 'category', label: `Category ${index} (level ${currentLevel + 1})`, - items: generateRecursive(maxLevel, currentLevel + 1), + key: `category-${parentKey}-${index}`, + items: generateRecursive( + maxLevel, + currentLevel + 1, + `${parentKey}-${index}`, + ), }), ); diff --git a/website/docs/guides/docs/sidebar/index.mdx b/website/docs/guides/docs/sidebar/index.mdx index 4d2c4d209b..307d836fb3 100644 --- a/website/docs/guides/docs/sidebar/index.mdx +++ b/website/docs/guides/docs/sidebar/index.mdx @@ -6,8 +6,8 @@ slug: /sidebar Creating a sidebar is useful to: -- Group multiple **related documents** -- **Display a sidebar** on each of those documents +- Group multiple **related documents** into an ordered tree +- **Display a common sidebar** on each of those documents - Provide **paginated navigation**, with next/previous button To use sidebars on your Docusaurus site: @@ -160,6 +160,20 @@ export default { }; ``` +## Passing CSS classes {#passing-css-classes} + +To pass CSS classes to a sidebar item, add the optional `className` attribute to any of the items. This is useful to apply visual customizations to specific sidebar items. + +```js +{ + type: 'doc', + id: 'doc1', + // highlight-start + className: 'sidebar-item--highlighted', + // highlight-end +}; +``` + ## Passing custom props {#passing-custom-props} To pass in custom props to a sidebar item, add the optional `customProps` object to any of the items. This is useful to apply site customizations by swizzling React components rendering sidebar items. @@ -177,6 +191,28 @@ To pass in custom props to a sidebar item, add the optional `customProps` object }; ``` +## Passing a unique key {#passing-custom-props} + +Passing a unique `key` attribute can help uniquely identify a sidebar item. Sometimes other attributes (such as `label`) are not enough to distinguish two sidebar items from each other. + +```js +{ + type: 'category', + // highlight-start + label: 'API', // You may have multiple categories with this widespread label + key: 'api-for-feature-1', // and now, they can be uniquely identified + // highlight-end +}; +``` + +:::info How is this useful? + +Docusaurus only uses the `key` attribute to generate unique i18n translation keys. When a translation key conflict happens ([issue](https://github.com/facebook/docusaurus/issues/10913)), Docusaurus will tell you to apply a `key` to distinguish sidebar items. + +Alternatively, you may have your own reasons for using the `key` attribute that will be passed to the respective sidebar item React components. + +::: + ## Sidebar Breadcrumbs {#sidebar-breadcrumbs} By default, breadcrumbs are rendered at the top, using the "sidebar path" of the current page. diff --git a/website/docs/guides/docs/sidebar/items.mdx b/website/docs/guides/docs/sidebar/items.mdx index 1dd0c0100e..12c4a518ee 100644 --- a/website/docs/guides/docs/sidebar/items.mdx +++ b/website/docs/guides/docs/sidebar/items.mdx @@ -11,14 +11,14 @@ 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. +The sidebar supports various item types: - **[Doc](#sidebar-item-doc)**: link to a doc page, associating it with the sidebar - **[Link](#sidebar-item-link)**: link to any internal or external page - **[Category](#sidebar-item-category)**: creates a dropdown of sidebar items - **[Autogenerated](autogenerated.mdx)**: generate a sidebar slice automatically - **[HTML](#sidebar-item-html)**: renders pure HTML in the item's position -- **[\*Ref](multiple-sidebars.mdx#sidebar-item-ref)**: link to a doc page, without making the item take part in navigation generation +- **[Ref](multiple-sidebars.mdx#sidebar-item-ref)**: link to a doc page, without making the item take part in navigation generation ## Doc: link to a doc {#sidebar-item-doc} @@ -31,6 +31,7 @@ type SidebarItemDoc = type: 'doc'; id: string; label: string; // Sidebar label text + key?: string; // Sidebar key to uniquely identify the item className?: string; // Class name for sidebar label customProps?: Record; // Custom props } @@ -84,8 +85,10 @@ type SidebarItemLink = { type: 'link'; label: string; href: string; - className?: string; description?: string; + key?: string; + className?: string; + customProps?: Record; }; ``` @@ -126,7 +129,9 @@ type SidebarItemHtml = { type: 'html'; value: string; defaultStyle?: boolean; // Use default menu item styles + key?: string; className?: string; + customProps?: Record; }; ``` @@ -173,8 +178,10 @@ type SidebarItemCategory = { type: 'category'; label: string; // Sidebar label text. items: SidebarItem[]; // Array of sidebar items. - className?: string; description?: string; + key?: string; + className?: string; + customProps?: Record; // Category options: collapsible: boolean; // Set the category to be collapsible From fad80c4421d6fb74bd0aac18aca3bf4f528b5e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 4 Jul 2025 15:14:17 +0200 Subject: [PATCH 030/103] test(docs): fix docs tests issues (#11307) --- packages/docusaurus-plugin-content-docs/src/index.ts | 6 ++++++ .../src/versions/loadVersion.ts | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index d20a88185a..317dadbad0 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -62,6 +62,12 @@ async function createMdxLoaderDependencyFile({ options: PluginOptions; versionsMetadata: VersionMetadata[]; }): Promise { + // Disabled for unit tests, the side effect produces infinite watch loops + // TODO find a better way :/ + if (process.env.NODE_ENV === 'test') { + return undefined; + } + const filePath = path.join(dataDir, '__mdx-loader-dependency.json'); // the cache is invalidated whenever this file content changes const fileContent = { diff --git a/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts b/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts index 061f2d53ad..c47dde2ef4 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/loadVersion.ts @@ -38,6 +38,12 @@ type LoadVersionParams = { function ensureNoDuplicateDocId(docs: DocMetadataBase[]): void { const duplicatesById = _.chain(docs) + .sort((d1, d2) => { + // Need to sort because Globby order is non-deterministic + // TODO maybe we should create a deterministic glob utils? + // see https://github.com/sindresorhus/globby/issues/131 + return d1.source.localeCompare(d2.source); + }) .groupBy((d) => d.id) .pickBy((group) => group.length > 1) .value(); From 4c3daab18be51e40571c4ec58a3ec0fb6dfa1ec5 Mon Sep 17 00:00:00 2001 From: Sergey Schetinin Date: Fri, 4 Jul 2025 16:20:16 +0300 Subject: [PATCH 031/103] fix(translations): Add missing Ukrainian translations (#11305) --- .../locales/uk/theme-common.json | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/docusaurus-theme-translations/locales/uk/theme-common.json b/packages/docusaurus-theme-translations/locales/uk/theme-common.json index 4437745d5c..72ee02cdf7 100644 --- a/packages/docusaurus-theme-translations/locales/uk/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/uk/theme-common.json @@ -5,11 +5,11 @@ "theme.CodeBlock.copy": "Копіювати", "theme.CodeBlock.copyButtonAriaLabel": "Копіювати в буфер обміну", "theme.CodeBlock.wordWrapToggle": "Перемикання обведення слів", - "theme.DocSidebarItem.collapseCategoryAriaLabel": "Collapse sidebar category '{label}'", - "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", + "theme.DocSidebarItem.collapseCategoryAriaLabel": "Згорнути категорію в сайдбарі '{label}'", + "theme.DocSidebarItem.expandCategoryAriaLabel": "Розгорнути категорію в сайдбарі '{label}'", "theme.ErrorPageContent.title": "На сторінці стався збій.", "theme.ErrorPageContent.tryAgain": "Спробуйте ще раз", - "theme.NavBar.navAriaLabel": "Main", + "theme.NavBar.navAriaLabel": "Головна", "theme.NotFound.p1": "На жаль, ми не змогли знайти сторінку, яку ви запитували.", "theme.NotFound.p2": "Будь ласка, зверніться до власника сайту, з якого ви перейшли на це посилання, щоб повідомити, що посилання не працює.", "theme.NotFound.title": "Сторінку не знайдено", @@ -19,13 +19,13 @@ "theme.admonition.info": "інформація", "theme.admonition.note": "примітка", "theme.admonition.tip": "порада", - "theme.admonition.warning": "warning", + "theme.admonition.warning": "попередження", "theme.blog.archive.description": "Архів", "theme.blog.archive.title": "Архів", - "theme.blog.author.noPosts": "This author has not written any posts yet.", + "theme.blog.author.noPosts": "Цей автор ще не написав жодної публікації.", "theme.blog.author.pageTitle": "{authorName} - {nPosts}", - "theme.blog.authorsList.pageTitle": "Authors", - "theme.blog.authorsList.viewAll": "View All Authors", + "theme.blog.authorsList.pageTitle": "Автори", + "theme.blog.authorsList.viewAll": "Переглянути всіх авторів", "theme.blog.paginator.navAriaLabel": "Навігація по сторінці списку блогів", "theme.blog.paginator.newerEntries": "Наступні записи", "theme.blog.paginator.olderEntries": "Попередні записи", @@ -41,27 +41,27 @@ "theme.colorToggle.ariaLabel": "Перемикання між темним та світлим режимом (зараз використовується {mode})", "theme.colorToggle.ariaLabel.mode.dark": "Темний режим", "theme.colorToggle.ariaLabel.mode.light": "Світлий режим", - "theme.colorToggle.ariaLabel.mode.system": "system mode", + "theme.colorToggle.ariaLabel.mode.system": "Автоматичний режим", "theme.common.editThisPage": "Відредагувати цю сторінку", "theme.common.headingLinkTitle": "Пряме посилання на {heading}", "theme.common.skipToMainContent": "Перейти до основного вмісту", - "theme.contentVisibility.draftBanner.message": "This page is a draft. It will only be visible in dev and be excluded from the production build.", - "theme.contentVisibility.draftBanner.title": "Draft page", - "theme.contentVisibility.unlistedBanner.message": "This page is unlisted. Search engines will not index it, and only users having a direct link can access it.", - "theme.contentVisibility.unlistedBanner.title": "Unlisted page", + "theme.contentVisibility.draftBanner.message": "Це чернетка. Ця сторінка видима лише в режимі розробки й буде виключена з фінальної збірки.", + "theme.contentVisibility.draftBanner.title": "Чернетка", + "theme.contentVisibility.unlistedBanner.message": "Ця сторінка є непублічною. Пошукові системи її не індексуватимуть, і доступ до неї матимуть лише користувачі з прямим посиланням.", + "theme.contentVisibility.unlistedBanner.title": "Непублічна сторінка", "theme.docs.DocCard.categoryDescription.plurals": "{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.closeSidebarButtonAriaLabel": "Close navigation bar", + "theme.docs.sidebar.closeSidebarButtonAriaLabel": "Закрити сайдбар", "theme.docs.sidebar.collapseButtonAriaLabel": "Згорнути сайдбар", "theme.docs.sidebar.collapseButtonTitle": "Згорнути сайдбар", "theme.docs.sidebar.expandButtonAriaLabel": "Розгорнути сайдбар", "theme.docs.sidebar.expandButtonTitle": "Розгорнути сайдбар", - "theme.docs.sidebar.navAriaLabel": "Docs sidebar", - "theme.docs.sidebar.toggleSidebarButtonAriaLabel": "Toggle navigation bar", + "theme.docs.sidebar.navAriaLabel": "Сайдбар документації", + "theme.docs.sidebar.toggleSidebarButtonAriaLabel": "Перемкнути сайдбар", "theme.docs.tagDocListPageTitle": "{nDocsTagged} з тегом \"{tagName}\"", "theme.docs.tagDocListPageTitle.nDocsTagged": "Одна сторінка|{count} сторінки|{count} сторінок", "theme.docs.versionBadge.label": "Версія: {versionLabel}", @@ -72,8 +72,8 @@ "theme.lastUpdated.atDate": " {date}", "theme.lastUpdated.byUser": " від {user}", "theme.lastUpdated.lastUpdatedAtBy": "Останнє оновлення{atDate}{byUser}", - "theme.navbar.mobileDropdown.collapseButton.collapseAriaLabel": "Collapse the dropdown", - "theme.navbar.mobileDropdown.collapseButton.expandAriaLabel": "Expand the dropdown", + "theme.navbar.mobileDropdown.collapseButton.collapseAriaLabel": "Згорнути випадаючий список", + "theme.navbar.mobileDropdown.collapseButton.expandAriaLabel": "Розгорнути випадаючий список", "theme.navbar.mobileLanguageDropdown.label": "Мови", "theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": "← Перейти до головного меню", "theme.navbar.mobileVersionsDropdown.label": "Версії", From e0524a5c845d221df2d617cd8a3a6616ac4e8128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Mon, 7 Jul 2025 12:04:30 +0200 Subject: [PATCH 032/103] docs(website): fix duplicate anchor id typo (#11311) --- website/docs/guides/docs/sidebar/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/guides/docs/sidebar/index.mdx b/website/docs/guides/docs/sidebar/index.mdx index 307d836fb3..82cf0499ae 100644 --- a/website/docs/guides/docs/sidebar/index.mdx +++ b/website/docs/guides/docs/sidebar/index.mdx @@ -191,7 +191,7 @@ To pass in custom props to a sidebar item, add the optional `customProps` object }; ``` -## Passing a unique key {#passing-custom-props} +## Passing a unique key {#passing-unique-key} Passing a unique `key` attribute can help uniquely identify a sidebar item. Sometimes other attributes (such as `label`) are not enough to distinguish two sidebar items from each other. From 1808945c1f9b6ab87b6d7e37c157951903690aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Mon, 7 Jul 2025 14:55:46 +0200 Subject: [PATCH 033/103] feat(core): add `i18n.localeConfigs.translate` + skip translation process if `i18n/` dir doesn't exist (#11304) --- .../src/__tests__/index.test.ts | 123 ++++++- .../src/blogUtils.ts | 4 +- .../src/index.ts | 14 +- .../__snapshots__/index.test.ts.snap | 57 --- .../src/__tests__/cli.test.ts | Bin 14956 -> 15340 bytes .../src/__tests__/docs.test.ts | 48 ++- .../src/__tests__/index.test.ts | 326 +++++++++++++----- .../docusaurus-plugin-content-docs/src/cli.ts | 4 +- .../src/docs.ts | 4 +- .../versions/__tests__/loadVersion.test.ts | 4 +- .../src/versions/__tests__/version.test.ts | 109 +++++- .../src/versions/files.ts | 21 +- .../src/versions/version.ts | 60 ++-- .../__snapshots__/index.test.ts.snap | 70 ++++ .../src/__tests__/index.test.ts | 19 + .../src/content.ts | 30 +- .../src/index.ts | 7 +- .../src/types.ts | 11 - packages/docusaurus-types/src/i18n.d.ts | 5 + .../src/__tests__/i18nUtils.test.ts | 78 ++++- .../docusaurus-utils/src/dataFileUtils.ts | 4 +- packages/docusaurus-utils/src/i18nUtils.ts | 16 + packages/docusaurus-utils/src/index.ts | 1 + .../docusaurus-utils/src/markdownLinks.ts | 6 +- .../docusaurus/src/commands/build/build.ts | 6 +- .../i18n/zh-Hans-custom/README.md | 1 + .../load-i18n-site/i18n/de/README.md | 1 + .../load-i18n-site/i18n/fr/README.md | 1 + .../__tests__/__snapshots__/site.test.ts.snap | 2 + .../src/server/__tests__/i18n.test.ts | 125 +++++-- packages/docusaurus/src/server/i18n.ts | 54 ++- .../server/plugins/__tests__/plugins.test.ts | 178 +++++++--- .../docusaurus/src/server/plugins/plugins.ts | 21 +- packages/docusaurus/src/server/site.ts | 9 +- packages/docusaurus/src/webpack/client.ts | 3 +- website/docs/api/docusaurus.config.js.mdx | 5 +- 36 files changed, 1061 insertions(+), 366 deletions(-) delete mode 100644 packages/docusaurus-plugin-content-pages/src/types.ts create mode 100644 packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site/i18n/zh-Hans-custom/README.md create mode 100644 packages/docusaurus/src/server/__tests__/__fixtures__/load-i18n-site/i18n/de/README.md create mode 100644 packages/docusaurus/src/server/__tests__/__fixtures__/load-i18n-site/i18n/fr/README.md diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts index ebbca9b18d..cfa1b0c9b5 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts @@ -6,12 +6,13 @@ */ import {jest} from '@jest/globals'; -import path from 'path'; +import * as path from 'path'; import {normalizePluginOptions} from '@docusaurus/utils-validation'; import { posixPath, getFileCommitDate, LAST_UPDATE_FALLBACK, + getLocaleConfig, } from '@docusaurus/utils'; import {DEFAULT_FUTURE_CONFIG} from '@docusaurus/core/src/server/configValidation'; import pluginContentBlog from '../index'; @@ -22,6 +23,7 @@ import type { I18n, Validate, MarkdownConfig, + I18nLocaleConfig, } from '@docusaurus/types'; import type { BlogPost, @@ -67,7 +69,10 @@ Available blog post titles are:\n- ${blogPosts return post; } -function getI18n(locale: string): I18n { +function getI18n( + locale: string, + localeConfigOptions?: Partial, +): I18n { return { currentLocale: locale, locales: [locale], @@ -80,6 +85,8 @@ function getI18n(locale: string): I18n { htmlLang: locale, direction: 'ltr', path: locale, + translate: true, + ...localeConfigOptions, }, }, }; @@ -94,13 +101,14 @@ const BaseEditUrl = 'https://baseEditUrl.com/edit'; const getPlugin = async ( siteDir: string, pluginOptions: Partial = {}, - i18n: I18n = DefaultI18N, + i18nOptions: Partial = {}, ) => { + const i18n = {...DefaultI18N, ...i18nOptions}; const generatedFilesDir: string = path.resolve(siteDir, '.docusaurus'); const localizationDir = path.join( siteDir, i18n.path, - i18n.localeConfigs[i18n.currentLocale]!.path, + getLocaleConfig(i18n).path, ); const siteConfig = { title: 'Hello', @@ -153,20 +161,34 @@ const getBlogTags = async ( }; describe('blog plugin', () => { - it('getPathsToWatch returns right files', async () => { - const siteDir = path.join(__dirname, '__fixtures__', 'website'); - const plugin = await getPlugin(siteDir); - const pathsToWatch = plugin.getPathsToWatch!(); - const relativePathsToWatch = pathsToWatch.map((p) => - posixPath(path.relative(siteDir, p)), - ); - expect(relativePathsToWatch).toEqual([ - 'i18n/en/docusaurus-plugin-content-blog/authors.yml', - 'i18n/en/docusaurus-plugin-content-blog/tags.yml', - 'blog/tags.yml', - 'i18n/en/docusaurus-plugin-content-blog/**/*.{md,mdx}', - 'blog/**/*.{md,mdx}', - ]); + describe('getPathsToWatch', () => { + async function runTest({translate}: {translate: boolean}) { + const siteDir = path.join(__dirname, '__fixtures__', 'website'); + const plugin = await getPlugin(siteDir, {}, getI18n('en', {translate})); + const pathsToWatch = plugin.getPathsToWatch!(); + return pathsToWatch.map((p) => posixPath(path.relative(siteDir, p))); + } + + it('getPathsToWatch returns right files', async () => { + const relativePathsToWatch = await runTest({translate: true}); + expect(relativePathsToWatch).toEqual([ + 'i18n/en/docusaurus-plugin-content-blog/authors.yml', + 'i18n/en/docusaurus-plugin-content-blog/tags.yml', + // 'blog/authors.yml', // TODO weird that it's not here but tags is? + 'blog/tags.yml', + 'i18n/en/docusaurus-plugin-content-blog/**/*.{md,mdx}', + 'blog/**/*.{md,mdx}', + ]); + }); + + it('getPathsToWatch returns right files (translate: false)', async () => { + const relativePathsToWatch = await runTest({translate: false}); + expect(relativePathsToWatch).toEqual([ + 'blog/authors.yml', + 'blog/tags.yml', + 'blog/**/*.{md,mdx}', + ]); + }); }); it('builds a simple website', async () => { @@ -377,6 +399,54 @@ describe('blog plugin', () => { }); }); + describe('i18n config translate is wired properly', () => { + async function runTest({translate}: {translate: boolean}) { + const siteDir = path.join(__dirname, '__fixtures__', 'website'); + const blogPosts = await getBlogPosts( + siteDir, + {}, + getI18n('en', {translate}), + ); + + // Simpler to snapshot + return blogPosts.map((post) => post.metadata.title); + } + + it('works with translate: false', async () => { + await expect(runTest({translate: false})).resolves.toMatchInlineSnapshot(` + [ + "test links", + "MDX Blog Sample with require calls", + "Full Blog Sample", + "Complex Slug", + "Simple Slug", + "draft", + "unlisted", + "some heading", + "date-matter", + "Happy 1st Birthday Slash!", + ] + `); + }); + + it('works with translate: true', async () => { + await expect(runTest({translate: true})).resolves.toMatchInlineSnapshot(` + [ + "test links", + "MDX Blog Sample with require calls", + "Full Blog Sample", + "Complex Slug", + "Simple Slug", + "draft", + "unlisted", + "some heading", + "date-matter", + "Happy 1st Birthday Slash! (translated)", + ] + `); + }); + }); + it('handles edit URL with editLocalizedBlogs: true', async () => { const siteDir = path.join(__dirname, '__fixtures__', 'website'); const blogPosts = await getBlogPosts(siteDir, {editLocalizedFiles: true}); @@ -390,6 +460,23 @@ describe('blog plugin', () => { ); }); + it('handles edit URL with editLocalizedBlogs: true and translate: false', async () => { + const siteDir = path.join(__dirname, '__fixtures__', 'website'); + const blogPosts = await getBlogPosts( + siteDir, + {editLocalizedFiles: true}, + getI18n('en', {translate: false}), + ); + + const localizedBlogPost = blogPosts.find( + (v) => v.metadata.title === 'Happy 1st Birthday Slash!', + )!; + + expect(localizedBlogPost.metadata.editUrl).toBe( + `${BaseEditUrl}/blog/2018-12-14-Happy-First-Birthday-Slash.md`, + ); + }); + it('handles edit URL with editUrl function', async () => { const siteDir = path.join(__dirname, '__fixtures__', 'website'); diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index cd3c1b8837..3647a34550 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -323,7 +323,9 @@ async function processBlogSourceFile( } else if (typeof editUrl === 'string') { const isLocalized = blogDirPath === contentPaths.contentPathLocalized; const fileContentPath = - isLocalized && options.editLocalizedFiles + isLocalized && + options.editLocalizedFiles && + contentPaths.contentPathLocalized ? contentPaths.contentPathLocalized : contentPaths.contentPath; diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index fe38ec471c..e19969ab22 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -19,6 +19,7 @@ import { getDataFilePath, DEFAULT_PLUGIN_ID, resolveMarkdownLinkPathname, + getLocaleConfig, } from '@docusaurus/utils'; import {getTagsFilePathsToWatch} from '@docusaurus/utils-validation'; import {createMDXLoaderItem} from '@docusaurus/mdx-loader'; @@ -73,13 +74,16 @@ export default async function pluginContentBlog( const {baseUrl} = siteConfig; + const shouldTranslate = getLocaleConfig(context.i18n).translate; const contentPaths: BlogContentPaths = { contentPath: path.resolve(siteDir, options.path), - contentPathLocalized: getPluginI18nPath({ - localizationDir, - pluginName: PluginName, - pluginId: options.id, - }), + contentPathLocalized: shouldTranslate + ? getPluginI18nPath({ + localizationDir, + pluginName: PluginName, + pluginId: options.id, + }) + : undefined, }; const pluginId = options.id ?? DEFAULT_PLUGIN_ID; 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 820c30fec3..c8692a5eb8 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 @@ -2005,17 +2005,6 @@ exports[`simple website content: route config 1`] = ` ] `; -exports[`simple website getPathToWatch 1`] = ` -[ - "sidebars.json", - "i18n/en/docusaurus-plugin-content-docs/current/**/*.{md,mdx}", - "docs/**/*.{md,mdx}", - "i18n/en/docusaurus-plugin-content-docs/current/tags.yml", - "docs/tags.yml", - "docs/**/_category_.{json,yml,yaml}", -] -`; - exports[`site with custom sidebar items generator sidebar is autogenerated according to a custom sidebarItemsGenerator 1`] = ` { "defaultSidebar": [ @@ -3327,23 +3316,6 @@ exports[`versioned website (community) content: route config 1`] = ` ] `; -exports[`versioned website (community) getPathToWatch 1`] = ` -[ - "community_sidebars.json", - "i18n/en/docusaurus-plugin-content-docs-community/current/**/*.{md,mdx}", - "community/**/*.{md,mdx}", - "i18n/en/docusaurus-plugin-content-docs-community/current/tags.yml", - "community/tags.yml", - "community/**/_category_.{json,yml,yaml}", - "community_versioned_sidebars/version-1.0.0-sidebars.json", - "i18n/en/docusaurus-plugin-content-docs-community/version-1.0.0/**/*.{md,mdx}", - "community_versioned_docs/version-1.0.0/**/*.{md,mdx}", - "i18n/en/docusaurus-plugin-content-docs-community/version-1.0.0/tags.yml", - "community_versioned_docs/version-1.0.0/tags.yml", - "community_versioned_docs/version-1.0.0/**/_category_.{json,yml,yaml}", -] -`; - exports[`versioned website content 1`] = ` { "description": "This is next version of bar.", @@ -5209,32 +5181,3 @@ exports[`versioned website content: withSlugs version sidebars 1`] = ` ], } `; - -exports[`versioned website getPathToWatch 1`] = ` -[ - "sidebars.json", - "i18n/en/docusaurus-plugin-content-docs/current/**/*.{md,mdx}", - "docs/**/*.{md,mdx}", - "i18n/en/docusaurus-plugin-content-docs/current/tags.yml", - "docs/tags.yml", - "docs/**/_category_.{json,yml,yaml}", - "versioned_sidebars/version-1.0.1-sidebars.json", - "i18n/en/docusaurus-plugin-content-docs/version-1.0.1/**/*.{md,mdx}", - "versioned_docs/version-1.0.1/**/*.{md,mdx}", - "i18n/en/docusaurus-plugin-content-docs/version-1.0.1/tags.yml", - "versioned_docs/version-1.0.1/tags.yml", - "versioned_docs/version-1.0.1/**/_category_.{json,yml,yaml}", - "versioned_sidebars/version-1.0.0-sidebars.json", - "i18n/en/docusaurus-plugin-content-docs/version-1.0.0/**/*.{md,mdx}", - "versioned_docs/version-1.0.0/**/*.{md,mdx}", - "i18n/en/docusaurus-plugin-content-docs/version-1.0.0/tags.yml", - "versioned_docs/version-1.0.0/tags.yml", - "versioned_docs/version-1.0.0/**/_category_.{json,yml,yaml}", - "versioned_sidebars/version-withSlugs-sidebars.json", - "i18n/en/docusaurus-plugin-content-docs/version-withSlugs/**/*.{md,mdx}", - "versioned_docs/version-withSlugs/**/*.{md,mdx}", - "i18n/en/docusaurus-plugin-content-docs/version-withSlugs/tags.yml", - "versioned_docs/version-withSlugs/tags.yml", - "versioned_docs/version-withSlugs/**/_category_.{json,yml,yaml}", -] -`; diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/cli.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/cli.test.ts index c8c28dfca3adea1f1df04e3e2fcc71c6b5ce9e4a..98d73c52eabf5f619895347aa2b768a29f4105bd 100644 GIT binary patch delta 331 zcmaD;@}_(Przl%;X;D#X-sBG=j+1#*xF?IM2#BleD3lZ><`w58mZVw%nWd?)X7$Vf2QO;4 delta 174 zcmaD;{-$IDr|4u2Q4PV=JS&Cjg2a*xD+Tq`JoQ?g$^6nXjJ1;$R7E%665Y)*S;t%r zry_0D;LWq7<%9?*%A71`;XnDjzS-so{q5`^#Yz~~Dx?)59FkU~UOQP^HFL9^#W`jG D>+Lrf diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts index 6b1815ee25..56422102c8 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts @@ -13,6 +13,7 @@ import { posixPath, DEFAULT_PLUGIN_ID, LAST_UPDATE_FALLBACK, + getLocaleConfig, } from '@docusaurus/utils'; import {getTagsFile} from '@docusaurus/utils-validation'; import {createSidebarsUtils} from '../sidebars/utils'; @@ -842,7 +843,11 @@ describe('simple site', () => { describe('versioned site', () => { async function loadSite( - loadSiteOptions: {options: Partial; locale?: string} = { + loadSiteOptions: { + options?: Partial; + locale?: string; + translate?: boolean; + } = { options: {}, }, ) { @@ -851,6 +856,10 @@ describe('versioned site', () => { siteDir, locale: loadSiteOptions.locale, }); + + // hacky but gets the job done + getLocaleConfig(context.i18n).translate = loadSiteOptions.translate ?? true; + const options = { id: DEFAULT_PLUGIN_ID, ...DEFAULT_OPTIONS, @@ -1055,6 +1064,43 @@ describe('versioned site', () => { }); }); + it('versioned docs - translate: false', async () => { + const {version100TestUtils} = await loadSite({ + translate: false, + }); + + // This doc is translated, but we still read the original + await version100TestUtils.testMeta(path.join('hello.md'), { + id: 'hello', + sourceDirName: '.', + permalink: '/docs/1.0.0/', + slug: '/', + title: 'hello', + description: 'Hello 1.0.0 !', + frontMatter: { + slug: '/', + tags: ['inlineTag-v1.0.0', 'globalTag-v1.0.0'], + }, + version: '1.0.0', + source: '@site/versioned_docs/version-1.0.0/hello.md', + tags: [ + { + description: undefined, + inline: true, + label: 'inlineTag-v1.0.0', + permalink: '/docs/1.0.0/tags/inline-tag-v-1-0-0', + }, + { + description: 'globalTag-v1.0.0 description', + inline: false, + label: 'globalTag-v1.0.0 label', + permalink: '/docs/1.0.0/tags/globalTag-v1.0.0 permalink', + }, + ], + unlisted: false, + }); + }); + it('next doc slugs', async () => { const {currentVersionTestUtils} = await loadSite(); 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 fb1180159f..26594bc95d 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts @@ -18,7 +18,7 @@ import { createConfigureWebpackUtils, } from '@docusaurus/core/src/webpack/configure'; import {sortRoutes} from '@docusaurus/core/src/server/plugins/routeConfig'; -import {posixPath} from '@docusaurus/utils'; +import {getLocaleConfig, posixPath} from '@docusaurus/utils'; import {normalizePluginOptions} from '@docusaurus/utils-validation'; import {fromPartial} from '@total-typescript/shoehorn'; @@ -219,9 +219,13 @@ describe('empty/no docs website', () => { }); describe('simple website', () => { - async function loadSite() { + async function loadSite({translate}: {translate?: boolean} = {}) { const siteDir = path.join(__dirname, '__fixtures__', 'simple-site'); const context = await loadContext({siteDir}); + + // hacky but gets the job done + getLocaleConfig(context.i18n).translate = translate ?? true; + const sidebarPath = path.join(siteDir, 'sidebars.json'); const options = validateOptions({ validate: normalizePluginOptions as Validate, @@ -233,7 +237,20 @@ describe('simple website', () => { const plugin = await pluginContentDocs(context, options); const pluginContentDir = path.join(context.generatedFilesDir, plugin.name); - return {siteDir, context, sidebarPath, plugin, options, pluginContentDir}; + return { + siteDir, + context, + sidebarPath, + plugin, + options, + pluginContentDir, + getPathsToWatch: () => { + const pathToWatch = plugin.getPathsToWatch!(); + return pathToWatch.map((filepath) => + posixPath(path.relative(siteDir, filepath)), + ); + }, + }; } it('extendCli - docsVersion', async () => { @@ -242,8 +259,6 @@ describe('simple website', () => { .spyOn(cliDocs, 'cliDocsVersionCommand') .mockImplementation(async () => {}); const cli = new commander.Command(); - // @ts-expect-error: in actual usage, we pass the static commander instead - // of the new command plugin.extendCli!(cli); cli.parse(['node', 'test', 'docs:version', '1.0.0']); expect(mock).toHaveBeenCalledTimes(1); @@ -251,25 +266,48 @@ describe('simple website', () => { mock.mockRestore(); }); - it('getPathToWatch', async () => { - const {siteDir, plugin} = await loadSite(); + describe('getPathToWatch', () => { + it('translate: false', async () => { + const {getPathsToWatch} = await loadSite({translate: false}); + expect(getPathsToWatch()).toMatchInlineSnapshot(` + [ + "sidebars.json", + "docs/**/*.{md,mdx}", + "docs/tags.yml", + "docs/**/_category_.{json,yml,yaml}", + ] + `); + }); - const pathToWatch = plugin.getPathsToWatch!(); - const matchPattern = pathToWatch.map((filepath) => - posixPath(path.relative(siteDir, filepath)), - ); - expect(matchPattern).toMatchSnapshot(); - expect(isMatch('docs/hello.md', matchPattern)).toBe(true); - expect(isMatch('docs/hello.mdx', matchPattern)).toBe(true); - expect(isMatch('docs/foo/bar.md', matchPattern)).toBe(true); - expect(isMatch('docs/hello.js', matchPattern)).toBe(false); - expect(isMatch('docs/super.mdl', matchPattern)).toBe(false); - expect(isMatch('docs/mdx', matchPattern)).toBe(false); - expect(isMatch('docs/headingAsTitle.md', matchPattern)).toBe(true); - expect(isMatch('sidebars.json', matchPattern)).toBe(true); - expect(isMatch('versioned_docs/hello.md', matchPattern)).toBe(false); - expect(isMatch('hello.md', matchPattern)).toBe(false); - expect(isMatch('super/docs/hello.md', matchPattern)).toBe(false); + it('translate: true', async () => { + const {getPathsToWatch} = await loadSite({translate: true}); + expect(getPathsToWatch()).toMatchInlineSnapshot(` + [ + "sidebars.json", + "i18n/en/docusaurus-plugin-content-docs/current/**/*.{md,mdx}", + "docs/**/*.{md,mdx}", + "i18n/en/docusaurus-plugin-content-docs/current/tags.yml", + "docs/tags.yml", + "docs/**/_category_.{json,yml,yaml}", + ] + `); + }); + + it('returns patterns matching docs', async () => { + const {getPathsToWatch} = await loadSite(); + const matchPattern = getPathsToWatch(); + expect(isMatch('docs/hello.md', matchPattern)).toBe(true); + expect(isMatch('docs/hello.mdx', matchPattern)).toBe(true); + expect(isMatch('docs/foo/bar.md', matchPattern)).toBe(true); + expect(isMatch('docs/hello.js', matchPattern)).toBe(false); + expect(isMatch('docs/super.mdl', matchPattern)).toBe(false); + expect(isMatch('docs/mdx', matchPattern)).toBe(false); + expect(isMatch('docs/headingAsTitle.md', matchPattern)).toBe(true); + expect(isMatch('sidebars.json', matchPattern)).toBe(true); + expect(isMatch('versioned_docs/hello.md', matchPattern)).toBe(false); + expect(isMatch('hello.md', matchPattern)).toBe(false); + expect(isMatch('super/docs/hello.md', matchPattern)).toBe(false); + }); }); it('configureWebpack', async () => { @@ -329,9 +367,13 @@ describe('simple website', () => { }); describe('versioned website', () => { - async function loadSite() { + async function loadSite({translate}: {translate?: boolean} = {}) { const siteDir = path.join(__dirname, '__fixtures__', 'versioned-site'); const context = await loadContext({siteDir}); + + // hacky but gets the job done + getLocaleConfig(context.i18n).translate = translate ?? true; + const sidebarPath = path.join(siteDir, 'sidebars.json'); const routeBasePath = 'docs'; const options = validateOptions({ @@ -356,6 +398,13 @@ describe('versioned website', () => { options, plugin, pluginContentDir, + + getPathsToWatch: () => { + const pathToWatch = plugin.getPathsToWatch!(); + return pathToWatch.map((filepath) => + posixPath(path.relative(siteDir, filepath)), + ); + }, }; } @@ -365,8 +414,6 @@ describe('versioned website', () => { .spyOn(cliDocs, 'cliDocsVersionCommand') .mockImplementation(async () => {}); const cli = new commander.Command(); - // @ts-expect-error: in actual usage, we pass the static commander instead - // of the new command plugin.extendCli!(cli); cli.parse(['node', 'test', 'docs:version', '2.0.0']); expect(mock).toHaveBeenCalledTimes(1); @@ -374,48 +421,101 @@ describe('versioned website', () => { mock.mockRestore(); }); - it('getPathToWatch', async () => { - const {siteDir, plugin} = await loadSite(); - const pathToWatch = plugin.getPathsToWatch!(); - const matchPattern = pathToWatch.map((filepath) => - posixPath(path.relative(siteDir, filepath)), - ); - expect(matchPattern).not.toEqual([]); - expect(matchPattern).toMatchSnapshot(); - expect(isMatch('docs/hello.md', matchPattern)).toBe(true); - expect(isMatch('docs/hello.mdx', matchPattern)).toBe(true); - expect(isMatch('docs/foo/bar.md', matchPattern)).toBe(true); - expect(isMatch('sidebars.json', matchPattern)).toBe(true); - expect(isMatch('versioned_docs/version-1.0.0/hello.md', matchPattern)).toBe( - true, - ); - expect( - isMatch('versioned_docs/version-1.0.0/foo/bar.md', matchPattern), - ).toBe(true); - expect( - isMatch('versioned_sidebars/version-1.0.0-sidebars.json', matchPattern), - ).toBe(true); + describe('getPathToWatch', () => { + it('translate: false', async () => { + const {getPathsToWatch} = await loadSite({translate: false}); + expect(getPathsToWatch()).toMatchInlineSnapshot(` + [ + "sidebars.json", + "docs/**/*.{md,mdx}", + "docs/tags.yml", + "docs/**/_category_.{json,yml,yaml}", + "versioned_sidebars/version-1.0.1-sidebars.json", + "versioned_docs/version-1.0.1/**/*.{md,mdx}", + "versioned_docs/version-1.0.1/tags.yml", + "versioned_docs/version-1.0.1/**/_category_.{json,yml,yaml}", + "versioned_sidebars/version-1.0.0-sidebars.json", + "versioned_docs/version-1.0.0/**/*.{md,mdx}", + "versioned_docs/version-1.0.0/tags.yml", + "versioned_docs/version-1.0.0/**/_category_.{json,yml,yaml}", + "versioned_sidebars/version-withSlugs-sidebars.json", + "versioned_docs/version-withSlugs/**/*.{md,mdx}", + "versioned_docs/version-withSlugs/tags.yml", + "versioned_docs/version-withSlugs/**/_category_.{json,yml,yaml}", + ] + `); + }); - // Non existing version - expect( - isMatch('versioned_docs/version-2.0.0/foo/bar.md', matchPattern), - ).toBe(false); - expect(isMatch('versioned_docs/version-2.0.0/hello.md', matchPattern)).toBe( - false, - ); - expect( - isMatch('versioned_sidebars/version-2.0.0-sidebars.json', matchPattern), - ).toBe(false); + it('translate: true', async () => { + const {getPathsToWatch} = await loadSite({translate: true}); + expect(getPathsToWatch()).toMatchInlineSnapshot(` + [ + "sidebars.json", + "i18n/en/docusaurus-plugin-content-docs/current/**/*.{md,mdx}", + "docs/**/*.{md,mdx}", + "i18n/en/docusaurus-plugin-content-docs/current/tags.yml", + "docs/tags.yml", + "docs/**/_category_.{json,yml,yaml}", + "versioned_sidebars/version-1.0.1-sidebars.json", + "i18n/en/docusaurus-plugin-content-docs/version-1.0.1/**/*.{md,mdx}", + "versioned_docs/version-1.0.1/**/*.{md,mdx}", + "i18n/en/docusaurus-plugin-content-docs/version-1.0.1/tags.yml", + "versioned_docs/version-1.0.1/tags.yml", + "versioned_docs/version-1.0.1/**/_category_.{json,yml,yaml}", + "versioned_sidebars/version-1.0.0-sidebars.json", + "i18n/en/docusaurus-plugin-content-docs/version-1.0.0/**/*.{md,mdx}", + "versioned_docs/version-1.0.0/**/*.{md,mdx}", + "i18n/en/docusaurus-plugin-content-docs/version-1.0.0/tags.yml", + "versioned_docs/version-1.0.0/tags.yml", + "versioned_docs/version-1.0.0/**/_category_.{json,yml,yaml}", + "versioned_sidebars/version-withSlugs-sidebars.json", + "i18n/en/docusaurus-plugin-content-docs/version-withSlugs/**/*.{md,mdx}", + "versioned_docs/version-withSlugs/**/*.{md,mdx}", + "i18n/en/docusaurus-plugin-content-docs/version-withSlugs/tags.yml", + "versioned_docs/version-withSlugs/tags.yml", + "versioned_docs/version-withSlugs/**/_category_.{json,yml,yaml}", + ] + `); + }); - expect(isMatch('docs/hello.js', matchPattern)).toBe(false); - expect(isMatch('docs/super.mdl', matchPattern)).toBe(false); - expect(isMatch('docs/mdx', matchPattern)).toBe(false); - expect(isMatch('hello.md', matchPattern)).toBe(false); - expect(isMatch('super/docs/hello.md', matchPattern)).toBe(false); + it('returns patterns matching docs', async () => { + const {getPathsToWatch} = await loadSite(); + const matchPattern = getPathsToWatch(); + expect(isMatch('docs/hello.md', matchPattern)).toBe(true); + expect(isMatch('docs/hello.mdx', matchPattern)).toBe(true); + expect(isMatch('docs/foo/bar.md', matchPattern)).toBe(true); + expect(isMatch('sidebars.json', matchPattern)).toBe(true); + expect( + isMatch('versioned_docs/version-1.0.0/hello.md', matchPattern), + ).toBe(true); + expect( + isMatch('versioned_docs/version-1.0.0/foo/bar.md', matchPattern), + ).toBe(true); + expect( + isMatch('versioned_sidebars/version-1.0.0-sidebars.json', matchPattern), + ).toBe(true); + + // Non existing version + expect( + isMatch('versioned_docs/version-2.0.0/foo/bar.md', matchPattern), + ).toBe(false); + expect( + isMatch('versioned_docs/version-2.0.0/hello.md', matchPattern), + ).toBe(false); + expect( + isMatch('versioned_sidebars/version-2.0.0-sidebars.json', matchPattern), + ).toBe(false); + + expect(isMatch('docs/hello.js', matchPattern)).toBe(false); + expect(isMatch('docs/super.mdl', matchPattern)).toBe(false); + expect(isMatch('docs/mdx', matchPattern)).toBe(false); + expect(isMatch('hello.md', matchPattern)).toBe(false); + expect(isMatch('super/docs/hello.md', matchPattern)).toBe(false); + }); }); it('content', async () => { - const {plugin, pluginContentDir} = await loadSite(); + const {plugin, pluginContentDir} = await loadSite({translate: true}); const content = await plugin.loadContent!(); expect(content.loadedVersions).toHaveLength(4); const [currentVersion, version101, version100, versionWithSlugs] = @@ -453,9 +553,13 @@ describe('versioned website', () => { }); describe('versioned website (community)', () => { - async function loadSite() { + async function loadSite({translate}: {translate?: boolean} = {}) { const siteDir = path.join(__dirname, '__fixtures__', 'versioned-site'); const context = await loadContext({siteDir}); + + // hacky but gets the job done + getLocaleConfig(context.i18n).translate = translate ?? true; + const sidebarPath = path.join(siteDir, 'community_sidebars.json'); const routeBasePath = 'community'; const pluginId = 'community'; @@ -479,6 +583,13 @@ describe('versioned website (community)', () => { options, plugin, pluginContentDir, + + getPathsToWatch: () => { + const pathToWatch = plugin.getPathsToWatch!(); + return pathToWatch.map((filepath) => + posixPath(path.relative(siteDir, filepath)), + ); + }, }; } @@ -488,8 +599,6 @@ describe('versioned website (community)', () => { .spyOn(cliDocs, 'cliDocsVersionCommand') .mockImplementation(async () => {}); const cli = new commander.Command(); - // @ts-expect-error: in actual usage, we pass the static commander instead - // of the new command plugin.extendCli!(cli); cli.parse(['node', 'test', `docs:version:${pluginId}`, '2.0.0']); expect(mock).toHaveBeenCalledTimes(1); @@ -497,34 +606,67 @@ describe('versioned website (community)', () => { mock.mockRestore(); }); - it('getPathToWatch', async () => { - const {siteDir, plugin} = await loadSite(); - const pathToWatch = plugin.getPathsToWatch!(); - const matchPattern = pathToWatch.map((filepath) => - posixPath(path.relative(siteDir, filepath)), - ); - expect(matchPattern).not.toEqual([]); - expect(matchPattern).toMatchSnapshot(); - expect(isMatch('community/team.md', matchPattern)).toBe(true); - expect( - isMatch('community_versioned_docs/version-1.0.0/team.md', matchPattern), - ).toBe(true); + describe('getPathToWatch', () => { + it('translate: false', async () => { + const {getPathsToWatch} = await loadSite({translate: false}); + expect(getPathsToWatch()).toMatchInlineSnapshot(` + [ + "community_sidebars.json", + "community/**/*.{md,mdx}", + "community/tags.yml", + "community/**/_category_.{json,yml,yaml}", + "community_versioned_sidebars/version-1.0.0-sidebars.json", + "community_versioned_docs/version-1.0.0/**/*.{md,mdx}", + "community_versioned_docs/version-1.0.0/tags.yml", + "community_versioned_docs/version-1.0.0/**/_category_.{json,yml,yaml}", + ] + `); + }); - // Non existing version - expect( - isMatch('community_versioned_docs/version-2.0.0/team.md', matchPattern), - ).toBe(false); - expect( - isMatch( - 'community_versioned_sidebars/version-2.0.0-sidebars.json', - matchPattern, - ), - ).toBe(false); + it('translate: true', async () => { + const {getPathsToWatch} = await loadSite({translate: true}); + expect(getPathsToWatch()).toMatchInlineSnapshot(` + [ + "community_sidebars.json", + "i18n/en/docusaurus-plugin-content-docs-community/current/**/*.{md,mdx}", + "community/**/*.{md,mdx}", + "i18n/en/docusaurus-plugin-content-docs-community/current/tags.yml", + "community/tags.yml", + "community/**/_category_.{json,yml,yaml}", + "community_versioned_sidebars/version-1.0.0-sidebars.json", + "i18n/en/docusaurus-plugin-content-docs-community/version-1.0.0/**/*.{md,mdx}", + "community_versioned_docs/version-1.0.0/**/*.{md,mdx}", + "i18n/en/docusaurus-plugin-content-docs-community/version-1.0.0/tags.yml", + "community_versioned_docs/version-1.0.0/tags.yml", + "community_versioned_docs/version-1.0.0/**/_category_.{json,yml,yaml}", + ] + `); + }); - expect(isMatch('community/team.js', matchPattern)).toBe(false); - expect( - isMatch('community_versioned_docs/version-1.0.0/team.js', matchPattern), - ).toBe(false); + it('returns patterns matching docs', async () => { + const {getPathsToWatch} = await loadSite(); + const matchPattern = getPathsToWatch(); + expect(isMatch('community/team.md', matchPattern)).toBe(true); + expect( + isMatch('community_versioned_docs/version-1.0.0/team.md', matchPattern), + ).toBe(true); + + // Non existing version + expect( + isMatch('community_versioned_docs/version-2.0.0/team.md', matchPattern), + ).toBe(false); + expect( + isMatch( + 'community_versioned_sidebars/version-2.0.0-sidebars.json', + matchPattern, + ), + ).toBe(false); + + expect(isMatch('community/team.js', matchPattern)).toBe(false); + expect( + isMatch('community_versioned_docs/version-1.0.0/team.js', matchPattern), + ).toBe(false); + }); }); it('content', async () => { diff --git a/packages/docusaurus-plugin-content-docs/src/cli.ts b/packages/docusaurus-plugin-content-docs/src/cli.ts index e66e910ebc..d19d3f5fbd 100644 --- a/packages/docusaurus-plugin-content-docs/src/cli.ts +++ b/packages/docusaurus-plugin-content-docs/src/cli.ts @@ -8,7 +8,7 @@ import fs from 'fs-extra'; import path from 'path'; import logger from '@docusaurus/logger'; -import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils'; +import {DEFAULT_PLUGIN_ID, getLocaleConfig} from '@docusaurus/utils'; import { getVersionsFilePath, getVersionDocsDirPath, @@ -89,7 +89,7 @@ async function cliDocsVersionCommand( const localizationDir = path.resolve( siteDir, i18n.path, - i18n.localeConfigs[locale]!.path, + getLocaleConfig(i18n, locale).path, ); // Copy docs files. const docsDir = diff --git a/packages/docusaurus-plugin-content-docs/src/docs.ts b/packages/docusaurus-plugin-content-docs/src/docs.ts index e3eb7cc47f..352ccb3adb 100644 --- a/packages/docusaurus-plugin-content-docs/src/docs.ts +++ b/packages/docusaurus-plugin-content-docs/src/docs.ts @@ -196,7 +196,9 @@ async function doProcessDocMetadata({ locale: context.i18n.currentLocale, }); } else if (typeof options.editUrl === 'string') { - const isLocalized = contentPath === versionMetadata.contentPathLocalized; + const isLocalized = + typeof versionMetadata.contentPathLocalized !== 'undefined' && + contentPath === versionMetadata.contentPathLocalized; const baseVersionEditUrl = isLocalized && options.editLocalizedFiles ? versionMetadata.editUrlLocalized diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts index a4329f7a5c..442e4a43a5 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/loadVersion.test.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import path from 'path'; +import * as path from 'path'; import {fromPartial} from '@total-typescript/shoehorn'; import {DEFAULT_PARSE_FRONT_MATTER} from '@docusaurus/utils/src'; import {readVersionsMetadata} from '../version'; @@ -19,7 +19,7 @@ const DefaultI18N: I18n = { currentLocale: 'en', locales: ['en'], defaultLocale: 'en', - localeConfigs: {}, + localeConfigs: {en: fromPartial({translate: true})}, }; async function siteFixture(fixture: string) { diff --git a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/version.test.ts b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/version.test.ts index e4e53b58be..4109f7e72f 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/__tests__/version.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/__tests__/version.test.ts @@ -6,27 +6,44 @@ */ import {jest} from '@jest/globals'; -import path from 'path'; +import * as path from 'path'; import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils'; import {readVersionsMetadata} from '../version'; import {DEFAULT_OPTIONS} from '../../options'; -import type {I18n, LoadContext} from '@docusaurus/types'; +import type {I18n, I18nLocaleConfig, LoadContext} from '@docusaurus/types'; import type { PluginOptions, VersionMetadata, } from '@docusaurus/plugin-content-docs'; -const DefaultI18N: I18n = { - path: 'i18n', - currentLocale: 'en', - locales: ['en'], - defaultLocale: 'en', - localeConfigs: {}, -}; +function getI18n( + locale: string, + localeConfigOptions?: Partial, +): I18n { + return { + path: 'i18n', + currentLocale: locale, + locales: ['en'], + defaultLocale: locale, + localeConfigs: { + [locale]: { + path: locale, + label: locale, + translate: true, + calendar: 'calendar', + htmlLang: locale, + direction: 'rtl', + ...localeConfigOptions, + }, + }, + }; +} + +const DefaultI18N: I18n = getI18n('en'); describe('readVersionsMetadata', () => { describe('simple site', () => { - async function loadSite() { + async function loadSite({context}: {context?: Partial} = {}) { const simpleSiteDir = path.resolve( path.join(__dirname, '../../__tests__/__fixtures__', 'simple-site'), ); @@ -39,6 +56,7 @@ describe('readVersionsMetadata', () => { baseUrl: '/', i18n: DefaultI18N, localizationDir: path.join(simpleSiteDir, 'i18n/en'), + ...context, } as LoadContext; const vCurrent: VersionMetadata = { @@ -73,6 +91,26 @@ describe('readVersionsMetadata', () => { expect(versionsMetadata).toEqual([vCurrent]); }); + it('works with translate: false', async () => { + const {defaultOptions, defaultContext, vCurrent} = await loadSite({ + context: { + i18n: getI18n('en', {translate: false}), + }, + }); + + const versionsMetadata = await readVersionsMetadata({ + options: defaultOptions, + context: defaultContext, + }); + + expect(versionsMetadata).toEqual([ + { + ...vCurrent, + contentPathLocalized: undefined, + }, + ]); + }); + it('works with base url', async () => { const {defaultOptions, defaultContext, vCurrent} = await loadSite(); @@ -188,7 +226,7 @@ describe('readVersionsMetadata', () => { }); describe('versioned site, pluginId=default', () => { - async function loadSite() { + async function loadSite({context}: {context?: Partial} = {}) { const versionedSiteDir = path.resolve( path.join(__dirname, '../../__tests__/__fixtures__', 'versioned-site'), ); @@ -202,6 +240,7 @@ describe('readVersionsMetadata', () => { baseUrl: '/', i18n: DefaultI18N, localizationDir: path.join(versionedSiteDir, 'i18n/en'), + ...context, } as LoadContext; const vCurrent: VersionMetadata = { @@ -436,6 +475,54 @@ describe('readVersionsMetadata', () => { ]); }); + it('works with editUrl and translate=false', async () => { + const {defaultOptions, defaultContext, vCurrent, v101, v100, vWithSlugs} = + await loadSite({ + context: { + i18n: getI18n('en', {translate: false}), + }, + }); + + const versionsMetadata = await readVersionsMetadata({ + options: { + ...defaultOptions, + editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/', + }, + context: defaultContext, + }); + + expect(versionsMetadata).toEqual([ + { + ...vCurrent, + contentPathLocalized: undefined, + editUrl: + 'https://github.com/facebook/docusaurus/edit/main/website/docs', + editUrlLocalized: undefined, + }, + { + ...v101, + contentPathLocalized: undefined, + editUrl: + 'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-1.0.1', + editUrlLocalized: undefined, + }, + { + ...v100, + contentPathLocalized: undefined, + editUrl: + 'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-1.0.0', + editUrlLocalized: undefined, + }, + { + ...vWithSlugs, + contentPathLocalized: undefined, + editUrl: + 'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-withSlugs', + editUrlLocalized: undefined, + }, + ]); + }); + it('works with editUrl and editCurrentVersion=true', async () => { const {defaultOptions, defaultContext, vCurrent, v101, v100, vWithSlugs} = await loadSite(); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/files.ts b/packages/docusaurus-plugin-content-docs/src/versions/files.ts index 33839b9027..d7b8115432 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/files.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/files.ts @@ -7,7 +7,11 @@ import path from 'path'; import fs from 'fs-extra'; -import {getPluginI18nPath, DEFAULT_PLUGIN_ID} from '@docusaurus/utils'; +import { + getPluginI18nPath, + getLocaleConfig, + DEFAULT_PLUGIN_ID, +} from '@docusaurus/utils'; import { VERSIONS_JSON_FILE, VERSIONED_DOCS_DIR, @@ -186,11 +190,16 @@ export async function getVersionMetadataPaths({ > > { const isCurrent = versionName === CURRENT_VERSION_NAME; - const contentPathLocalized = getDocsDirPathLocalized({ - localizationDir: context.localizationDir, - pluginId: options.id, - versionName, - }); + + const shouldTranslate = getLocaleConfig(context.i18n).translate; + const contentPathLocalized = shouldTranslate + ? getDocsDirPathLocalized({ + localizationDir: context.localizationDir, + pluginId: options.id, + versionName, + }) + : undefined; + const contentPath = isCurrent ? path.resolve(context.siteDir, options.path) : getVersionDocsDirPath(context.siteDir, options.id, versionName); diff --git a/packages/docusaurus-plugin-content-docs/src/versions/version.ts b/packages/docusaurus-plugin-content-docs/src/versions/version.ts index 5b4ef5c043..a7f85ecbb6 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions/version.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions/version.ts @@ -50,33 +50,47 @@ function getVersionEditUrls({ return {editUrl: undefined, editUrlLocalized: undefined}; } - const editDirPath = options.editCurrentVersion ? options.path : contentPath; - const editDirPathLocalized = options.editCurrentVersion - ? getDocsDirPathLocalized({ - localizationDir: context.localizationDir, - versionName: CURRENT_VERSION_NAME, - pluginId: options.id, - }) - : contentPathLocalized; + // Intermediate var just to please TS not narrowing to "string" + const editUrlOption = options.editUrl; - const versionPathSegment = posixPath( - path.relative(context.siteDir, path.resolve(context.siteDir, editDirPath)), - ); - const versionPathSegmentLocalized = posixPath( - path.relative( - context.siteDir, - path.resolve(context.siteDir, editDirPathLocalized), - ), - ); + const getEditUrl = () => { + const editDirPath = options.editCurrentVersion ? options.path : contentPath; - const editUrl = normalizeUrl([options.editUrl, versionPathSegment]); + return normalizeUrl([ + editUrlOption, + posixPath( + path.relative( + context.siteDir, + path.resolve(context.siteDir, editDirPath), + ), + ), + ]); + }; - const editUrlLocalized = normalizeUrl([ - options.editUrl, - versionPathSegmentLocalized, - ]); + const getEditUrlLocalized = () => { + if (!contentPathLocalized) { + return undefined; + } + const editDirPathLocalized = options.editCurrentVersion + ? getDocsDirPathLocalized({ + localizationDir: context.localizationDir, + versionName: CURRENT_VERSION_NAME, + pluginId: options.id, + }) + : contentPathLocalized; - return {editUrl, editUrlLocalized}; + return normalizeUrl([ + editUrlOption, + posixPath( + path.relative( + context.siteDir, + path.resolve(context.siteDir, editDirPathLocalized), + ), + ), + ]); + }; + + return {editUrl: getEditUrl(), editUrlLocalized: getEditUrlLocalized()}; } /** diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap index ecb51dba22..4fb6568e8e 100644 --- a/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap @@ -70,6 +70,76 @@ exports[`docusaurus-plugin-content-pages loads simple pages 1`] = ` ] `; +exports[`docusaurus-plugin-content-pages loads simple pages with french translations (translate: false) 1`] = ` +[ + { + "permalink": "/fr/", + "source": "@site/src/pages/index.js", + "type": "jsx", + }, + { + "permalink": "/fr/typescript", + "source": "@site/src/pages/typescript.tsx", + "type": "jsx", + }, + { + "description": "Markdown index page", + "editUrl": undefined, + "frontMatter": { + "custom_frontMatter": "added by parseFrontMatter", + }, + "lastUpdatedAt": undefined, + "lastUpdatedBy": undefined, + "permalink": "/fr/hello/", + "source": "@site/src/pages/hello/index.md", + "title": "Index", + "type": "mdx", + "unlisted": false, + }, + { + "description": "my MDX page", + "editUrl": undefined, + "frontMatter": { + "custom_frontMatter": "added by parseFrontMatter", + "description": "my MDX page", + "slug": "/custom-mdx/slug", + "title": "MDX page", + }, + "lastUpdatedAt": undefined, + "lastUpdatedBy": undefined, + "permalink": "/fr/custom-mdx/slug", + "source": "@site/src/pages/hello/mdxPage.mdx", + "title": "MDX page", + "type": "mdx", + "unlisted": false, + }, + { + "permalink": "/fr/hello/translatedJs", + "source": "@site/src/pages/hello/translatedJs.js", + "type": "jsx", + }, + { + "description": "translated Markdown page", + "editUrl": undefined, + "frontMatter": { + "custom_frontMatter": "added by parseFrontMatter", + }, + "lastUpdatedAt": undefined, + "lastUpdatedBy": undefined, + "permalink": "/fr/hello/translatedMd", + "source": "@site/src/pages/hello/translatedMd.md", + "title": undefined, + "type": "mdx", + "unlisted": false, + }, + { + "permalink": "/fr/hello/world", + "source": "@site/src/pages/hello/world.js", + "type": "jsx", + }, +] +`; + exports[`docusaurus-plugin-content-pages loads simple pages with french translations 1`] = ` [ { diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-pages/src/__tests__/index.test.ts index b1f14ebcbb..91efb8c576 100644 --- a/packages/docusaurus-plugin-content-pages/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/index.test.ts @@ -47,6 +47,25 @@ describe('docusaurus-plugin-content-pages', () => { expect(pagesMetadata).toMatchSnapshot(); }); + it('loads simple pages with french translations (translate: false)', async () => { + const siteDir = path.join(__dirname, '__fixtures__', 'website'); + const context = await loadContext({siteDir, locale: 'fr'}); + context.i18n.localeConfigs.fr.translate = false; + + const plugin = await pluginContentPages( + context, + validateOptions({ + validate: normalizePluginOptions, + options: { + path: 'src/pages', + }, + }), + ); + const pagesMetadata = await plugin.loadContent!(); + + expect(pagesMetadata).toMatchSnapshot(); + }); + it('loads simple pages with last update', async () => { const siteDir = path.join(__dirname, '__fixtures__', 'website'); const context = await loadContext({siteDir}); diff --git a/packages/docusaurus-plugin-content-pages/src/content.ts b/packages/docusaurus-plugin-content-pages/src/content.ts index 97806bfb67..65f1d9b420 100644 --- a/packages/docusaurus-plugin-content-pages/src/content.ts +++ b/packages/docusaurus-plugin-content-pages/src/content.ts @@ -21,10 +21,12 @@ import { getEditUrl, posixPath, getPluginI18nPath, + getContentPathList, + getLocaleConfig, + type ContentPaths, } from '@docusaurus/utils'; import {validatePageFrontMatter} from './frontMatter'; import type {LoadContext} from '@docusaurus/types'; -import type {PagesContentPaths} from './types'; import type { PluginOptions, Metadata, @@ -37,29 +39,29 @@ export function createPagesContentPaths({ }: { context: LoadContext; options: PluginOptions; -}): PagesContentPaths { +}): ContentPaths { const {siteDir, localizationDir} = context; + + const shouldTranslate = getLocaleConfig(context.i18n).translate; return { contentPath: path.resolve(siteDir, options.path), - contentPathLocalized: getPluginI18nPath({ - localizationDir, - pluginName: 'docusaurus-plugin-content-pages', - pluginId: options.id, - }), + contentPathLocalized: shouldTranslate + ? getPluginI18nPath({ + localizationDir, + pluginName: 'docusaurus-plugin-content-pages', + pluginId: options.id, + }) + : undefined, }; } -export function getContentPathList(contentPaths: PagesContentPaths): string[] { - return [contentPaths.contentPathLocalized, contentPaths.contentPath]; -} - const isMarkdownSource = (source: string) => source.endsWith('.md') || source.endsWith('.mdx'); type LoadContentParams = { context: LoadContext; options: PluginOptions; - contentPaths: PagesContentPaths; + contentPaths: ContentPaths; }; export async function loadPagesContent( @@ -158,7 +160,9 @@ async function processPageSourceFile( } else if (typeof editUrl === 'string') { const isLocalized = pagesDirPath === contentPaths.contentPathLocalized; const fileContentPath = - isLocalized && options.editLocalizedFiles + isLocalized && + options.editLocalizedFiles && + contentPaths.contentPathLocalized ? contentPaths.contentPathLocalized : contentPaths.contentPath; diff --git a/packages/docusaurus-plugin-content-pages/src/index.ts b/packages/docusaurus-plugin-content-pages/src/index.ts index bb06e3adcd..aea10501f2 100644 --- a/packages/docusaurus-plugin-content-pages/src/index.ts +++ b/packages/docusaurus-plugin-content-pages/src/index.ts @@ -12,15 +12,12 @@ import { docuHash, addTrailingPathSeparator, createAbsoluteFilePathMatcher, + getContentPathList, DEFAULT_PLUGIN_ID, } from '@docusaurus/utils'; import {createMDXLoaderRule} from '@docusaurus/mdx-loader'; import {createAllRoutes} from './routes'; -import { - createPagesContentPaths, - getContentPathList, - loadPagesContent, -} from './content'; +import {createPagesContentPaths, loadPagesContent} from './content'; import type {LoadContext, Plugin} from '@docusaurus/types'; import type { PluginOptions, diff --git a/packages/docusaurus-plugin-content-pages/src/types.ts b/packages/docusaurus-plugin-content-pages/src/types.ts deleted file mode 100644 index 2d11492cb0..0000000000 --- a/packages/docusaurus-plugin-content-pages/src/types.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 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. - */ - -export type PagesContentPaths = { - contentPath: string; - contentPathLocalized: string; -}; diff --git a/packages/docusaurus-types/src/i18n.d.ts b/packages/docusaurus-types/src/i18n.d.ts index f8ddf15b83..ea834788e5 100644 --- a/packages/docusaurus-types/src/i18n.d.ts +++ b/packages/docusaurus-types/src/i18n.d.ts @@ -32,6 +32,11 @@ export type I18nLocaleConfig = { * name. */ path: string; + /** + * Should we attempt to translate this locale? + * By default, it will only be run if the `./i18n/` exists. + */ + translate: boolean; }; export type I18nConfig = { diff --git a/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts b/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts index 55c0b52e7c..527aa21379 100644 --- a/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts @@ -5,13 +5,15 @@ * LICENSE file in the root directory of this source tree. */ -import path from 'path'; +import * as path from 'path'; import { mergeTranslations, updateTranslationFileMessages, getPluginI18nPath, localizePath, + getLocaleConfig, } from '../i18nUtils'; +import type {I18n, I18nLocaleConfig} from '@docusaurus/types'; describe('mergeTranslations', () => { it('works', () => { @@ -179,3 +181,77 @@ describe('localizePath', () => { ).toBe('/baseUrl/'); }); }); + +describe('getLocaleConfig', () => { + const localeConfigEn: I18nLocaleConfig = { + path: 'path', + direction: 'rtl', + htmlLang: 'en', + calendar: 'calendar', + label: 'EN', + translate: true, + }; + const localeConfigFr: I18nLocaleConfig = { + path: 'path', + direction: 'rtl', + htmlLang: 'fr', + calendar: 'calendar', + label: 'FR', + translate: true, + }; + + function i18n(params: Partial): I18n { + return { + defaultLocale: 'en', + localeConfigs: {}, + locales: ['en'], + path: 'path', + currentLocale: 'en', + ...params, + }; + } + + it('returns single locale config', () => { + expect( + getLocaleConfig( + i18n({currentLocale: 'en', localeConfigs: {en: localeConfigEn}}), + ), + ).toEqual(localeConfigEn); + }); + + it('returns correct locale config among 2', () => { + expect( + getLocaleConfig( + i18n({ + currentLocale: 'fr', + localeConfigs: {en: localeConfigEn, fr: localeConfigFr}, + }), + ), + ).toEqual(localeConfigFr); + }); + + it('accepts locale to look for as param', () => { + expect( + getLocaleConfig( + i18n({ + currentLocale: 'fr', + localeConfigs: {en: localeConfigEn, fr: localeConfigFr}, + }), + 'en', + ), + ).toEqual(localeConfigEn); + }); + + it('throws for locale config that does not exist', () => { + expect(() => + getLocaleConfig( + i18n({ + currentLocale: 'fr', + localeConfigs: {en: localeConfigEn}, + }), + ), + ).toThrowErrorMatchingInlineSnapshot( + `"Can't find locale config for locale \`fr\`"`, + ); + }); +}); diff --git a/packages/docusaurus-utils/src/dataFileUtils.ts b/packages/docusaurus-utils/src/dataFileUtils.ts index decd57da94..8c07f2dd49 100644 --- a/packages/docusaurus-utils/src/dataFileUtils.ts +++ b/packages/docusaurus-utils/src/dataFileUtils.ts @@ -74,7 +74,9 @@ export async function readDataFile(params: DataFileParams): Promise { * in priority. */ export function getContentPathList(contentPaths: ContentPaths): string[] { - return [contentPaths.contentPathLocalized, contentPaths.contentPath]; + return [contentPaths.contentPathLocalized, contentPaths.contentPath].filter( + (p) => p !== undefined, + ); } /** diff --git a/packages/docusaurus-utils/src/i18nUtils.ts b/packages/docusaurus-utils/src/i18nUtils.ts index 15723648d7..8e7080b962 100644 --- a/packages/docusaurus-utils/src/i18nUtils.ts +++ b/packages/docusaurus-utils/src/i18nUtils.ts @@ -7,12 +7,14 @@ import path from 'path'; import _ from 'lodash'; +import logger from '@docusaurus/logger'; import {DEFAULT_PLUGIN_ID} from './constants'; import {normalizeUrl} from './urlUtils'; import type { TranslationFileContent, TranslationFile, I18n, + I18nLocaleConfig, } from '@docusaurus/types'; /** @@ -112,3 +114,17 @@ export function localizePath({ // Url paths; add a trailing slash so it's a valid base URL return normalizeUrl([originalPath, i18n.currentLocale, '/']); } + +// TODO we may extract this to a separate package +// we want to use it on the frontend too +// but "docusaurus-utils-common" (agnostic utils) is not an ideal place since +export function getLocaleConfig(i18n: I18n, locale?: string): I18nLocaleConfig { + const localeToLookFor = locale ?? i18n.currentLocale; + const localeConfig = i18n.localeConfigs[localeToLookFor]; + if (!localeConfig) { + throw new Error( + `Can't find locale config for locale ${logger.code(localeToLookFor)}`, + ); + } + return localeConfig; +} diff --git a/packages/docusaurus-utils/src/index.ts b/packages/docusaurus-utils/src/index.ts index a38a6def09..74b66ca3a9 100644 --- a/packages/docusaurus-utils/src/index.ts +++ b/packages/docusaurus-utils/src/index.ts @@ -34,6 +34,7 @@ export { updateTranslationFileMessages, getPluginI18nPath, localizePath, + getLocaleConfig, } from './i18nUtils'; export {mapAsyncSequential, findAsyncSequential} from './jsUtils'; export { diff --git a/packages/docusaurus-utils/src/markdownLinks.ts b/packages/docusaurus-utils/src/markdownLinks.ts index 1183656aa1..a045ab4cd5 100644 --- a/packages/docusaurus-utils/src/markdownLinks.ts +++ b/packages/docusaurus-utils/src/markdownLinks.ts @@ -20,9 +20,11 @@ export type ContentPaths = { contentPath: string; /** * The absolute path to the localized content directory, like - * `"/i18n/zh-Hans/plugin-content-docs"`. + * `"/i18n/zh-Hans/plugin-content-blog"`. + * + * Undefined when the locale has `translate: false` config */ - contentPathLocalized: string; + contentPathLocalized: string | undefined; }; /** Data structure representing each broken Markdown link to be reported. */ diff --git a/packages/docusaurus/src/commands/build/build.ts b/packages/docusaurus/src/commands/build/build.ts index 7efaa0ca1d..4bfea69201 100644 --- a/packages/docusaurus/src/commands/build/build.ts +++ b/packages/docusaurus/src/commands/build/build.ts @@ -91,7 +91,11 @@ async function getLocalesToBuild({ localizePath, }); - const i18n = await loadI18n(context.siteConfig); + const i18n = await loadI18n({ + siteDir, + config: context.siteConfig, + currentLocale: context.siteConfig.i18n.defaultLocale // Awkward but ok + }); const locales = cliOptions.locale ?? i18n.locales; diff --git a/packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site/i18n/zh-Hans-custom/README.md b/packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site/i18n/zh-Hans-custom/README.md new file mode 100644 index 0000000000..0d736fa79c --- /dev/null +++ b/packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site/i18n/zh-Hans-custom/README.md @@ -0,0 +1 @@ +Since i18n/zh-Hans-custom folder exists, zh-Hans locale should infer to translate = true diff --git a/packages/docusaurus/src/server/__tests__/__fixtures__/load-i18n-site/i18n/de/README.md b/packages/docusaurus/src/server/__tests__/__fixtures__/load-i18n-site/i18n/de/README.md new file mode 100644 index 0000000000..0d58ac5abf --- /dev/null +++ b/packages/docusaurus/src/server/__tests__/__fixtures__/load-i18n-site/i18n/de/README.md @@ -0,0 +1 @@ +Since i18n/de folder exists, de locale should infer to translate = true diff --git a/packages/docusaurus/src/server/__tests__/__fixtures__/load-i18n-site/i18n/fr/README.md b/packages/docusaurus/src/server/__tests__/__fixtures__/load-i18n-site/i18n/fr/README.md new file mode 100644 index 0000000000..8b313dec94 --- /dev/null +++ b/packages/docusaurus/src/server/__tests__/__fixtures__/load-i18n-site/i18n/fr/README.md @@ -0,0 +1 @@ +Since i18n/fr folder exists, fr locale should infer to translate = true diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap index 40c87e4b93..b15943ef82 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap @@ -20,6 +20,7 @@ exports[`load loads props for site with custom i18n path 1`] = ` "htmlLang": "en", "label": "English", "path": "en-custom", + "translate": false, }, "zh-Hans": { "calendar": "gregory", @@ -27,6 +28,7 @@ exports[`load loads props for site with custom i18n path 1`] = ` "htmlLang": "zh-Hans", "label": "简体中文", "path": "zh-Hans-custom", + "translate": true, }, }, "locales": [ diff --git a/packages/docusaurus/src/server/__tests__/i18n.test.ts b/packages/docusaurus/src/server/__tests__/i18n.test.ts index 205dc7b05c..fb075d8b2b 100644 --- a/packages/docusaurus/src/server/__tests__/i18n.test.ts +++ b/packages/docusaurus/src/server/__tests__/i18n.test.ts @@ -6,23 +6,33 @@ */ import {jest} from '@jest/globals'; +import path from 'path'; import {loadI18n, getDefaultLocaleConfig} from '../i18n'; import {DEFAULT_I18N_CONFIG} from '../configValidation'; import type {DocusaurusConfig, I18nConfig} from '@docusaurus/types'; -function testLocaleConfigsFor(locales: string[]) { - return Object.fromEntries( - locales.map((locale) => [locale, getDefaultLocaleConfig(locale)]), - ); -} +const loadI18nSiteDir = path.resolve( + __dirname, + '__fixtures__', + 'load-i18n-site', +); -function loadI18nTest(i18nConfig: I18nConfig, locale?: string) { - return loadI18n( - { +function loadI18nTest({ + siteDir = loadI18nSiteDir, + i18nConfig, + currentLocale, +}: { + siteDir?: string; + i18nConfig: I18nConfig; + currentLocale: string; +}) { + return loadI18n({ + siteDir, + config: { i18n: i18nConfig, } as DocusaurusConfig, - {locale}, - ); + currentLocale, + }); } describe('defaultLocaleConfig', () => { @@ -109,66 +119,106 @@ describe('loadI18n', () => { }); it('loads I18n for default config', async () => { - await expect(loadI18nTest(DEFAULT_I18N_CONFIG)).resolves.toEqual({ + await expect( + loadI18nTest({ + i18nConfig: DEFAULT_I18N_CONFIG, + currentLocale: 'en', + }), + ).resolves.toEqual({ path: 'i18n', defaultLocale: 'en', locales: ['en'], currentLocale: 'en', - localeConfigs: testLocaleConfigsFor(['en']), + localeConfigs: { + en: { + ...getDefaultLocaleConfig('en'), + translate: false, + }, + }, }); }); it('loads I18n for multi-lang config', async () => { await expect( loadI18nTest({ - path: 'i18n', - defaultLocale: 'fr', - locales: ['en', 'fr', 'de'], - localeConfigs: {}, + i18nConfig: { + path: 'i18n', + defaultLocale: 'fr', + locales: ['en', 'fr', 'de'], + localeConfigs: {}, + }, + currentLocale: 'fr', }), ).resolves.toEqual({ defaultLocale: 'fr', path: 'i18n', locales: ['en', 'fr', 'de'], currentLocale: 'fr', - localeConfigs: testLocaleConfigsFor(['en', 'fr', 'de']), + localeConfigs: { + en: { + ...getDefaultLocaleConfig('en'), + translate: false, + }, + fr: { + ...getDefaultLocaleConfig('fr'), + translate: true, + }, + de: { + ...getDefaultLocaleConfig('de'), + translate: true, + }, + }, }); }); it('loads I18n for multi-locale config with specified locale', async () => { await expect( - loadI18nTest( - { + loadI18nTest({ + i18nConfig: { path: 'i18n', defaultLocale: 'fr', locales: ['en', 'fr', 'de'], localeConfigs: {}, }, - 'de', - ), + currentLocale: 'de', + }), ).resolves.toEqual({ defaultLocale: 'fr', path: 'i18n', locales: ['en', 'fr', 'de'], currentLocale: 'de', - localeConfigs: testLocaleConfigsFor(['en', 'fr', 'de']), + localeConfigs: { + en: { + ...getDefaultLocaleConfig('en'), + translate: false, + }, + fr: { + ...getDefaultLocaleConfig('fr'), + translate: true, + }, + de: { + ...getDefaultLocaleConfig('de'), + translate: true, + }, + }, }); }); it('loads I18n for multi-locale config with some custom locale configs', async () => { await expect( - loadI18nTest( - { + loadI18nTest({ + i18nConfig: { path: 'i18n', defaultLocale: 'fr', locales: ['en', 'fr', 'de'], localeConfigs: { - fr: {label: 'Français'}, - en: {}, + fr: {label: 'Français', translate: false}, + en: {translate: true}, + de: {translate: false}, }, }, - 'de', - ), + currentLocale: 'de', + }), ).resolves.toEqual({ defaultLocale: 'fr', path: 'i18n', @@ -181,23 +231,30 @@ describe('loadI18n', () => { htmlLang: 'fr', calendar: 'gregory', path: 'fr', + translate: false, + }, + en: { + ...getDefaultLocaleConfig('en'), + translate: true, + }, + de: { + ...getDefaultLocaleConfig('de'), + translate: false, }, - en: getDefaultLocaleConfig('en'), - de: getDefaultLocaleConfig('de'), }, }); }); it('warns when trying to load undeclared locale', async () => { - await loadI18nTest( - { + await loadI18nTest({ + i18nConfig: { path: 'i18n', defaultLocale: 'fr', locales: ['en', 'fr', 'de'], localeConfigs: {}, }, - 'it', - ); + currentLocale: 'it', + }); expect(consoleSpy.mock.calls[0]![0]).toMatch( /The locale .*it.* was not found in your site configuration/, ); diff --git a/packages/docusaurus/src/server/i18n.ts b/packages/docusaurus/src/server/i18n.ts index a7b41de4c7..9d97140b3a 100644 --- a/packages/docusaurus/src/server/i18n.ts +++ b/packages/docusaurus/src/server/i18n.ts @@ -5,9 +5,11 @@ * LICENSE file in the root directory of this source tree. */ +import path from 'path'; +import fs from 'fs-extra'; import logger from '@docusaurus/logger'; +import combinePromises from 'combine-promises'; import type {I18n, DocusaurusConfig, I18nLocaleConfig} from '@docusaurus/types'; -import type {LoadContextParams} from './site'; function inferLanguageDisplayName(locale: string) { const tryLocale = (l: string) => { @@ -78,7 +80,9 @@ function getDefaultDirection(localeStr: string) { return textInto.direction; } -export function getDefaultLocaleConfig(locale: string): I18nLocaleConfig { +export function getDefaultLocaleConfig( + locale: string, +): Omit { try { return { label: getDefaultLocaleLabel(locale), @@ -95,14 +99,17 @@ export function getDefaultLocaleConfig(locale: string): I18nLocaleConfig { } } -export async function loadI18n( - config: DocusaurusConfig, - options?: Pick, -): Promise { +export async function loadI18n({ + siteDir, + config, + currentLocale, +}: { + siteDir: string; + config: DocusaurusConfig; + currentLocale: string; +}): Promise { const {i18n: i18nConfig} = config; - const currentLocale = options?.locale ?? i18nConfig.defaultLocale; - if (!i18nConfig.locales.includes(currentLocale)) { logger.warn`The locale name=${currentLocale} was not found in your site configuration: Available locales are: ${i18nConfig.locales} Note: Docusaurus only support running one locale at a time.`; @@ -112,15 +119,36 @@ Note: Docusaurus only support running one locale at a time.`; ? i18nConfig.locales : (i18nConfig.locales.concat(currentLocale) as [string, ...string[]]); - function getLocaleConfig(locale: string): I18nLocaleConfig { - return { + async function getFullLocaleConfig( + locale: string, + ): Promise { + const localeConfigInput = i18nConfig.localeConfigs[locale] ?? {}; + const localeConfig: Omit = { ...getDefaultLocaleConfig(locale), - ...i18nConfig.localeConfigs[locale], + ...localeConfigInput, + }; + + // By default, translations will be enabled if i18n/ dir exists + async function inferTranslate() { + const localizationDir = path.resolve( + siteDir, + i18nConfig.path, + localeConfig.path, + ); + return fs.pathExists(localizationDir); + } + + const translate = localeConfigInput.translate ?? (await inferTranslate()); + return { + ...localeConfig, + translate, }; } - const localeConfigs = Object.fromEntries( - locales.map((locale) => [locale, getLocaleConfig(locale)]), + const localeConfigs = await combinePromises( + Object.fromEntries( + locales.map((locale) => [locale, getFullLocaleConfig(locale)]), + ), ); return { diff --git a/packages/docusaurus/src/server/plugins/__tests__/plugins.test.ts b/packages/docusaurus/src/server/plugins/__tests__/plugins.test.ts index 39c12daa0b..b62276638b 100644 --- a/packages/docusaurus/src/server/plugins/__tests__/plugins.test.ts +++ b/packages/docusaurus/src/server/plugins/__tests__/plugins.test.ts @@ -11,12 +11,16 @@ import {loadPlugins, reloadPlugin} from '../plugins'; import {DEFAULT_FUTURE_CONFIG} from '../../configValidation'; import type {LoadContext, Plugin, PluginConfig} from '@docusaurus/types'; +type TestOptions = {translate?: boolean}; + async function testLoad({ plugins, themes, + options = {}, }: { plugins: PluginConfig[]; themes: PluginConfig[]; + options?: TestOptions; }) { const siteDir = path.join(__dirname, '__fixtures__/site-with-plugin'); @@ -25,6 +29,13 @@ async function testLoad({ siteConfigPath: path.join(siteDir, 'docusaurus.config.js'), generatedFilesDir: path.join(siteDir, '.docusaurus'), outDir: path.join(siteDir, 'build'), + i18n: { + path: 'i18n', + locales: ['en'], + currentLocale: 'en', + defaultLocale: 'en', + localeConfigs: {en: {translate: options.translate ?? true}}, + }, siteConfig: { baseUrl: '/', trailingSlash: true, @@ -49,10 +60,12 @@ const SyntheticPluginNames = [ async function testPlugin( pluginConfig: PluginConfig, + options?: TestOptions, ) { const {context, plugins, routes, globalData} = await testLoad({ plugins: [pluginConfig], themes: [], + options, }); const nonSyntheticPlugins = plugins.filter( @@ -86,65 +99,120 @@ describe('loadPlugins', () => { expect(globalData).toEqual({}); }); - it('typical plugin', async () => { - const {plugin, routes, globalData} = await testPlugin(() => ({ - name: 'plugin-name', - loadContent: () => ({name: 'Toto', age: 42}), - translateContent: ({content}) => ({ - ...content, - name: `${content.name} (translated)`, - }), - contentLoaded({content, actions}) { - actions.addRoute({ - path: '/foo', - component: 'Comp', - modules: {someModule: 'someModulePath'}, - context: {someContext: 'someContextPath'}, - }); - actions.setGlobalData({ - globalName: content.name, - globalAge: content.age, - }); - }, - })); + describe('typical plugin', () => { + function typicalPlugin(options: TestOptions) { + return testPlugin( + () => ({ + name: 'plugin-name', + loadContent: () => ({name: 'Toto', age: 42}), + translateContent: ({content}) => ({ + ...content, + name: `${content.name} (translated)`, + }), + contentLoaded({content, actions}) { + actions.addRoute({ + path: '/foo', + component: 'Comp', + modules: {someModule: 'someModulePath'}, + context: {someContext: 'someContextPath'}, + }); + actions.setGlobalData({ + globalName: content.name, + globalAge: content.age, + }); + }, + }), + options, + ); + } - expect(plugin.content).toMatchInlineSnapshot(` - { - "age": 42, - "name": "Toto (translated)", - } - `); - expect(routes).toMatchInlineSnapshot(` - [ + it('translated: true', async () => { + const {plugin, routes, globalData} = await typicalPlugin({ + translate: true, + }); + + expect(plugin.content).toMatchInlineSnapshot(` + { + "age": 42, + "name": "Toto (translated)", + } + `); + expect(routes).toMatchInlineSnapshot(` + [ + { + "component": "Comp", + "context": { + "data": { + "someContext": "someContextPath", + }, + "plugin": "@generated/plugin-name/default/__plugin.json", + }, + "modules": { + "someModule": "someModulePath", + }, + "path": "/foo/", + "plugin": { + "id": "default", + "name": "plugin-name", + }, + }, + ] + `); + expect(globalData).toMatchInlineSnapshot(` + { + "plugin-name": { + "default": { + "globalAge": 42, + "globalName": "Toto (translated)", + }, + }, + } + `); + }); + + it('translated: false', async () => { + const {plugin, routes, globalData} = await typicalPlugin({ + translate: false, + }); + + expect(plugin.content).toMatchInlineSnapshot(` { - "component": "Comp", - "context": { - "data": { - "someContext": "someContextPath", + "age": 42, + "name": "Toto", + } + `); + expect(routes).toMatchInlineSnapshot(` + [ + { + "component": "Comp", + "context": { + "data": { + "someContext": "someContextPath", + }, + "plugin": "@generated/plugin-name/default/__plugin.json", + }, + "modules": { + "someModule": "someModulePath", + }, + "path": "/foo/", + "plugin": { + "id": "default", + "name": "plugin-name", + }, + }, + ] + `); + expect(globalData).toMatchInlineSnapshot(` + { + "plugin-name": { + "default": { + "globalAge": 42, + "globalName": "Toto", }, - "plugin": "@generated/plugin-name/default/__plugin.json", }, - "modules": { - "someModule": "someModulePath", - }, - "path": "/foo/", - "plugin": { - "id": "default", - "name": "plugin-name", - }, - }, - ] - `); - expect(globalData).toMatchInlineSnapshot(` - { - "plugin-name": { - "default": { - "globalAge": 42, - "globalName": "Toto (translated)", - }, - }, - } - `); + } + `); + }); }); it('plugin with options', async () => { diff --git a/packages/docusaurus/src/server/plugins/plugins.ts b/packages/docusaurus/src/server/plugins/plugins.ts index f16007a5ec..b697878624 100644 --- a/packages/docusaurus/src/server/plugins/plugins.ts +++ b/packages/docusaurus/src/server/plugins/plugins.ts @@ -6,6 +6,7 @@ */ import {PerfLogger} from '@docusaurus/logger'; +import {getLocaleConfig} from '@docusaurus/utils'; import {initPlugins} from './init'; import {createBootstrapPlugin, createMDXFallbackPlugin} from './synthetic'; import {localizePluginTranslationFile} from '../translations/translations'; @@ -81,14 +82,20 @@ async function executePluginContentLoading({ plugin.loadContent?.(), ); - content = await PerfLogger.async('translatePluginContent()', () => - translatePluginContent({ - plugin, - content, - context, - }), - ); + const shouldTranslate = getLocaleConfig(context.i18n).translate; + if (shouldTranslate) { + content = await PerfLogger.async('translatePluginContent()', () => + translatePluginContent({ + plugin, + content, + context, + }), + ); + } + + // If shouldTranslate === false, we still need the code translations + // Otherwise an unlocalized French site would show code strings in English const defaultCodeTranslations = (await PerfLogger.async('getDefaultCodeTranslationMessages()', () => plugin.getDefaultCodeTranslationMessages?.(), diff --git a/packages/docusaurus/src/server/site.ts b/packages/docusaurus/src/server/site.ts index d8fd3f242c..a48e68dd8a 100644 --- a/packages/docusaurus/src/server/site.ts +++ b/packages/docusaurus/src/server/site.ts @@ -10,6 +10,7 @@ import { localizePath, DEFAULT_BUILD_DIR_NAME, GENERATED_FILES_DIR_NAME, + getLocaleConfig, } from '@docusaurus/utils'; import {PerfLogger} from '@docusaurus/logger'; import combinePromises from 'combine-promises'; @@ -96,7 +97,11 @@ export async function loadContext( siteConfig: initialSiteConfig, }); - const i18n = await loadI18n(initialSiteConfig, {locale}); + const i18n = await loadI18n({ + siteDir, + config: initialSiteConfig, + currentLocale: locale ?? initialSiteConfig.i18n.defaultLocale, + }); const baseUrl = localizePath({ path: initialSiteConfig.baseUrl, @@ -113,7 +118,7 @@ export async function loadContext( const localizationDir = path.resolve( siteDir, i18n.path, - i18n.localeConfigs[i18n.currentLocale]!.path, + getLocaleConfig(i18n).path, ); const siteConfig: DocusaurusConfig = {...initialSiteConfig, baseUrl}; diff --git a/packages/docusaurus/src/webpack/client.ts b/packages/docusaurus/src/webpack/client.ts index 66e32fae36..660e7f8119 100644 --- a/packages/docusaurus/src/webpack/client.ts +++ b/packages/docusaurus/src/webpack/client.ts @@ -11,6 +11,7 @@ import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer'; import ReactLoadableSSRAddon from 'react-loadable-ssr-addon-v5-slorber'; import HtmlWebpackPlugin from 'html-webpack-plugin'; import {getProgressBarPlugin} from '@docusaurus/bundler'; +import {getLocaleConfig} from '@docusaurus/utils'; import {createBaseConfig} from './base'; import ChunkAssetPlugin from './plugins/ChunkAssetPlugin'; import ForceTerminatePlugin from './plugins/ForceTerminatePlugin'; @@ -117,7 +118,7 @@ export async function createStartClientConfig({ headTags, preBodyTags, postBodyTags, - lang: props.i18n.localeConfigs[props.i18n.currentLocale]!.htmlLang, + lang: getLocaleConfig(props.i18n).htmlLang, }), ], }, diff --git a/website/docs/api/docusaurus.config.js.mdx b/website/docs/api/docusaurus.config.js.mdx index 1ac4d1e07b..351da0421a 100644 --- a/website/docs/api/docusaurus.config.js.mdx +++ b/website/docs/api/docusaurus.config.js.mdx @@ -151,6 +151,7 @@ export default { htmlLang: 'en-US', calendar: 'gregory', path: 'en', + translate: false, }, fa: { label: 'فارسی', @@ -158,6 +159,7 @@ export default { htmlLang: 'fa-IR', calendar: 'persian', path: 'fa', + translate: true, }, }, }, @@ -172,7 +174,8 @@ export default { - `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 `` (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. + - `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 (`i18n/`). Note: this has no effect on the locale's `baseUrl`—customization of base URL is a work-in-progress. + - `translate`: Should we run the translation process for this locale? By default, it is enabled if the `i18n/` folder exists ### `future` {#future} From 3733dfee525201f4520daccddf9c56563cb7ff76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Mon, 7 Jul 2025 16:50:01 +0200 Subject: [PATCH 034/103] test: fix site test infinite loop in Jest --watch mode + simplify test (#11312) --- jest.config.mjs | 7 +++-- .../__tests__/__snapshots__/site.test.ts.snap | 2 +- .../src/server/__tests__/site.test.ts | 28 ++++++++----------- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/jest.config.mjs b/jest.config.mjs index 3245daa850..e8e4f3d235 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -32,15 +32,16 @@ const ignorePatterns = [ export default { rootDir: fileURLToPath(new URL('.', import.meta.url)), verbose: true, + // Default 5s timeout often fails on Windows :s, + // see https://github.com/facebook/docusaurus/pull/8259 + testTimeout: 15000, setupFiles: ['./jest/setup.js'], testEnvironmentOptions: { url: 'https://docusaurus.io/', }, testEnvironment: 'node', testPathIgnorePatterns: ignorePatterns, - // Default 5s timeout often fails on Windows :s, - // see https://github.com/facebook/docusaurus/pull/8259 - testTimeout: 15000, + watchPathIgnorePatterns: ['/\\.docusaurus'], coveragePathIgnorePatterns: [ ...ignorePatterns, // We also ignore all package entry points diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap index b15943ef82..4b335e062b 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`load loads props for site with custom i18n path 1`] = ` +exports[`load loads props for site 1`] = ` { "baseUrl": "/", "codeTranslations": {}, diff --git a/packages/docusaurus/src/server/__tests__/site.test.ts b/packages/docusaurus/src/server/__tests__/site.test.ts index dc6027c780..7ce18bfa4d 100644 --- a/packages/docusaurus/src/server/__tests__/site.test.ts +++ b/packages/docusaurus/src/server/__tests__/site.test.ts @@ -6,26 +6,22 @@ */ import path from 'path'; -import {mergeWithCustomize} from 'webpack-merge'; import {loadSetup} from './testUtils'; -import type {Props} from '@docusaurus/types'; -import type {DeepPartial} from 'utility-types'; describe('load', () => { - it('loads props for site with custom i18n path', async () => { + it('loads props for site', async () => { const site = await loadSetup('custom-i18n-site'); expect(site.props).toMatchSnapshot(); - const site2 = await loadSetup('custom-i18n-site', {locale: 'zh-Hans'}); - expect(site2.props).toEqual( - mergeWithCustomize>({ - customizeArray(a, b, key) { - return ['routesPaths', 'plugins'].includes(key) ? b : undefined; - }, - })(site.props, { + }); + + it('loads props for site - custom i18n path', async () => { + const site = await loadSetup('custom-i18n-site', {locale: 'zh-Hans'}); + expect(site.props).toEqual( + expect.objectContaining({ baseUrl: '/zh-Hans/', - i18n: { + i18n: expect.objectContaining({ currentLocale: 'zh-Hans', - }, + }), localizationDir: path.join( __dirname, '__fixtures__/custom-i18n-site/i18n/zh-Hans-custom', @@ -35,14 +31,14 @@ describe('load', () => { '__fixtures__/custom-i18n-site/build/zh-Hans', ), routesPaths: ['/zh-Hans/404.html'], - siteConfig: { + siteConfig: expect.objectContaining({ baseUrl: '/zh-Hans/', - }, + }), siteStorage: { namespace: '', type: 'localStorage', }, - plugins: site2.props.plugins, + plugins: site.props.plugins, }), ); }); From 0306d182407bb98f140cd5ec7481fa9608fe0297 Mon Sep 17 00:00:00 2001 From: Marcelo Junior Date: Thu, 10 Jul 2025 04:42:11 -0300 Subject: [PATCH 035/103] fix(theme-translations): Add missing Portuguese (pt-BR) theme translations and improve some of it. (#11315) --- .../locales/pt-BR/theme-common.json | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/packages/docusaurus-theme-translations/locales/pt-BR/theme-common.json b/packages/docusaurus-theme-translations/locales/pt-BR/theme-common.json index b65f3a0d2d..d848584d66 100644 --- a/packages/docusaurus-theme-translations/locales/pt-BR/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/pt-BR/theme-common.json @@ -1,83 +1,83 @@ { "theme.AnnouncementBar.closeButtonAriaLabel": "Fechar", - "theme.BackToTopButton.buttonAriaLabel": "Volte para o topo", + "theme.BackToTopButton.buttonAriaLabel": "Voltar para o topo", "theme.CodeBlock.copied": "Copiado", "theme.CodeBlock.copy": "Copiar", "theme.CodeBlock.copyButtonAriaLabel": "Copiar código para a área de transferência", "theme.CodeBlock.wordWrapToggle": "Alternar quebra de linha", - "theme.DocSidebarItem.collapseCategoryAriaLabel": "Fechar a categoria lateral '{label}'", - "theme.DocSidebarItem.expandCategoryAriaLabel": "Expandir a categoria lateral '{label}'", + "theme.DocSidebarItem.collapseCategoryAriaLabel": "Recolher a categoria '{label}'", + "theme.DocSidebarItem.expandCategoryAriaLabel": "Expandir a categoria '{label}'", "theme.ErrorPageContent.title": "Esta página deu erro.", - "theme.ErrorPageContent.tryAgain": "Tente novamente", - "theme.NavBar.navAriaLabel": "Main", + "theme.ErrorPageContent.tryAgain": "Tentar novamente", + "theme.NavBar.navAriaLabel": "Navegação principal", "theme.NotFound.p1": "Não foi possível encontrar o que você está procurando.", - "theme.NotFound.p2": "Entre em contato com o proprietário do site que lhe trouxe para cá e lhe informe que o link está quebrado.", + "theme.NotFound.p2": "Por favor, entre em contato com o dono do site que ligou você à URL original e informe que o link está quebrado.", "theme.NotFound.title": "Página não encontrada", - "theme.TOCCollapsible.toggleButtonLabel": "Nessa página", + "theme.TOCCollapsible.toggleButtonLabel": "Nesta página", "theme.admonition.caution": "cuidado", "theme.admonition.danger": "perigo", - "theme.admonition.info": "info", - "theme.admonition.note": "nota", + "theme.admonition.info": "informação", + "theme.admonition.note": "observação", "theme.admonition.tip": "dica", - "theme.admonition.warning": "atenção", + "theme.admonition.warning": "aviso", "theme.blog.archive.description": "Arquivo", "theme.blog.archive.title": "Arquivo", - "theme.blog.author.noPosts": "This author has not written any posts yet.", + "theme.blog.author.noPosts": "Este autor ainda não escreveu nenhuma publicação.", "theme.blog.author.pageTitle": "{authorName} - {nPosts}", - "theme.blog.authorsList.pageTitle": "Authors", - "theme.blog.authorsList.viewAll": "View All Authors", + "theme.blog.authorsList.pageTitle": "Autores", + "theme.blog.authorsList.viewAll": "Ver todos os autores", "theme.blog.paginator.navAriaLabel": "Navegação da página de listagem do blog", - "theme.blog.paginator.newerEntries": "Conteúdo mais novo", - "theme.blog.paginator.olderEntries": "Conteúdo mais antigo", - "theme.blog.post.paginator.navAriaLabel": "Navegação da página de postagem do blog", - "theme.blog.post.paginator.newerPost": "Postagem mais nova", - "theme.blog.post.paginator.olderPost": "Postagem mais antiga", - "theme.blog.post.plurals": "Uma postagem|{count} postagens", - "theme.blog.post.readMore": "Leia Mais", + "theme.blog.paginator.newerEntries": "Publicações mais recentes", + "theme.blog.paginator.olderEntries": "Publicações mais antigas", + "theme.blog.post.paginator.navAriaLabel": "Navegação da página de publicação do blog", + "theme.blog.post.paginator.newerPost": "Publicação mais recente", + "theme.blog.post.paginator.olderPost": "Publicação mais antiga", + "theme.blog.post.plurals": "Uma publicação|{count} publicações", + "theme.blog.post.readMore": "Ler mais", "theme.blog.post.readMoreLabel": "Ler mais sobre {title}", - "theme.blog.post.readingTime.plurals": "Leitura de um minuto|Leitura de {readingTime} minutos", - "theme.blog.sidebar.navAriaLabel": "Blog recent posts navigation", - "theme.blog.tagTitle": "{nPosts} marcadas com \"{tagName}\"", - "theme.colorToggle.ariaLabel": "Alterar entre os modos claro e escuro (modo {mode} ativado)", + "theme.blog.post.readingTime.plurals": "Um minuto para ler|{readingTime} min para ler", + "theme.blog.sidebar.navAriaLabel": "Navegação das publicações recentes do blog", + "theme.blog.tagTitle": "{nPosts} com a etiqueta \"{tagName}\"", + "theme.colorToggle.ariaLabel": "Mudar entre modo claro e escuro ({mode} está ativo)", "theme.colorToggle.ariaLabel.mode.dark": "modo escuro", "theme.colorToggle.ariaLabel.mode.light": "modo claro", - "theme.colorToggle.ariaLabel.mode.system": "system mode", - "theme.common.editThisPage": "Editar essa página", + "theme.colorToggle.ariaLabel.mode.system": "modo do sistema", + "theme.common.editThisPage": "Editar esta página", "theme.common.headingLinkTitle": "Link direto para {heading}", "theme.common.skipToMainContent": "Pular para o conteúdo principal", - "theme.contentVisibility.draftBanner.message": "This page is a draft. It will only be visible in dev and be excluded from the production build.", - "theme.contentVisibility.draftBanner.title": "Draft page", - "theme.contentVisibility.unlistedBanner.message": "Esta página não está listada. Mecanismos de busca não armazenarão nenhuma informação, e somente usuários que possuam o link direto poderão acessá-la", + "theme.contentVisibility.draftBanner.message": "Esta página é um rascunho. Ela estará visível apenas no desenvolvimento e será excluída da compilação de produção.", + "theme.contentVisibility.draftBanner.title": "Página de rascunho", + "theme.contentVisibility.unlistedBanner.message": "Esta página não está listada. Mecanismos de busca não irão indexá-la, e somente usuários que possuam o link direto poderão acessá-la", "theme.contentVisibility.unlistedBanner.title": "Página não listada", - "theme.docs.DocCard.categoryDescription.plurals": "1 item|{count} items", + "theme.docs.DocCard.categoryDescription.plurals": "1 item|{count} itens", "theme.docs.breadcrumbs.home": "Página Inicial", - "theme.docs.breadcrumbs.navAriaLabel": "Breadcrumbs", - "theme.docs.paginator.navAriaLabel": "Páginas de documentação", + "theme.docs.breadcrumbs.navAriaLabel": "Trilha", + "theme.docs.paginator.navAriaLabel": "Páginas de documento", "theme.docs.paginator.next": "Próxima", "theme.docs.paginator.previous": "Anterior", - "theme.docs.sidebar.closeSidebarButtonAriaLabel": "Fechar barra de navegação", - "theme.docs.sidebar.collapseButtonAriaLabel": "Fechar painel lateral", - "theme.docs.sidebar.collapseButtonTitle": "Fechar painel lateral", + "theme.docs.sidebar.closeSidebarButtonAriaLabel": "Fechar painel de navegação", + "theme.docs.sidebar.collapseButtonAriaLabel": "Recolher painel lateral", + "theme.docs.sidebar.collapseButtonTitle": "Recolher painel lateral", "theme.docs.sidebar.expandButtonAriaLabel": "Expandir painel lateral", "theme.docs.sidebar.expandButtonTitle": "Expandir painel lateral", - "theme.docs.sidebar.navAriaLabel": "Docs sidebar", - "theme.docs.sidebar.toggleSidebarButtonAriaLabel": "Alternar a barra de navegação", + "theme.docs.sidebar.navAriaLabel": "Painel lateral de documentos", + "theme.docs.sidebar.toggleSidebarButtonAriaLabel": "Alternar painel de navegação", "theme.docs.tagDocListPageTitle": "{nDocsTagged} com \"{tagName}\"", - "theme.docs.tagDocListPageTitle.nDocsTagged": "Um documento selecionado|{count} documentos selecionados", + "theme.docs.tagDocListPageTitle.nDocsTagged": "Um documento marcado|{count} documentos marcados", "theme.docs.versionBadge.label": "Versão: {versionLabel}", - "theme.docs.versions.latestVersionLinkLabel": "última versão", - "theme.docs.versions.latestVersionSuggestionLabel": "Para a documentação atualizada, veja: {latestVersionLink} ({versionLabel}).", + "theme.docs.versions.latestVersionLinkLabel": "versão mais recente", + "theme.docs.versions.latestVersionSuggestionLabel": "Para a documentação atualizada, consulte a {latestVersionLink} ({versionLabel}).", "theme.docs.versions.unmaintainedVersionLabel": "Esta é a documentação para {siteTitle} {versionLabel}, que não é mais mantida ativamente.", - "theme.docs.versions.unreleasedVersionLabel": "Esta é uma documentação não lançada para {siteTitle} {versionLabel}.", + "theme.docs.versions.unreleasedVersionLabel": "Esta é uma documentação não lançada da versão {versionLabel} para {siteTitle}.", "theme.lastUpdated.atDate": " em {date}", "theme.lastUpdated.byUser": " por {user}", - "theme.lastUpdated.lastUpdatedAtBy": "Última atualização {atDate}{byUser}", - "theme.navbar.mobileDropdown.collapseButton.collapseAriaLabel": "Collapse the dropdown", - "theme.navbar.mobileDropdown.collapseButton.expandAriaLabel": "Expand the dropdown", - "theme.navbar.mobileLanguageDropdown.label": "Linguagens", + "theme.lastUpdated.lastUpdatedAtBy": "Última atualização{atDate}{byUser}", + "theme.navbar.mobileDropdown.collapseButton.collapseAriaLabel": "Recolher a seleção", + "theme.navbar.mobileDropdown.collapseButton.expandAriaLabel": "Expandir a seleção", + "theme.navbar.mobileLanguageDropdown.label": "Línguas", "theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": "← Voltar para o menu principal", "theme.navbar.mobileVersionsDropdown.label": "Versões", - "theme.tags.tagsListLabel": "Marcadores:", - "theme.tags.tagsPageLink": "Ver todas os Marcadores", - "theme.tags.tagsPageTitle": "Marcadores" + "theme.tags.tagsListLabel": "Etiquetas:", + "theme.tags.tagsPageLink": "Ver todas as etiquetas", + "theme.tags.tagsPageTitle": "Etiquetas" } From 2adbc0d6a0b92b099d2c3e22b147c904d3f9fc59 Mon Sep 17 00:00:00 2001 From: Seth Falco Date: Tue, 15 Jul 2025 13:58:05 +0100 Subject: [PATCH 036/103] chore: minor reduction to inline svg/js code (#11317) --- .../__snapshots__/inlineScripts.test.ts.snap | 33 +++++++++++++ .../src/__tests__/inlineScripts.test.ts | 42 +++++++++++++++++ .../docusaurus-theme-classic/src/index.ts | 1 - .../src/inlineScripts.ts | 47 +++++++++++-------- 4 files changed, 102 insertions(+), 21 deletions(-) create mode 100644 packages/docusaurus-theme-classic/src/__tests__/__snapshots__/inlineScripts.test.ts.snap create mode 100644 packages/docusaurus-theme-classic/src/__tests__/inlineScripts.test.ts diff --git a/packages/docusaurus-theme-classic/src/__tests__/__snapshots__/inlineScripts.test.ts.snap b/packages/docusaurus-theme-classic/src/__tests__/__snapshots__/inlineScripts.test.ts.snap new file mode 100644 index 0000000000..acad179bbe --- /dev/null +++ b/packages/docusaurus-theme-classic/src/__tests__/__snapshots__/inlineScripts.test.ts.snap @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`inlineScripts inline javascript for default options 1`] = ` +"(function() { + function getSystemColorMode() { + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; + } + function getQueryStringTheme() { + try { + return new URLSearchParams(window.location.search).get('docusaurus-theme') + } catch (e) {} + } + function getStoredTheme() { + try { + return window['localStorage'].getItem('theme'); + } catch (err) {} + } + var initialTheme = getQueryStringTheme() || getStoredTheme(); + document.documentElement.setAttribute('data-theme', initialTheme || 'light'); + document.documentElement.setAttribute('data-theme-choice', initialTheme || 'light'); +})();" +`; + +exports[`inlineScripts inline javascript for prefers color scheme and no switch 1`] = ` +"(function() { + function getSystemColorMode() { + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; + } + var initialTheme; + document.documentElement.setAttribute('data-theme', initialTheme || getSystemColorMode()); + document.documentElement.setAttribute('data-theme-choice', initialTheme || 'system'); +})();" +`; diff --git a/packages/docusaurus-theme-classic/src/__tests__/inlineScripts.test.ts b/packages/docusaurus-theme-classic/src/__tests__/inlineScripts.test.ts new file mode 100644 index 0000000000..5671d77d3c --- /dev/null +++ b/packages/docusaurus-theme-classic/src/__tests__/inlineScripts.test.ts @@ -0,0 +1,42 @@ +/** + * 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 {getThemeInlineScript} from '../inlineScripts'; + +describe('inlineScripts', () => { + it('inline javascript for default options', () => { + expect( + getThemeInlineScript({ + colorMode: { + disableSwitch: false, + defaultMode: 'light', + respectPrefersColorScheme: false, + }, + siteStorage: { + type: 'localStorage', + namespace: '', + }, + }), + ).toMatchSnapshot(); + }); + + it('inline javascript for prefers color scheme and no switch', () => { + expect( + getThemeInlineScript({ + colorMode: { + disableSwitch: true, + defaultMode: 'light', + respectPrefersColorScheme: true, + }, + siteStorage: { + type: 'localStorage', + namespace: '', + }, + }), + ).toMatchSnapshot(); + }); +}); diff --git a/packages/docusaurus-theme-classic/src/index.ts b/packages/docusaurus-theme-classic/src/index.ts index ac2ea69a4c..f219d9039b 100644 --- a/packages/docusaurus-theme-classic/src/index.ts +++ b/packages/docusaurus-theme-classic/src/index.ts @@ -125,7 +125,6 @@ export default function themeClassic( { tagName: 'svg', attributes: { - xmlns: 'http://www.w3.org/2000/svg', style: 'display: none;', }, innerHTML: SvgSpriteDefs, diff --git a/packages/docusaurus-theme-classic/src/inlineScripts.ts b/packages/docusaurus-theme-classic/src/inlineScripts.ts index 4a2e4694b6..fe49094a52 100644 --- a/packages/docusaurus-theme-classic/src/inlineScripts.ts +++ b/packages/docusaurus-theme-classic/src/inlineScripts.ts @@ -15,7 +15,7 @@ const ThemeQueryStringKey = 'docusaurus-theme'; const DataQueryStringPrefixKey = 'docusaurus-data-'; export function getThemeInlineScript({ - colorMode: {defaultMode, respectPrefersColorScheme}, + colorMode: {disableSwitch, defaultMode, respectPrefersColorScheme}, siteStorage, }: { colorMode: ThemeConfig['colorMode']; @@ -25,28 +25,35 @@ export function getThemeInlineScript({ // Make sure the key is the same as the one in the color mode React context // Currently defined in: `docusaurus-theme-common/src/contexts/colorMode.tsx` const themeStorageKey = `theme${siteStorage.namespace}`; + const isThemeUserConfigurable = !disableSwitch; /* language=js */ return `(function() { - var defaultMode = '${defaultMode}'; - var respectPrefersColorScheme = ${respectPrefersColorScheme}; - function getSystemColorMode() { - return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; - } - function getQueryStringTheme() { - try { - return new URLSearchParams(window.location.search).get('${ThemeQueryStringKey}') - } catch (e) {} - } - function getStoredTheme() { - try { - return window['${siteStorage.type}'].getItem('${themeStorageKey}'); - } catch (err) {} - } - var initialTheme = getQueryStringTheme() || getStoredTheme(); - document.documentElement.setAttribute('data-theme', initialTheme || (respectPrefersColorScheme ? getSystemColorMode() : defaultMode)); - document.documentElement.setAttribute('data-theme-choice', initialTheme || (respectPrefersColorScheme ? 'system' : defaultMode)); - })();`; + function getSystemColorMode() { + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; + } +${ + isThemeUserConfigurable + ? ` function getQueryStringTheme() { + try { + return new URLSearchParams(window.location.search).get('${ThemeQueryStringKey}') + } catch (e) {} + } + function getStoredTheme() { + try { + return window['${siteStorage.type}'].getItem('${themeStorageKey}'); + } catch (err) {} + } + var initialTheme = getQueryStringTheme() || getStoredTheme();` + : ' var initialTheme;' +} + document.documentElement.setAttribute('data-theme', initialTheme || ${ + respectPrefersColorScheme ? 'getSystemColorMode()' : `'${defaultMode}'` + }); + document.documentElement.setAttribute('data-theme-choice', initialTheme || ${ + respectPrefersColorScheme ? `'system'` : `'${defaultMode}'` + }); +})();`; } /* language=js */ From a3324ff65e3b6b4472049a510a9a9d8be4830ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Tue, 15 Jul 2025 15:11:20 +0200 Subject: [PATCH 037/103] docs: fix release notes link (#11329) --- website/src/pages/versions.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/website/src/pages/versions.tsx b/website/src/pages/versions.tsx index 5e453e27d1..a54985643c 100644 --- a/website/src/pages/versions.tsx +++ b/website/src/pages/versions.tsx @@ -12,6 +12,7 @@ import Translate from '@docusaurus/Translate'; import { useVersions, useLatestVersion, + type GlobalVersion, } from '@docusaurus/plugin-content-docs/client'; import Layout from '@theme/Layout'; import Heading from '@theme/Heading'; @@ -49,6 +50,13 @@ export default function Version(): ReactNode { ); const repoUrl = `https://github.com/${organizationName!}/${projectName!}`; + function getReleaseNotesUrl(version: GlobalVersion): string { + if (version.name === '2.x') { + return 'https://github.com/facebook/docusaurus/blob/main/CHANGELOG-v2.md'; + } + return `${repoUrl}/releases/tag/v${version.name}`; + } + return ( - + @@ -142,7 +150,7 @@ export default function Version(): ReactNode { - + From 0239c18b784db2f5eea2e2f9550539c22921e6f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 10:01:03 +0200 Subject: [PATCH 038/103] chore(deps): bump marocchino/sticky-pull-request-comment from 2.9.3 to 2.9.4 (#11341) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lighthouse-report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lighthouse-report.yml b/.github/workflows/lighthouse-report.yml index 118cd61afb..ce28df365e 100644 --- a/.github/workflows/lighthouse-report.yml +++ b/.github/workflows/lighthouse-report.yml @@ -65,7 +65,7 @@ jobs: - name: Add Lighthouse stats as comment id: comment_to_pr - uses: marocchino/sticky-pull-request-comment@d2ad0de260ae8b0235ce059e63f2949ba9e05943 # 2.9.3 + uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # 2.9.4 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} number: ${{ github.event.pull_request.number }} From 2655db686e42b727271b3e6d2cf4959735ddfc9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 10:01:10 +0200 Subject: [PATCH 039/103] chore(deps): bump form-data from 4.0.1 to 4.0.4 (#11342) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/yarn.lock b/yarn.lock index b1d51b9392..47772572cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8166,14 +8166,15 @@ es-object-atoms@^1.0.0: dependencies: es-errors "^1.3.0" -es-set-tostringtag@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" - integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== +es-set-tostringtag@^2.0.3, es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== dependencies: - get-intrinsic "^1.2.4" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" has-tostringtag "^1.0.2" - hasown "^2.0.1" + hasown "^2.0.2" es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: version "1.0.2" @@ -9059,12 +9060,14 @@ form-data-encoder@^2.1.2: integrity sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw== form-data@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" - integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== + version "4.0.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.4.tgz#784cdcce0669a9d68e94d11ac4eea98088edd2c4" + integrity sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" mime-types "^2.1.12" format@^0.2.0: From e83747f323809023bf9dc1f4a7c41869ce1690f2 Mon Sep 17 00:00:00 2001 From: Guo Ci Date: Thu, 24 Jul 2025 04:03:46 -0400 Subject: [PATCH 040/103] Fix npm command typos in deployment.mdx (#11337) --- website/versioned_docs/version-3.8.1/deployment.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/versioned_docs/version-3.8.1/deployment.mdx b/website/versioned_docs/version-3.8.1/deployment.mdx index 5a6cfb00ee..98f8f02cfa 100644 --- a/website/versioned_docs/version-3.8.1/deployment.mdx +++ b/website/versioned_docs/version-3.8.1/deployment.mdx @@ -407,7 +407,7 @@ jobs: - name: Install dependencies run: npm ci - name: Build website - run: npm build + run: npm run build - name: Upload Build Artifact uses: actions/upload-pages-artifact@v3 @@ -461,7 +461,7 @@ jobs: - name: Install dependencies run: npm ci - name: Test build website - run: npm build + run: npm run build ``` From c81808459d9f494fe6a801473987d0c783ddb642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 24 Jul 2025 11:01:03 +0200 Subject: [PATCH 041/103] fix(core): Fix docusaurus start on macOS when exec throws a synchronous error (#11347) Co-authored-by: slorber <749374+slorber@users.noreply.github.com> --- .../src/commands/utils/openBrowser/openBrowser.ts | 14 ++++++++++---- yarn.lock | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/docusaurus/src/commands/utils/openBrowser/openBrowser.ts b/packages/docusaurus/src/commands/utils/openBrowser/openBrowser.ts index a0dd2654ce..2c4d2789a6 100644 --- a/packages/docusaurus/src/commands/utils/openBrowser/openBrowser.ts +++ b/packages/docusaurus/src/commands/utils/openBrowser/openBrowser.ts @@ -72,10 +72,16 @@ async function tryOpenWithAppleScript({ '|', )})$"`; - const result = await execPromise(command).catch(() => { - // Ignore grep errors when macOS user has no Chromium-based browser open - // See https://github.com/facebook/docusaurus/issues/11204 - }); + const result = await Promise + // TODO Docusaurus v4: use Promise.try() + // See why here https://github.com/facebook/docusaurus/issues/11204#issuecomment-3073480330 + .resolve() + .then(() => execPromise(command)) + .catch(() => { + // Ignore all errors + // In particular grep errors when macOS user has no Chromium-based browser open + // See https://github.com/facebook/docusaurus/issues/11204 + }); if (!result) { return []; } diff --git a/yarn.lock b/yarn.lock index 47772572cf..38003b5fcb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9652,7 +9652,7 @@ has-yarn@^3.0.0: resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-3.0.0.tgz#c3c21e559730d1d3b57e28af1f30d06fac38147d" integrity sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA== -hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: +hasown@^2.0.0, hasown@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== From 12bcad983735b83b668cb21ea1869a87f3480fe2 Mon Sep 17 00:00:00 2001 From: hjcho Date: Thu, 24 Jul 2025 18:03:25 +0900 Subject: [PATCH 042/103] fix(theme-classic): fix collapsed sidebar category expansion when navigating to another link within that category (#11338) Co-authored-by: qqq614 --- .../theme/DocSidebarItem/Category/index.tsx | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx index cf29059928..22270f21a3 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx @@ -37,18 +37,30 @@ function useAutoExpandActiveCategory({ isActive, collapsed, updateCollapsed, + activePath, }: { isActive: boolean; collapsed: boolean; updateCollapsed: (b: boolean) => void; + activePath: string; }) { const wasActive = usePrevious(isActive); + const previousActivePath = usePrevious(activePath); useEffect(() => { const justBecameActive = isActive && !wasActive; - if (justBecameActive && collapsed) { + const stillActiveButPathChanged = + isActive && wasActive && activePath !== previousActivePath; + if ((justBecameActive || stillActiveButPathChanged) && collapsed) { updateCollapsed(false); } - }, [isActive, wasActive, collapsed, updateCollapsed]); + }, [ + isActive, + wasActive, + collapsed, + updateCollapsed, + activePath, + previousActivePath, + ]); } /** @@ -150,7 +162,12 @@ export default function DocSidebarItemCategory({ setExpandedItem(toCollapsed ? null : index); setCollapsed(toCollapsed); }; - useAutoExpandActiveCategory({isActive, collapsed, updateCollapsed}); + useAutoExpandActiveCategory({ + isActive, + collapsed, + updateCollapsed, + activePath, + }); useEffect(() => { if ( collapsible && From 2febb76fae9a353778d9d995ced18f9515dab8de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Mon, 28 Jul 2025 17:04:34 +0200 Subject: [PATCH 043/103] feat(core): Add `i18n.localeConfigs[locale].{url,baseUrl}` config options (#11316) Co-authored-by: slorber <749374+slorber@users.noreply.github.com> --- .eslintrc.js | 2 +- .../docusaurus-plugin-pwa/src/registerSw.ts | 3 +- .../LocaleDropdownNavbarItem/index.tsx | 87 +++++++-- packages/docusaurus-theme-common/package.json | 1 + packages/docusaurus-theme-common/src/index.ts | 2 + .../src/utils/__tests__/historyUtils.test.ts | 80 +++++++++ .../__tests__/useAlternatePageUtils.test.tsx | 169 ++++++++++++------ .../src/utils/historyUtils.ts | 29 +++ .../src/utils/useAlternatePageUtils.ts | 32 ++-- packages/docusaurus-types/src/i18n.d.ts | 19 ++ .../src/__tests__/i18nUtils.test.ts | 89 +-------- packages/docusaurus-utils/src/i18nUtils.ts | 49 ----- packages/docusaurus-utils/src/index.ts | 1 - .../src/client/exports/ComponentCreator.tsx | 1 - .../docusaurus/src/commands/build/build.ts | 12 +- .../src/commands/build/buildLocale.ts | 3 +- .../src/commands/build/buildUtils.ts | 18 ++ .../docusaurus/src/commands/start/utils.ts | 1 - .../configValidation.test.ts.snap | 4 +- .../__tests__/__snapshots__/site.test.ts.snap | 8 +- .../server/__tests__/configValidation.test.ts | 123 ++++++++++++- .../src/server/__tests__/i18n.test.ts | 146 ++++++++++++++- .../src/server/__tests__/site.test.ts | 2 +- .../docusaurus/src/server/configValidation.ts | 61 ++++--- packages/docusaurus/src/server/i18n.ts | 36 +++- packages/docusaurus/src/server/site.ts | 48 +++-- project-words.txt | 1 - website/docs/api/docusaurus.config.js.mdx | 33 +++- website/docs/i18n/i18n-tutorial.mdx | 41 ++++- 29 files changed, 800 insertions(+), 301 deletions(-) create mode 100644 packages/docusaurus-theme-common/src/utils/__tests__/historyUtils.test.ts create mode 100644 packages/docusaurus/src/commands/build/buildUtils.ts diff --git a/.eslintrc.js b/.eslintrc.js index 502c615068..e8e026c966 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -214,7 +214,7 @@ module.exports = { ], 'no-useless-escape': WARNING, 'no-void': [ERROR, {allowAsStatement: true}], - 'prefer-destructuring': WARNING, + 'prefer-destructuring': OFF, 'prefer-named-capture-group': WARNING, 'prefer-template': WARNING, yoda: WARNING, diff --git a/packages/docusaurus-plugin-pwa/src/registerSw.ts b/packages/docusaurus-plugin-pwa/src/registerSw.ts index d367df63a3..69a6cf3d82 100644 --- a/packages/docusaurus-plugin-pwa/src/registerSw.ts +++ b/packages/docusaurus-plugin-pwa/src/registerSw.ts @@ -9,12 +9,11 @@ import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; import {createStorageSlot} from '@docusaurus/theme-common'; // First: read the env variables (provided by Webpack) -/* eslint-disable prefer-destructuring */ + const PWA_SERVICE_WORKER_URL = process.env.PWA_SERVICE_WORKER_URL!; const PWA_OFFLINE_MODE_ACTIVATION_STRATEGIES = process.env .PWA_OFFLINE_MODE_ACTIVATION_STRATEGIES as unknown as (keyof typeof OfflineModeActivationStrategiesImplementations)[]; const PWA_DEBUG = process.env.PWA_DEBUG; -/* eslint-enable prefer-destructuring */ const MAX_MOBILE_WIDTH = 996; 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 21b14d417e..9c16b5387c 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx @@ -9,7 +9,7 @@ import React, {type ReactNode} from 'react'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import {useAlternatePageUtils} from '@docusaurus/theme-common/internal'; import {translate} from '@docusaurus/Translate'; -import {useHistorySelector} from '@docusaurus/theme-common'; +import {mergeSearchStrings, useHistorySelector} from '@docusaurus/theme-common'; import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem'; import IconLanguage from '@theme/Icon/Language'; import type {LinkLikeNavbarItemProps} from '@theme/NavbarItem'; @@ -17,31 +17,80 @@ import type {Props} from '@theme/NavbarItem/LocaleDropdownNavbarItem'; import styles from './styles.module.css'; -export default function LocaleDropdownNavbarItem({ - mobile, - dropdownItemsBefore, - dropdownItemsAfter, - queryString = '', - ...props -}: Props): ReactNode { +function useLocaleDropdownUtils() { const { - i18n: {currentLocale, locales, localeConfigs}, + siteConfig, + i18n: {localeConfigs}, } = useDocusaurusContext(); const alternatePageUtils = useAlternatePageUtils(); const search = useHistorySelector((history) => history.location.search); const hash = useHistorySelector((history) => history.location.hash); - const localeItems = locales.map((locale): LinkLikeNavbarItemProps => { - const baseTo = `pathname://${alternatePageUtils.createUrl({ + const getLocaleConfig = (locale: string) => { + const localeConfig = localeConfigs[locale]; + if (!localeConfig) { + throw new Error( + `Docusaurus bug, no locale config found for locale=${locale}`, + ); + } + return localeConfig; + }; + + const getBaseURLForLocale = (locale: string) => { + const localeConfig = getLocaleConfig(locale); + const isSameDomain = localeConfig.url === siteConfig.url; + if (isSameDomain) { + // Shorter paths if localized sites are hosted on the same domain + // This reduces HTML size a bit + return `pathname://${alternatePageUtils.createUrl({ + locale, + fullyQualified: false, + })}`; + } + return alternatePageUtils.createUrl({ locale, - fullyQualified: false, - })}`; - // preserve ?search#hash suffix on locale switches - const to = `${baseTo}${search}${hash}${queryString}`; + fullyQualified: true, + }); + }; + + return { + getURL: (locale: string, options: {queryString: string | undefined}) => { + // We have 2 query strings because + // - there's the current one + // - there's one user can provide through navbar config + // see https://github.com/facebook/docusaurus/pull/8915 + const finalSearch = mergeSearchStrings( + [search, options.queryString], + 'append', + ); + return `${getBaseURLForLocale(locale)}${finalSearch}${hash}`; + }, + getLabel: (locale: string) => { + return getLocaleConfig(locale).label; + }, + getLang: (locale: string) => { + return getLocaleConfig(locale).htmlLang; + }, + }; +} + +export default function LocaleDropdownNavbarItem({ + mobile, + dropdownItemsBefore, + dropdownItemsAfter, + queryString, + ...props +}: Props): ReactNode { + const utils = useLocaleDropdownUtils(); + + const { + i18n: {currentLocale, locales}, + } = useDocusaurusContext(); + const localeItems = locales.map((locale): LinkLikeNavbarItemProps => { return { - label: localeConfigs[locale]!.label, - lang: localeConfigs[locale]!.htmlLang, - to, + label: utils.getLabel(locale), + lang: utils.getLang(locale), + to: utils.getURL(locale, {queryString}), target: '_self', autoAddBaseUrl: false, className: @@ -66,7 +115,7 @@ export default function LocaleDropdownNavbarItem({ id: 'theme.navbar.mobileLanguageDropdown.label', description: 'The label for the mobile language switcher dropdown', }) - : localeConfigs[currentLocale]!.label; + : utils.getLabel(currentLocale); return ( { + it('can append search params', () => { + expect( + mergeSearchParams( + [ + new URLSearchParams('?key1=val1&key2=val2'), + new URLSearchParams('key2=val2-bis&key3=val3'), + new URLSearchParams(''), + new URLSearchParams('?key3=val3-bis&key4=val4'), + ], + 'append', + ).toString(), + ).toBe( + 'key1=val1&key2=val2&key2=val2-bis&key3=val3&key3=val3-bis&key4=val4', + ); + }); + + it('can overwrite search params', () => { + expect( + mergeSearchParams( + [ + new URLSearchParams('?key1=val1&key2=val2'), + new URLSearchParams('key2=val2-bis&key3=val3'), + new URLSearchParams(''), + new URLSearchParams('?key3=val3-bis&key4=val4'), + ], + 'set', + ).toString(), + ).toBe('key1=val1&key2=val2-bis&key3=val3-bis&key4=val4'); + }); +}); + +describe('mergeSearchStrings', () => { + it('can append search params', () => { + expect( + mergeSearchStrings( + [ + '?key1=val1&key2=val2', + 'key2=val2-bis&key3=val3', + '', + '?key3=val3-bis&key4=val4', + ], + 'append', + ), + ).toBe( + '?key1=val1&key2=val2&key2=val2-bis&key3=val3&key3=val3-bis&key4=val4', + ); + }); + + it('can overwrite search params', () => { + expect( + mergeSearchStrings( + [ + '?key1=val1&key2=val2', + 'key2=val2-bis&key3=val3', + '', + '?key3=val3-bis&key4=val4', + ], + 'set', + ), + ).toBe('?key1=val1&key2=val2-bis&key3=val3-bis&key4=val4'); + }); + + it('automatically adds ? if there are params', () => { + expect(mergeSearchStrings(['key1=val1'], 'append')).toBe('?key1=val1'); + }); + + it('automatically removes ? if there are no params', () => { + expect(mergeSearchStrings([undefined, ''], 'append')).toBe(''); + }); +}); diff --git a/packages/docusaurus-theme-common/src/utils/__tests__/useAlternatePageUtils.test.tsx b/packages/docusaurus-theme-common/src/utils/__tests__/useAlternatePageUtils.test.tsx index fb964b015f..a16832a648 100644 --- a/packages/docusaurus-theme-common/src/utils/__tests__/useAlternatePageUtils.test.tsx +++ b/packages/docusaurus-theme-common/src/utils/__tests__/useAlternatePageUtils.test.tsx @@ -9,116 +9,185 @@ import React from 'react'; import {renderHook} from '@testing-library/react-hooks'; import {StaticRouter} from 'react-router-dom'; import {Context} from '@docusaurus/core/src/client/docusaurusContext'; +import {fromPartial} from '@total-typescript/shoehorn'; import {useAlternatePageUtils} from '../useAlternatePageUtils'; import type {DocusaurusContext} from '@docusaurus/types'; describe('useAlternatePageUtils', () => { - const createUseAlternatePageUtilsMock = - (context: DocusaurusContext) => (location: string) => - renderHook(() => useAlternatePageUtils(), { - wrapper: ({children}) => ( - - {children} - - ), - }).result.current; - it('works for baseUrl: / and currentLocale = defaultLocale', () => { - const mockUseAlternatePageUtils = createUseAlternatePageUtilsMock({ - siteConfig: {baseUrl: '/', url: 'https://example.com'}, - i18n: {defaultLocale: 'en', currentLocale: 'en'}, - } as DocusaurusContext); + const createTestUtils = (context: DocusaurusContext) => { + return { + forLocation: (location: string) => { + return renderHook(() => useAlternatePageUtils(), { + wrapper: ({children}) => ( + + {children} + + ), + }).result.current; + }, + }; + }; + + it('works for baseUrl: / and currentLocale === defaultLocale', () => { + const testUtils = createTestUtils( + fromPartial({ + siteConfig: { + url: 'https://example.com', + baseUrl: '/', + }, + i18n: { + defaultLocale: 'en', + currentLocale: 'en', + localeConfigs: { + en: { + url: 'https://example.com', + baseUrl: '/', + }, + 'zh-Hans': { + url: 'https://zh.example.com', + baseUrl: '/zh-Hans-baseUrl/', + }, + }, + }, + }), + ); + expect( - mockUseAlternatePageUtils('/').createUrl({ + testUtils.forLocation('/').createUrl({ locale: 'zh-Hans', fullyQualified: false, }), - ).toBe('/zh-Hans/'); + ).toBe('/zh-Hans-baseUrl/'); expect( - mockUseAlternatePageUtils('/foo').createUrl({ + testUtils.forLocation('/foo').createUrl({ locale: 'zh-Hans', fullyQualified: false, }), - ).toBe('/zh-Hans/foo'); + ).toBe('/zh-Hans-baseUrl/foo'); expect( - mockUseAlternatePageUtils('/foo').createUrl({ + testUtils.forLocation('/foo').createUrl({ locale: 'zh-Hans', fullyQualified: true, }), - ).toBe('https://example.com/zh-Hans/foo'); + ).toBe('https://zh.example.com/zh-Hans-baseUrl/foo'); }); - it('works for baseUrl: / and currentLocale /= defaultLocale', () => { - const mockUseAlternatePageUtils = createUseAlternatePageUtilsMock({ - siteConfig: {baseUrl: '/zh-Hans/', url: 'https://example.com'}, - i18n: {defaultLocale: 'en', currentLocale: 'zh-Hans'}, - } as DocusaurusContext); + it('works for baseUrl: / and currentLocale !== defaultLocale', () => { + const testUtils = createTestUtils( + fromPartial({ + siteConfig: { + url: 'https://zh.example.com', + baseUrl: '/zh-Hans-baseUrl/', + }, + i18n: { + defaultLocale: 'en', + currentLocale: 'zh-Hans', + localeConfigs: { + en: {url: 'https://example.com', baseUrl: '/'}, + 'zh-Hans': { + url: 'https://zh.example.com', + baseUrl: '/zh-Hans-baseUrl/', + }, + }, + }, + }), + ); + expect( - mockUseAlternatePageUtils('/zh-Hans/').createUrl({ + testUtils.forLocation('/zh-Hans-baseUrl/').createUrl({ locale: 'en', fullyQualified: false, }), ).toBe('/'); expect( - mockUseAlternatePageUtils('/zh-Hans/foo').createUrl({ + testUtils.forLocation('/zh-Hans-baseUrl/foo').createUrl({ locale: 'en', fullyQualified: false, }), ).toBe('/foo'); expect( - mockUseAlternatePageUtils('/zh-Hans/foo').createUrl({ + testUtils.forLocation('/zh-Hans-baseUrl/foo').createUrl({ locale: 'en', fullyQualified: true, }), ).toBe('https://example.com/foo'); }); - it('works for non-root base URL and currentLocale = defaultLocale', () => { - const mockUseAlternatePageUtils = createUseAlternatePageUtilsMock({ - siteConfig: {baseUrl: '/base/', url: 'https://example.com'}, - i18n: {defaultLocale: 'en', currentLocale: 'en'}, - } as DocusaurusContext); + it('works for non-root base URL and currentLocale === defaultLocale', () => { + const testUtils = createTestUtils( + fromPartial({ + siteConfig: {baseUrl: '/en/', url: 'https://example.com'}, + i18n: { + defaultLocale: 'en', + currentLocale: 'en', + localeConfigs: { + en: {url: 'https://example.com', baseUrl: '/base/'}, + 'zh-Hans': { + url: 'https://zh.example.com', + baseUrl: '/zh-Hans-baseUrl/', + }, + }, + }, + }), + ); expect( - mockUseAlternatePageUtils('/base/').createUrl({ + testUtils.forLocation('/en/').createUrl({ locale: 'zh-Hans', fullyQualified: false, }), - ).toBe('/base/zh-Hans/'); + ).toBe('/zh-Hans-baseUrl/'); expect( - mockUseAlternatePageUtils('/base/foo').createUrl({ + testUtils.forLocation('/en/foo').createUrl({ locale: 'zh-Hans', fullyQualified: false, }), - ).toBe('/base/zh-Hans/foo'); + ).toBe('/zh-Hans-baseUrl/foo'); expect( - mockUseAlternatePageUtils('/base/foo').createUrl({ + testUtils.forLocation('/en/foo').createUrl({ locale: 'zh-Hans', fullyQualified: true, }), - ).toBe('https://example.com/base/zh-Hans/foo'); + ).toBe('https://zh.example.com/zh-Hans-baseUrl/foo'); }); - it('works for non-root base URL and currentLocale /= defaultLocale', () => { - const mockUseAlternatePageUtils = createUseAlternatePageUtilsMock({ - siteConfig: {baseUrl: '/base/zh-Hans/', url: 'https://example.com'}, - i18n: {defaultLocale: 'en', currentLocale: 'zh-Hans'}, - } as DocusaurusContext); + it('works for non-root base URL and currentLocale !== defaultLocale', () => { + const testUtils = createTestUtils( + fromPartial({ + siteConfig: { + baseUrl: '/zh-Hans-baseUrl/', + url: 'https://zh.example.com', + }, + i18n: { + defaultLocale: 'en', + currentLocale: 'zh-Hans', + localeConfigs: { + en: {url: 'https://en.example.com', baseUrl: '/en/'}, + 'zh-Hans': { + url: 'https://zh.example.com', + baseUrl: '/zh-Hans-baseUrl/', + }, + }, + }, + }), + ); + expect( - mockUseAlternatePageUtils('/base/zh-Hans/').createUrl({ + testUtils.forLocation('/zh-Hans-baseUrl/').createUrl({ locale: 'en', fullyQualified: false, }), - ).toBe('/base/'); + ).toBe('/en/'); expect( - mockUseAlternatePageUtils('/base/zh-Hans/foo').createUrl({ + testUtils.forLocation('/zh-Hans-baseUrl/foo').createUrl({ locale: 'en', fullyQualified: false, }), - ).toBe('/base/foo'); + ).toBe('/en/foo'); expect( - mockUseAlternatePageUtils('/base/zh-Hans/foo').createUrl({ + testUtils.forLocation('/zh-Hans-baseUrl/foo').createUrl({ locale: 'en', fullyQualified: true, }), - ).toBe('https://example.com/base/foo'); + ).toBe('https://en.example.com/en/foo'); }); }); diff --git a/packages/docusaurus-theme-common/src/utils/historyUtils.ts b/packages/docusaurus-theme-common/src/utils/historyUtils.ts index eea45351d8..45f9cc22dd 100644 --- a/packages/docusaurus-theme-common/src/utils/historyUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/historyUtils.ts @@ -168,3 +168,32 @@ export function useClearQueryString(): () => void { }); }, [history]); } + +export function mergeSearchParams( + params: URLSearchParams[], + strategy: 'append' | 'set', +): URLSearchParams { + const result = new URLSearchParams(); + for (const item of params) { + for (const [key, value] of item.entries()) { + if (strategy === 'append') { + result.append(key, value); + } else { + result.set(key, value); + } + } + } + return result; +} + +export function mergeSearchStrings( + searchStrings: (string | undefined)[], + strategy: 'append' | 'set', +): string { + const params = mergeSearchParams( + searchStrings.map((s) => new URLSearchParams(s ?? '')), + strategy, + ); + const str = params.toString(); + return str ? `?${str}` : str; +} diff --git a/packages/docusaurus-theme-common/src/utils/useAlternatePageUtils.ts b/packages/docusaurus-theme-common/src/utils/useAlternatePageUtils.ts index 073aa8956f..fd537163f1 100644 --- a/packages/docusaurus-theme-common/src/utils/useAlternatePageUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/useAlternatePageUtils.ts @@ -8,6 +8,7 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import {useLocation} from '@docusaurus/router'; import {applyTrailingSlash} from '@docusaurus/utils-common'; +import type {I18nLocaleConfig} from '@docusaurus/types'; /** * Permits to obtain the url of the current page in another locale, useful to @@ -36,8 +37,8 @@ export function useAlternatePageUtils(): { }) => string; } { const { - siteConfig: {baseUrl, url, trailingSlash}, - i18n: {defaultLocale, currentLocale}, + siteConfig: {baseUrl, trailingSlash}, + i18n: {localeConfigs}, } = useDocusaurusContext(); // TODO using useLocation().pathname is not a super idea @@ -49,21 +50,19 @@ export function useAlternatePageUtils(): { baseUrl, }); - const baseUrlUnlocalized = - currentLocale === defaultLocale - ? baseUrl - : baseUrl.replace(`/${currentLocale}/`, '/'); - + // Canonical pathname, without the baseUrl of the current locale const pathnameSuffix = canonicalPathname.replace(baseUrl, ''); - function getLocalizedBaseUrl(locale: string) { - return locale === defaultLocale - ? `${baseUrlUnlocalized}` - : `${baseUrlUnlocalized}${locale}/`; + function getLocaleConfig(locale: string): I18nLocaleConfig { + const localeConfig = localeConfigs[locale]; + if (!localeConfig) { + throw new Error( + `Unexpected Docusaurus bug, no locale config found for locale=${locale}`, + ); + } + return localeConfig; } - // TODO support correct alternate url when localized site is deployed on - // another domain function createUrl({ locale, fullyQualified, @@ -71,9 +70,10 @@ export function useAlternatePageUtils(): { locale: string; fullyQualified: boolean; }) { - return `${fullyQualified ? url : ''}${getLocalizedBaseUrl( - locale, - )}${pathnameSuffix}`; + const localeConfig = getLocaleConfig(locale); + const newUrl = `${fullyQualified ? localeConfig.url : ''}`; + const newBaseUrl = localeConfig.baseUrl; + return `${newUrl}${newBaseUrl}${pathnameSuffix}`; } return {createUrl}; diff --git a/packages/docusaurus-types/src/i18n.d.ts b/packages/docusaurus-types/src/i18n.d.ts index ea834788e5..5f1541a5b2 100644 --- a/packages/docusaurus-types/src/i18n.d.ts +++ b/packages/docusaurus-types/src/i18n.d.ts @@ -37,6 +37,25 @@ export type I18nLocaleConfig = { * By default, it will only be run if the `./i18n/` exists. */ translate: boolean; + + /** + * For i18n sites deployed to distinct domains, it is recommended to configure + * a site url on a per-locale basis. + */ + url: string; + + /** + * An explicit baseUrl to use for this locale, overriding the default one: + * Default values: + * - Default locale: `/${siteConfig.baseUrl}/` + * - Other locales: `/${siteConfig.baseUrl}//` + * + * Exception: when using the CLI with a single `--locale` parameter, the + * `//` path segment is not included. This is a better default for + * sites looking to deploy each locale to a different subdomain, such as + * `https://.docusaurus.io` + */ + baseUrl: string; }; export type I18nConfig = { diff --git a/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts b/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts index 527aa21379..7786001643 100644 --- a/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/i18nUtils.test.ts @@ -5,12 +5,10 @@ * LICENSE file in the root directory of this source tree. */ -import * as path from 'path'; import { mergeTranslations, updateTranslationFileMessages, getPluginI18nPath, - localizePath, getLocaleConfig, } from '../i18nUtils'; import type {I18n, I18nLocaleConfig} from '@docusaurus/types'; @@ -97,91 +95,6 @@ describe('getPluginI18nPath', () => { }); }); -describe('localizePath', () => { - it('localizes url path with current locale', () => { - expect( - localizePath({ - pathType: 'url', - path: '/baseUrl', - i18n: { - defaultLocale: 'en', - path: 'i18n', - locales: ['en', 'fr'], - currentLocale: 'fr', - localeConfigs: {}, - }, - options: {localizePath: true}, - }), - ).toBe('/baseUrl/fr/'); - }); - - it('localizes fs path with current locale', () => { - expect( - localizePath({ - pathType: 'fs', - path: '/baseFsPath', - i18n: { - defaultLocale: 'en', - path: 'i18n', - locales: ['en', 'fr'], - currentLocale: 'fr', - localeConfigs: {fr: {path: 'fr'}, en: {path: 'en'}}, - }, - options: {localizePath: true}, - }), - ).toBe(`${path.sep}baseFsPath${path.sep}fr`); - }); - - it('localizes path for default locale, if requested', () => { - expect( - localizePath({ - pathType: 'url', - path: '/baseUrl/', - i18n: { - defaultLocale: 'en', - path: 'i18n', - locales: ['en', 'fr'], - currentLocale: 'en', - localeConfigs: {fr: {path: 'fr'}, en: {path: 'en'}}, - }, - options: {localizePath: true}, - }), - ).toBe('/baseUrl/en/'); - }); - - it('does not localize path for default locale by default', () => { - expect( - localizePath({ - pathType: 'url', - path: '/baseUrl/', - i18n: { - defaultLocale: 'en', - path: 'i18n', - locales: ['en', 'fr'], - currentLocale: 'en', - localeConfigs: {fr: {path: 'fr'}, en: {path: 'en'}}, - }, - }), - ).toBe('/baseUrl/'); - }); - - it('localizes path for non-default locale by default', () => { - expect( - localizePath({ - pathType: 'url', - path: '/baseUrl/', - i18n: { - defaultLocale: 'en', - path: 'i18n', - locales: ['en', 'fr'], - currentLocale: 'en', - localeConfigs: {fr: {path: 'fr'}, en: {path: 'en'}}, - }, - }), - ).toBe('/baseUrl/'); - }); -}); - describe('getLocaleConfig', () => { const localeConfigEn: I18nLocaleConfig = { path: 'path', @@ -190,6 +103,7 @@ describe('getLocaleConfig', () => { calendar: 'calendar', label: 'EN', translate: true, + baseUrl: '/', }; const localeConfigFr: I18nLocaleConfig = { path: 'path', @@ -198,6 +112,7 @@ describe('getLocaleConfig', () => { calendar: 'calendar', label: 'FR', translate: true, + baseUrl: '/fr/', }; function i18n(params: Partial): I18n { diff --git a/packages/docusaurus-utils/src/i18nUtils.ts b/packages/docusaurus-utils/src/i18nUtils.ts index 8e7080b962..3c92381521 100644 --- a/packages/docusaurus-utils/src/i18nUtils.ts +++ b/packages/docusaurus-utils/src/i18nUtils.ts @@ -9,7 +9,6 @@ import path from 'path'; import _ from 'lodash'; import logger from '@docusaurus/logger'; import {DEFAULT_PLUGIN_ID} from './constants'; -import {normalizeUrl} from './urlUtils'; import type { TranslationFileContent, TranslationFile, @@ -67,54 +66,6 @@ export function getPluginI18nPath({ ); } -/** - * Takes a path and returns a localized a version (which is basically `path + - * i18n.currentLocale`). - * - * This is used to resolve the `outDir` and `baseUrl` of each locale; it is NOT - * used to determine plugin localization file locations. - */ -export function localizePath({ - pathType, - path: originalPath, - i18n, - options = {}, -}: { - /** - * FS paths will treat Windows specially; URL paths will always have a - * trailing slash to make it a valid base URL. - */ - pathType: 'fs' | 'url'; - /** The path, URL or file path, to be localized. */ - path: string; - /** The current i18n context. */ - i18n: I18n; - options?: { - /** - * By default, we don't localize the path of defaultLocale. This option - * would override that behavior. Setting `false` is useful for `yarn build - * -l zh-Hans` to always emit into the root build directory. - */ - localizePath?: boolean; - }; -}): string { - const shouldLocalizePath: boolean = - options.localizePath ?? i18n.currentLocale !== i18n.defaultLocale; - - if (!shouldLocalizePath) { - return originalPath; - } - // FS paths need special care, for Windows support. Note: we don't use the - // locale config's `path` here, because this function is used for resolving - // outDir, which must be the same as baseUrl. When we have the baseUrl config, - // we need to sync the two. - if (pathType === 'fs') { - return path.join(originalPath, i18n.currentLocale); - } - // Url paths; add a trailing slash so it's a valid base URL - return normalizeUrl([originalPath, i18n.currentLocale, '/']); -} - // TODO we may extract this to a separate package // we want to use it on the frontend too // but "docusaurus-utils-common" (agnostic utils) is not an ideal place since diff --git a/packages/docusaurus-utils/src/index.ts b/packages/docusaurus-utils/src/index.ts index 74b66ca3a9..9370af8885 100644 --- a/packages/docusaurus-utils/src/index.ts +++ b/packages/docusaurus-utils/src/index.ts @@ -33,7 +33,6 @@ export { mergeTranslations, updateTranslationFileMessages, getPluginI18nPath, - localizePath, getLocaleConfig, } from './i18nUtils'; export {mapAsyncSequential, findAsyncSequential} from './jsUtils'; diff --git a/packages/docusaurus/src/client/exports/ComponentCreator.tsx b/packages/docusaurus/src/client/exports/ComponentCreator.tsx index e0664bec5e..48d6640385 100644 --- a/packages/docusaurus/src/client/exports/ComponentCreator.tsx +++ b/packages/docusaurus/src/client/exports/ComponentCreator.tsx @@ -60,7 +60,6 @@ export default function ComponentCreator( Object.entries(flatChunkNames).forEach(([keyPath, chunkName]) => { const chunkRegistry = registry[chunkName]; if (chunkRegistry) { - // eslint-disable-next-line prefer-destructuring loader[keyPath] = chunkRegistry[0]; modules.push(chunkRegistry[1]); optsWebpack.push(chunkRegistry[2]); diff --git a/packages/docusaurus/src/commands/build/build.ts b/packages/docusaurus/src/commands/build/build.ts index 4bfea69201..c3baf7940b 100644 --- a/packages/docusaurus/src/commands/build/build.ts +++ b/packages/docusaurus/src/commands/build/build.ts @@ -11,6 +11,7 @@ import {mapAsyncSequential} from '@docusaurus/utils'; import {loadContext, type LoadContextParams} from '../../server/site'; import {loadI18n} from '../../server/i18n'; import {buildLocale, type BuildLocaleParams} from './buildLocale'; +import {isAutomaticBaseUrlLocalizationDisabled} from './buildUtils'; export type BuildCLIOptions = Pick & { locale?: [string, ...string[]]; @@ -80,21 +81,20 @@ async function getLocalesToBuild({ siteDir: string; cliOptions: BuildCLIOptions; }): Promise<[string, ...string[]]> { - // We disable locale path localization if CLI has single "--locale" option - // yarn build --locale fr => baseUrl=/ instead of baseUrl=/fr/ - const localizePath = cliOptions.locale?.length === 1 ? false : undefined; - + // TODO we shouldn't need to load all context + i18n just to get that list + // only loading siteConfig should be enough const context = await loadContext({ siteDir, outDir: cliOptions.outDir, config: cliOptions.config, - localizePath, + automaticBaseUrlLocalizationDisabled: isAutomaticBaseUrlLocalizationDisabled(cliOptions), }); const i18n = await loadI18n({ siteDir, config: context.siteConfig, - currentLocale: context.siteConfig.i18n.defaultLocale // Awkward but ok + currentLocale: context.siteConfig.i18n.defaultLocale, // Awkward but ok + automaticBaseUrlLocalizationDisabled: false, }); const locales = cliOptions.locale ?? i18n.locales; diff --git a/packages/docusaurus/src/commands/build/buildLocale.ts b/packages/docusaurus/src/commands/build/buildLocale.ts index 33ae8d346e..8173991ba1 100644 --- a/packages/docusaurus/src/commands/build/buildLocale.ts +++ b/packages/docusaurus/src/commands/build/buildLocale.ts @@ -27,6 +27,7 @@ import type { import type {SiteCollectedData} from '../../common'; import {BuildCLIOptions} from './build'; import clearPath from '../utils/clearPath'; +import {isAutomaticBaseUrlLocalizationDisabled} from './buildUtils'; export type BuildLocaleParams = { siteDir: string; @@ -56,7 +57,7 @@ export async function buildLocale({ outDir: cliOptions.outDir, config: cliOptions.config, locale, - localizePath: cliOptions.locale?.length === 1 ? false : undefined, + automaticBaseUrlLocalizationDisabled: isAutomaticBaseUrlLocalizationDisabled(cliOptions), }), ); diff --git a/packages/docusaurus/src/commands/build/buildUtils.ts b/packages/docusaurus/src/commands/build/buildUtils.ts new file mode 100644 index 0000000000..4421c2646d --- /dev/null +++ b/packages/docusaurus/src/commands/build/buildUtils.ts @@ -0,0 +1,18 @@ +/** + * 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 {BuildCLIOptions} from './build'; + +/** + * We disable locale path localization if CLI has a single "--locale" option + * yarn build --locale fr => baseUrl=/ instead of baseUrl=/fr/ + * By default, this makes it easier to support multi-domain deployments + * See https://docusaurus.io/docs/i18n/tutorial#multi-domain-deployment + */ +export function isAutomaticBaseUrlLocalizationDisabled(cliOptions: BuildCLIOptions) { + return cliOptions.locale?.length === 1; +} diff --git a/packages/docusaurus/src/commands/start/utils.ts b/packages/docusaurus/src/commands/start/utils.ts index 4c2b3fdf15..505c701a7f 100644 --- a/packages/docusaurus/src/commands/start/utils.ts +++ b/packages/docusaurus/src/commands/start/utils.ts @@ -90,7 +90,6 @@ async function createLoadSiteParams({ siteDir, config: cliOptions.config, locale: cliOptions.locale, - localizePath: undefined, // Should this be configurable? }; } diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/configValidation.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/configValidation.test.ts.snap index d298a46eb8..c1fea8b6ec 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/configValidation.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/configValidation.test.ts.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`normalizeConfig throws error for required fields 1`] = ` -""baseUrl" is required +""url" is required +"baseUrl" is required "title" is required -"url" is required "themes" must be an array "presets" must be an array "scripts" must be an array diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap index 4b335e062b..b6b28fc939 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap @@ -15,20 +15,24 @@ exports[`load loads props for site 1`] = ` "defaultLocale": "en", "localeConfigs": { "en": { + "baseUrl": "/", "calendar": "gregory", "direction": "ltr", "htmlLang": "en", "label": "English", "path": "en-custom", "translate": false, + "url": "https://example.com", }, "zh-Hans": { + "baseUrl": "/zh-Hans/", "calendar": "gregory", "direction": "ltr", "htmlLang": "zh-Hans", "label": "简体中文", "path": "zh-Hans-custom", "translate": true, + "url": "https://example.com", }, }, "locales": [ @@ -38,7 +42,7 @@ exports[`load loads props for site 1`] = ` "path": "i18n", }, "localizationDir": "/packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site/i18n/en-custom", - "outDir": "/packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site/build", + "outDir": "/packages/docusaurus/src/server/__tests__/__fixtures__/custom-i18n-site/build/", "plugins": [ { "content": undefined, @@ -109,11 +113,9 @@ exports[`load loads props for site 1`] = ` "defaultLocale": "en", "localeConfigs": { "en": { - "direction": "ltr", "path": "en-custom", }, "zh-Hans": { - "direction": "ltr", "path": "zh-Hans-custom", }, }, diff --git a/packages/docusaurus/src/server/__tests__/configValidation.test.ts b/packages/docusaurus/src/server/__tests__/configValidation.test.ts index aaad1d3bae..815857d1ff 100644 --- a/packages/docusaurus/src/server/__tests__/configValidation.test.ts +++ b/packages/docusaurus/src/server/__tests__/configValidation.test.ts @@ -27,6 +27,8 @@ import type { Config, DocusaurusConfig, PluginConfig, + I18nConfig, + I18nLocaleConfig, } from '@docusaurus/types'; import type {DeepPartial} from 'utility-types'; @@ -366,6 +368,115 @@ describe('onBrokenLinks', () => { }); }); +describe('i18n', () => { + function normalizeI18n(i18n: DeepPartial): I18nConfig { + return normalizeConfig({i18n}).i18n; + } + + it('accepts undefined object', () => { + expect(normalizeI18n(undefined)).toEqual(DEFAULT_CONFIG.i18n); + }); + + it('rejects empty object', () => { + expect(() => normalizeI18n({})).toThrowErrorMatchingInlineSnapshot(` + ""i18n.defaultLocale" is required + "i18n.locales" is required + " + `); + }); + + it('accepts minimal i18n config', () => { + expect(normalizeI18n({defaultLocale: 'fr', locales: ['fr']})).toEqual({ + defaultLocale: 'fr', + localeConfigs: {}, + locales: ['fr'], + path: 'i18n', + }); + }); + + describe('locale config', () => { + function normalizeLocaleConfig( + localeConfig?: Partial, + ): Partial { + return normalizeConfig({ + i18n: { + defaultLocale: 'fr', + locales: ['fr'], + localeConfigs: { + fr: localeConfig, + }, + }, + }).i18n.localeConfigs.fr; + } + + it('accepts undefined locale config', () => { + expect(normalizeLocaleConfig(undefined)).toBeUndefined(); + }); + + it('accepts empty locale config', () => { + expect(normalizeLocaleConfig({})).toEqual({}); + }); + + describe('url', () => { + it('accepts undefined', () => { + expect(normalizeLocaleConfig({url: undefined})).toEqual({ + url: undefined, + }); + }); + + it('rejects empty', () => { + expect(() => normalizeLocaleConfig({url: ''})) + .toThrowErrorMatchingInlineSnapshot(` + ""i18n.localeConfigs.fr.url" is not allowed to be empty + " + `); + }); + + it('accepts valid url', () => { + expect( + normalizeLocaleConfig({url: 'https://fr.docusaurus.io'}), + ).toEqual({ + url: 'https://fr.docusaurus.io', + }); + }); + + it('accepts valid url and removes trailing slash', () => { + expect( + normalizeLocaleConfig({url: 'https://fr.docusaurus.io/'}), + ).toEqual({ + url: 'https://fr.docusaurus.io', + }); + }); + }); + + describe('baseUrl', () => { + it('accepts undefined baseUrl', () => { + expect(normalizeLocaleConfig({baseUrl: undefined})).toEqual({ + baseUrl: undefined, + }); + }); + + it('accepts empty baseUrl', () => { + expect(normalizeLocaleConfig({baseUrl: ''})).toEqual({ + baseUrl: '/', + }); + }); + + it('accepts regular baseUrl', () => { + expect(normalizeLocaleConfig({baseUrl: '/myBase/Url/'})).toEqual({ + baseUrl: '/myBase/Url/', + }); + }); + + it('accepts baseUrl without leading/trailing slashes', () => { + expect(normalizeLocaleConfig({baseUrl: 'myBase/Url'})).toEqual({ + baseUrl: '/myBase/Url/', + }); + }); + }); + }); +}); + describe('markdown', () => { function normalizeMarkdown( markdown: DeepPartial, @@ -508,9 +619,9 @@ describe('markdown', () => { emoji: 'yes', }), ).toThrowErrorMatchingInlineSnapshot(` - ""markdown.emoji" must be a boolean - " - `); + ""markdown.emoji" must be a boolean + " + `); }); it('throw for number emoji value', () => { @@ -522,9 +633,9 @@ describe('markdown', () => { }, }), ).toThrowErrorMatchingInlineSnapshot(` - ""markdown.emoji" must be a boolean - " - `); + ""markdown.emoji" must be a boolean + " + `); }); }); diff --git a/packages/docusaurus/src/server/__tests__/i18n.test.ts b/packages/docusaurus/src/server/__tests__/i18n.test.ts index fb075d8b2b..d7af30b224 100644 --- a/packages/docusaurus/src/server/__tests__/i18n.test.ts +++ b/packages/docusaurus/src/server/__tests__/i18n.test.ts @@ -17,21 +17,31 @@ const loadI18nSiteDir = path.resolve( 'load-i18n-site', ); +const siteUrl = 'https://example.com'; + function loadI18nTest({ siteDir = loadI18nSiteDir, + baseUrl = '/', i18nConfig, currentLocale, + automaticBaseUrlLocalizationDisabled, }: { siteDir?: string; + baseUrl?: string; i18nConfig: I18nConfig; currentLocale: string; + automaticBaseUrlLocalizationDisabled?: boolean; }) { return loadI18n({ siteDir, config: { i18n: i18nConfig, + url: siteUrl, + baseUrl, } as DocusaurusConfig, currentLocale, + automaticBaseUrlLocalizationDisabled: + automaticBaseUrlLocalizationDisabled ?? false, }); } @@ -133,6 +143,8 @@ describe('loadI18n', () => { en: { ...getDefaultLocaleConfig('en'), translate: false, + url: siteUrl, + baseUrl: '/', }, }, }); @@ -158,14 +170,60 @@ describe('loadI18n', () => { en: { ...getDefaultLocaleConfig('en'), translate: false, + url: siteUrl, + baseUrl: '/en/', }, fr: { ...getDefaultLocaleConfig('fr'), translate: true, + url: siteUrl, + baseUrl: '/', }, de: { ...getDefaultLocaleConfig('de'), translate: true, + url: siteUrl, + baseUrl: '/de/', + }, + }, + }); + }); + + it('loads I18n for multi-lang config - with automaticBaseUrlLocalizationDisabled=true', async () => { + await expect( + loadI18nTest({ + i18nConfig: { + path: 'i18n', + defaultLocale: 'fr', + locales: ['en', 'fr', 'de'], + localeConfigs: {}, + }, + currentLocale: 'fr', + automaticBaseUrlLocalizationDisabled: true, + }), + ).resolves.toEqual({ + defaultLocale: 'fr', + path: 'i18n', + locales: ['en', 'fr', 'de'], + currentLocale: 'fr', + localeConfigs: { + en: { + ...getDefaultLocaleConfig('en'), + translate: false, + url: siteUrl, + baseUrl: '/', + }, + fr: { + ...getDefaultLocaleConfig('fr'), + translate: true, + url: siteUrl, + baseUrl: '/', + }, + de: { + ...getDefaultLocaleConfig('de'), + translate: true, + url: siteUrl, + baseUrl: '/', }, }, }); @@ -191,14 +249,20 @@ describe('loadI18n', () => { en: { ...getDefaultLocaleConfig('en'), translate: false, + url: siteUrl, + baseUrl: '/en/', }, fr: { ...getDefaultLocaleConfig('fr'), translate: true, + url: siteUrl, + baseUrl: '/', }, de: { ...getDefaultLocaleConfig('de'), translate: true, + url: siteUrl, + baseUrl: '/de/', }, }, }); @@ -213,10 +277,11 @@ describe('loadI18n', () => { locales: ['en', 'fr', 'de'], localeConfigs: { fr: {label: 'Français', translate: false}, - en: {translate: true}, - de: {translate: false}, + en: {translate: true, baseUrl: 'en-EN/whatever/else'}, + de: {translate: false, baseUrl: '/de-DE/'}, }, }, + currentLocale: 'de', }), ).resolves.toEqual({ @@ -232,19 +297,96 @@ describe('loadI18n', () => { calendar: 'gregory', path: 'fr', translate: false, + url: siteUrl, + baseUrl: '/', }, en: { ...getDefaultLocaleConfig('en'), translate: true, + url: siteUrl, + baseUrl: '/en-EN/whatever/else/', }, de: { ...getDefaultLocaleConfig('de'), translate: false, + url: siteUrl, + baseUrl: '/de-DE/', }, }, }); }); + it('loads I18n for multi-locale config with baseUrl edge cases', async () => { + await expect( + loadI18nTest({ + baseUrl: 'siteBaseUrl', + i18nConfig: { + path: 'i18n', + defaultLocale: 'fr', + locales: ['en', 'fr', 'de', 'pt'], + localeConfigs: { + fr: {}, + en: {baseUrl: ''}, + de: {baseUrl: '/de-DE/'}, + }, + }, + currentLocale: 'de', + }), + ).resolves.toEqual( + expect.objectContaining({ + localeConfigs: { + fr: expect.objectContaining({ + baseUrl: '/siteBaseUrl/', + }), + en: expect.objectContaining({ + baseUrl: '/', + }), + de: expect.objectContaining({ + baseUrl: '/de-DE/', + }), + pt: expect.objectContaining({ + baseUrl: '/siteBaseUrl/pt/', + }), + }, + }), + ); + }); + + it('loads I18n for multi-locale config with custom urls', async () => { + await expect( + loadI18nTest({ + baseUrl: 'siteBaseUrl', + i18nConfig: { + path: 'i18n', + defaultLocale: 'fr', + locales: ['en', 'fr', 'de', 'pt'], + localeConfigs: { + fr: {url: 'https://fr.example.com'}, + en: {url: 'https://en.example.com'}, + }, + }, + currentLocale: 'de', + }), + ).resolves.toEqual( + expect.objectContaining({ + localeConfigs: { + fr: expect.objectContaining({ + url: 'https://fr.example.com', + }), + en: expect.objectContaining({ + url: 'https://en.example.com', + }), + de: expect.objectContaining({ + url: siteUrl, + }), + pt: expect.objectContaining({ + url: siteUrl, + }), + }, + }), + ); + }); + it('warns when trying to load undeclared locale', async () => { await loadI18nTest({ i18nConfig: { diff --git a/packages/docusaurus/src/server/__tests__/site.test.ts b/packages/docusaurus/src/server/__tests__/site.test.ts index 7ce18bfa4d..e62d721035 100644 --- a/packages/docusaurus/src/server/__tests__/site.test.ts +++ b/packages/docusaurus/src/server/__tests__/site.test.ts @@ -28,7 +28,7 @@ describe('load', () => { ), outDir: path.join( __dirname, - '__fixtures__/custom-i18n-site/build/zh-Hans', + '__fixtures__/custom-i18n-site/build/zh-Hans/', ), routesPaths: ['/zh-Hans/404.html'], siteConfig: expect.objectContaining({ diff --git a/packages/docusaurus/src/server/configValidation.ts b/packages/docusaurus/src/server/configValidation.ts index d62e7b14c8..5f6059bfa6 100644 --- a/packages/docusaurus/src/server/configValidation.ts +++ b/packages/docusaurus/src/server/configValidation.ts @@ -26,10 +26,36 @@ import type { I18nConfig, MarkdownConfig, MarkdownHooks, + I18nLocaleConfig, } from '@docusaurus/types'; const DEFAULT_I18N_LOCALE = 'en'; +const SiteUrlSchema = Joi.string() + .custom((value: string, helpers) => { + try { + const {pathname} = new URL(value); + if (pathname !== '/') { + return helpers.error('docusaurus.subPathError', {pathname}); + } + } catch { + return helpers.error('any.invalid'); + } + return removeTrailingSlash(value); + }) + .messages({ + 'any.invalid': + '"{#value}" does not look like a valid URL. Make sure it has a protocol; for example, "https://example.com".', + 'docusaurus.subPathError': + 'The url is not supposed to contain a sub-path like "{#pathname}". Please use the baseUrl field for sub-paths.', + }); + +const BaseUrlSchema = Joi + // Weird Joi trick needed, otherwise value '' is not normalized... + .alternatives() + .try(Joi.string().required().allow('')) + .custom((value: string) => addLeadingSlash(addTrailingSlash(value))); + export const DEFAULT_I18N_CONFIG: I18nConfig = { defaultLocale: DEFAULT_I18N_LOCALE, path: DEFAULT_I18N_DIR_NAME, @@ -220,12 +246,14 @@ const PresetSchema = Joi.alternatives() - A simple string, like \`"classic"\``, }); -const LocaleConfigSchema = Joi.object({ +const LocaleConfigSchema = Joi.object({ label: Joi.string(), htmlLang: Joi.string(), - direction: Joi.string().equal('ltr', 'rtl').default('ltr'), + direction: Joi.string().equal('ltr', 'rtl'), calendar: Joi.string(), path: Joi.string(), + url: SiteUrlSchema, + baseUrl: BaseUrlSchema, }); const I18N_CONFIG_SCHEMA = Joi.object({ @@ -313,38 +341,13 @@ const FUTURE_CONFIG_SCHEMA = Joi.object({ .optional() .default(DEFAULT_FUTURE_CONFIG); -const SiteUrlSchema = Joi.string() - .required() - .custom((value: string, helpers) => { - try { - const {pathname} = new URL(value); - if (pathname !== '/') { - return helpers.error('docusaurus.subPathError', {pathname}); - } - } catch { - return helpers.error('any.invalid'); - } - return removeTrailingSlash(value); - }) - .messages({ - 'any.invalid': - '"{#value}" does not look like a valid URL. Make sure it has a protocol; for example, "https://example.com".', - 'docusaurus.subPathError': - 'The url is not supposed to contain a sub-path like "{#pathname}". Please use the baseUrl field for sub-paths.', - }); - // TODO move to @docusaurus/utils-validation export const ConfigSchema = Joi.object({ - baseUrl: Joi - // Weird Joi trick needed, otherwise value '' is not normalized... - .alternatives() - .try(Joi.string().required().allow('')) - .required() - .custom((value: string) => addLeadingSlash(addTrailingSlash(value))), + url: SiteUrlSchema.required(), + baseUrl: BaseUrlSchema.required(), baseUrlIssueBanner: Joi.boolean().default(DEFAULT_CONFIG.baseUrlIssueBanner), favicon: Joi.string().optional(), title: Joi.string().required(), - url: SiteUrlSchema, trailingSlash: Joi.boolean(), // No default value! undefined = retrocompatible legacy behavior! i18n: I18N_CONFIG_SCHEMA, future: FUTURE_CONFIG_SCHEMA, diff --git a/packages/docusaurus/src/server/i18n.ts b/packages/docusaurus/src/server/i18n.ts index 9d97140b3a..9b0021ae87 100644 --- a/packages/docusaurus/src/server/i18n.ts +++ b/packages/docusaurus/src/server/i18n.ts @@ -9,6 +9,7 @@ import path from 'path'; import fs from 'fs-extra'; import logger from '@docusaurus/logger'; import combinePromises from 'combine-promises'; +import {normalizeUrl} from '@docusaurus/utils'; import type {I18n, DocusaurusConfig, I18nLocaleConfig} from '@docusaurus/types'; function inferLanguageDisplayName(locale: string) { @@ -82,7 +83,7 @@ function getDefaultDirection(localeStr: string) { export function getDefaultLocaleConfig( locale: string, -): Omit { +): Omit { try { return { label: getDefaultLocaleLabel(locale), @@ -103,10 +104,12 @@ export async function loadI18n({ siteDir, config, currentLocale, + automaticBaseUrlLocalizationDisabled, }: { siteDir: string; config: DocusaurusConfig; currentLocale: string; + automaticBaseUrlLocalizationDisabled: boolean; }): Promise { const {i18n: i18nConfig} = config; @@ -123,7 +126,10 @@ Note: Docusaurus only support running one locale at a time.`; locale: string, ): Promise { const localeConfigInput = i18nConfig.localeConfigs[locale] ?? {}; - const localeConfig: Omit = { + const localeConfig: Omit< + I18nLocaleConfig, + 'translate' | 'url' | 'baseUrl' + > = { ...getDefaultLocaleConfig(locale), ...localeConfigInput, }; @@ -138,10 +144,36 @@ Note: Docusaurus only support running one locale at a time.`; return fs.pathExists(localizationDir); } + function getInferredBaseUrl(): string { + const addLocaleSegment = + locale !== i18nConfig.defaultLocale && + !automaticBaseUrlLocalizationDisabled; + + return normalizeUrl([ + '/', + config.baseUrl, + addLocaleSegment ? locale : '', + '/', + ]); + } + const translate = localeConfigInput.translate ?? (await inferTranslate()); + + const url = + typeof localeConfigInput.url !== 'undefined' + ? localeConfigInput.url + : config.url; + + const baseUrl = + typeof localeConfigInput.baseUrl !== 'undefined' + ? normalizeUrl(['/', localeConfigInput.baseUrl, '/']) + : getInferredBaseUrl(); + return { ...localeConfig, translate, + url, + baseUrl, }; } diff --git a/packages/docusaurus/src/server/site.ts b/packages/docusaurus/src/server/site.ts index a48e68dd8a..9668a13cd9 100644 --- a/packages/docusaurus/src/server/site.ts +++ b/packages/docusaurus/src/server/site.ts @@ -7,7 +7,6 @@ import path from 'path'; import { - localizePath, DEFAULT_BUILD_DIR_NAME, GENERATED_FILES_DIR_NAME, getLocaleConfig, @@ -47,13 +46,21 @@ export type LoadContextParams = { config?: string; /** Default is `i18n.defaultLocale` */ locale?: string; + /** - * `true` means the paths will have the locale prepended; `false` means they - * won't (useful for `yarn build -l zh-Hans` where the output should be - * emitted into `build/` instead of `build/zh-Hans/`); `undefined` is like the - * "smart" option where only non-default locale paths are localized + * By default, we try to automatically infer a localized baseUrl. + * We prepend `//` with a `//` path segment, + * except for the default locale. + * + * This option permits opting out of this baseUrl localization process. + * It is mostly useful to simplify config for multi-domain i18n deployments. + * See https://docusaurus.io/docs/i18n/tutorial#multi-domain-deployment + * + * In all cases, this process doesn't happen if an explicit localized baseUrl + * has been provided using `i18n.localeConfigs[].baseUrl`. We always use the + * provided value over the inferred one, letting you override it. */ - localizePath?: boolean; + automaticBaseUrlLocalizationDisabled?: boolean; }; export type LoadSiteParams = LoadContextParams & { @@ -79,6 +86,7 @@ export async function loadContext( outDir: baseOutDir = DEFAULT_BUILD_DIR_NAME, locale, config: customConfigFilePath, + automaticBaseUrlLocalizationDisabled, } = params; const generatedFilesDir = path.resolve(siteDir, GENERATED_FILES_DIR_NAME); @@ -101,27 +109,29 @@ export async function loadContext( siteDir, config: initialSiteConfig, currentLocale: locale ?? initialSiteConfig.i18n.defaultLocale, + automaticBaseUrlLocalizationDisabled: + automaticBaseUrlLocalizationDisabled ?? false, }); - const baseUrl = localizePath({ - path: initialSiteConfig.baseUrl, - i18n, - options: params, - pathType: 'url', - }); - const outDir = localizePath({ - path: path.resolve(siteDir, baseOutDir), - i18n, - options: params, - pathType: 'fs', - }); + const localeConfig = getLocaleConfig(i18n); + + // We use the baseUrl from the locale config. + // By default, it is inferred as // + // eventually including the // suffix + const baseUrl = localeConfig.baseUrl; + + const outDir = path.join(path.resolve(siteDir, baseOutDir), baseUrl); + const localizationDir = path.resolve( siteDir, i18n.path, getLocaleConfig(i18n).path, ); - const siteConfig: DocusaurusConfig = {...initialSiteConfig, baseUrl}; + const siteConfig: DocusaurusConfig = { + ...initialSiteConfig, + baseUrl, + }; const codeTranslations = await loadSiteCodeTranslations({localizationDir}); diff --git a/project-words.txt b/project-words.txt index 467a8d0a2d..36c96b80c8 100644 --- a/project-words.txt +++ b/project-words.txt @@ -334,7 +334,6 @@ Unavatar unlinkable Unlisteds unlisteds -Unlocalized unlocalized unswizzle upvotes diff --git a/website/docs/api/docusaurus.config.js.mdx b/website/docs/api/docusaurus.config.js.mdx index 351da0421a..a1e5f1c09a 100644 --- a/website/docs/api/docusaurus.config.js.mdx +++ b/website/docs/api/docusaurus.config.js.mdx @@ -84,11 +84,24 @@ export default { }; ``` +:::info Special case for i18n sites + +If your site uses multiple locales, it is possible to provide a distinct `url` for each locale thanks to the [`siteConfig.i18n.localeConfigs[].url`](#i18n) attribute. This makes it possible to deploy a localized Docusaurus site [deploy a localized Docusaurus site over multiple domains](../i18n/i18n-tutorial.mdx#multi-domain-deployment). + +::: + ### `baseUrl` {#baseUrl} - Type: `string` -Base URL for your site. Can be considered as the path after the host. For example, `/metro/` is the base URL of https://facebook.github.io/metro/. For URLs that have no path, the baseUrl should be set to `/`. This field is related to the [`url`](#url) field. Always has both leading and trailing slash. +The base URL of your site is the path segment appearing just after the [`url`](#url), letting you eventually host your site under a subpath instead of at the root of the domain. + +For example, let's consider you want to host a site at https://facebook.github.io/metro/, then you must configure it accordingly: + +- [`url`](#url) should be `'https://facebook.github.io'` +- `baseUrl` should be `'/metro/'` + +By default, a Docusaurus site is hosted at the root of the domain: ```js title="docusaurus.config.js" export default { @@ -96,6 +109,18 @@ export default { }; ``` +:::info Special case for i18n sites + +If your site uses multiple locales, then Docusaurus will automatically localize the `baseUrl` of your site based on smart heuristics: + +- For the default locale, `baseUrl` will be `//` +- For other locales, `baseUrl` will be `///` +- When building a single locale at a time (with `docusaurus build --locale `), `baseUrl` will be `//`, assuming the intent is to [deploy each locale on distinct domains](../i18n/i18n-tutorial.mdx#multi-domain-deployment). + +When the localized `baseUrl` Docusaurus computes doesn't satisfy you, it's always possible to override it by providing an explicit localized `baseUrl` thanks to the [`siteConfig.i18n.localeConfigs[].baseUrl`](#i18n) attribute. + +::: + ## Optional fields {#optional-fields} ### `favicon` {#favicon} @@ -152,6 +177,8 @@ export default { calendar: 'gregory', path: 'en', translate: false, + url: 'https://en.example.com', + baseUrl: '/', }, fa: { label: 'فارسی', @@ -160,6 +187,8 @@ export default { calendar: 'persian', path: 'fa', translate: true, + url: 'https://fa.example.com', + baseUrl: '/', }, }, }, @@ -176,6 +205,8 @@ export default { - `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 (`i18n/`). Note: this has no effect on the locale's `baseUrl`—customization of base URL is a work-in-progress. - `translate`: Should we run the translation process for this locale? By default, it is enabled if the `i18n/` folder exists + - `url`: This lets you override the [`siteConfig.url`](#url), particularly useful if your site is [deployed over multiple domains](../i18n/i18n-tutorial.mdx#multi-domain-deployment). + - `baseUrl`: This lets you override the default localized `baseUrl` Docusaurus infers from your [`siteConfig.baseUrl`](#baseUrl), giving you more control to host your localized site in less common ways, in particularly [deployments over multi-domains](../i18n/i18n-tutorial.mdx#multi-domain-deployment) ### `future` {#future} diff --git a/website/docs/i18n/i18n-tutorial.mdx b/website/docs/i18n/i18n-tutorial.mdx index a88e2f0a38..b76768fae5 100644 --- a/website/docs/i18n/i18n-tutorial.mdx +++ b/website/docs/i18n/i18n-tutorial.mdx @@ -453,6 +453,14 @@ For localized sites, it is recommended to use **[explicit heading IDs](../guides You can choose to deploy your site under a **single domain** or use **multiple (sub)domains**. +:::tip About localized baseUrls + +Docusaurus will automatically add a `//` path segment to your site for locales except the default one. This heuristic works well for most sites but can be configured on a per-locale basis depending on your deployment requirements. + +Read more on the [`siteConfig.baseUrl`](../api/docusaurus.config.js.mdx#baseUrl) docs. + +::: + ### Single-domain deployment {#single-domain-deployment} Run the following command: @@ -495,7 +503,7 @@ You can also build your site for a single locale: npm run build -- --locale fr ``` -Docusaurus will not add the `/fr/` URL prefix. +When building a single locale at a time, Docusaurus will not add the `/fr/` URL prefix automatically, assuming you want to deploy each locale to a distinct domain. On your [static hosting provider](../deployment.mdx): @@ -503,6 +511,37 @@ On your [static hosting provider](../deployment.mdx): - configure the appropriate build command, using the `--locale` option - configure the (sub)domain of your choice for each deployment +:::tip Configuring URLs for each locale + +Use the [`siteConfig.i18n.localeConfigs[].url`](./../api/docusaurus.config.js.mdx#i18n) attribute to configure a distinct site URL for each locale: + +```ts title=docusaurus.config.js +const config = { + i18n: { + localeConfigs: { + // highlight-start + en: { + url: 'https://en.docusaurus.io', + baseUrl: '/', + }, + fr: { + url: 'https://fr.docusaurus.io', + baseUrl: '/', + }, + // highlight-end + }, + }, +}; +``` + +This helps [search engines like Google know about localized versions of your page](https://developers.google.com/search/docs/specialty/international/localized-versions) thanks to `` meta tags. + +This also permits Docusaurus themes to redirect users to the appropriate URL when they switch locale, usually through the [Navbar locale dropdown](../api/themes/theme-configuration.mdx#navbar-locale-dropdown). + +Read more on the [`siteConfig.url`](../api/docusaurus.config.js.mdx#baseUrl) and [`siteConfig.baseUrl`](../api/docusaurus.config.js.mdx#baseUrl) docs. + +::: + :::warning This strategy is **not possible** with GitHub Pages, as it is only possible to **have a single deployment**. From 749b45e629bfc902955627c5bf0181e5aecb091b Mon Sep 17 00:00:00 2001 From: Weston Thayer Date: Mon, 28 Jul 2025 12:36:53 -0400 Subject: [PATCH 044/103] fix(theme): Add `aria-label` to `IconExternalLink` with value `'(opens in new tab)'` (#11331) Co-authored-by: sebastien --- .../src/theme/Icon/ExternalLink/index.tsx | 7 ++++++- .../locales/ar/theme-common.json | 1 + .../locales/base/theme-common.json | 2 ++ .../locales/bg/theme-common.json | 1 + .../locales/bn/theme-common.json | 1 + .../locales/cs/theme-common.json | 1 + .../locales/da/theme-common.json | 1 + .../locales/de/theme-common.json | 1 + .../locales/es/theme-common.json | 1 + .../locales/et/theme-common.json | 1 + .../locales/fa/theme-common.json | 1 + .../locales/fil/theme-common.json | 1 + .../locales/fr/theme-common.json | 1 + .../locales/he/theme-common.json | 1 + .../locales/hi/theme-common.json | 1 + .../locales/hu/theme-common.json | 1 + .../locales/id/theme-common.json | 1 + .../locales/is/theme-common.json | 1 + .../locales/it/theme-common.json | 1 + .../locales/ja/theme-common.json | 1 + .../locales/ko/theme-common.json | 1 + .../locales/nb/theme-common.json | 1 + .../locales/nl/theme-common.json | 1 + .../locales/pl/theme-common.json | 1 + .../locales/pt-BR/theme-common.json | 1 + .../locales/pt-PT/theme-common.json | 1 + .../locales/ru/theme-common.json | 1 + .../locales/sl/theme-common.json | 1 + .../locales/sr/theme-common.json | 1 + .../locales/sv/theme-common.json | 1 + .../locales/tk/theme-common.json | 1 + .../locales/tr/theme-common.json | 1 + .../locales/uk/theme-common.json | 1 + .../locales/vi/theme-common.json | 1 + .../locales/zh-Hans/theme-common.json | 1 + .../locales/zh-Hant/theme-common.json | 1 + 36 files changed, 42 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-theme-classic/src/theme/Icon/ExternalLink/index.tsx b/packages/docusaurus-theme-classic/src/theme/Icon/ExternalLink/index.tsx index 87523b6eec..b899a1fee7 100644 --- a/packages/docusaurus-theme-classic/src/theme/Icon/ExternalLink/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Icon/ExternalLink/index.tsx @@ -6,6 +6,7 @@ */ import React, {type ReactNode} from 'react'; +import {translate} from '@docusaurus/Translate'; import type {Props} from '@theme/Icon/ExternalLink'; import styles from './styles.module.css'; @@ -22,7 +23,11 @@ export default function IconExternalLink({ diff --git a/packages/docusaurus-theme-translations/locales/ar/theme-common.json b/packages/docusaurus-theme-translations/locales/ar/theme-common.json index dab32c9c31..fce1b0d37e 100644 --- a/packages/docusaurus-theme-translations/locales/ar/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/ar/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "هذه الصفحة لا تستجيب.", "theme.ErrorPageContent.tryAgain": "المحاولة مجددا", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "لم نتمكن من العثور على ما كنت تبحث عنه.", "theme.NotFound.p2": "يرجى الاتصال بمالك الموقع الذي ربطك بعنوان URL الأصلي وإخباره بأن الارتباط الخاص به معطل.", diff --git a/packages/docusaurus-theme-translations/locales/base/theme-common.json b/packages/docusaurus-theme-translations/locales/base/theme-common.json index b2762a0702..0efe3bd5c1 100644 --- a/packages/docusaurus-theme-translations/locales/base/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/base/theme-common.json @@ -19,6 +19,8 @@ "theme.ErrorPageContent.title___DESCRIPTION": "The title of the fallback page when the page crashed", "theme.ErrorPageContent.tryAgain": "Try again", "theme.ErrorPageContent.tryAgain___DESCRIPTION": "The label of the button to try again rendering when the React error boundary captures an error", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", + "theme.IconExternalLink.ariaLabel___DESCRIPTION": "The ARIA label for the external link icon", "theme.NavBar.navAriaLabel": "Main", "theme.NavBar.navAriaLabel___DESCRIPTION": "The ARIA label for the main navigation", "theme.NotFound.p1": "We could not find what you were looking for.", diff --git a/packages/docusaurus-theme-translations/locales/bg/theme-common.json b/packages/docusaurus-theme-translations/locales/bg/theme-common.json index 350fd3934c..7461d6ed26 100644 --- a/packages/docusaurus-theme-translations/locales/bg/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/bg/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Разширяване на категорията'{label}'", "theme.ErrorPageContent.title": "Тази страница се срина.", "theme.ErrorPageContent.tryAgain": "Опитайте отново", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Основен", "theme.NotFound.p1": "Не успяхме да намерим това, което търсите.", "theme.NotFound.p2": "Моля, свържете се със собственика на сайта, който ви е свързал с оригиналния URL адрес, и ги уведомете, че връзката им е повредена.", diff --git a/packages/docusaurus-theme-translations/locales/bn/theme-common.json b/packages/docusaurus-theme-translations/locales/bn/theme-common.json index 918f8d243e..05b15f26d2 100644 --- a/packages/docusaurus-theme-translations/locales/bn/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/bn/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "This page crashed.", "theme.ErrorPageContent.tryAgain": "Try again", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "আপনি যা খুঁজছিলেন তা আমরা খুঁজে পাইনি।", "theme.NotFound.p2": "দয়া করে সাইটের মালিকের সাথে যোগাযোগ করুন যা আপনাকে মূল URL এর সাথে যুক্ত করেছে এবং তাদের লিঙ্কটি ভাঙ্গা রয়েছে তা তাদের জানান।", diff --git a/packages/docusaurus-theme-translations/locales/cs/theme-common.json b/packages/docusaurus-theme-translations/locales/cs/theme-common.json index 809330a084..5af85f9b8b 100644 --- a/packages/docusaurus-theme-translations/locales/cs/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/cs/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "This page crashed.", "theme.ErrorPageContent.tryAgain": "Try again", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "Nepodařilo se nám najít co jste hledal(a).", "theme.NotFound.p2": "Kontaktujte prosím vlastníka webu, který vás odkázal na původní URL a upozorněte ho, že jejich odkaz nefunguje.", diff --git a/packages/docusaurus-theme-translations/locales/da/theme-common.json b/packages/docusaurus-theme-translations/locales/da/theme-common.json index 29901fd78b..5ccc178a5f 100644 --- a/packages/docusaurus-theme-translations/locales/da/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/da/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "This page crashed.", "theme.ErrorPageContent.tryAgain": "Try again", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "Vi kunne ikke finde det, du søgte.", "theme.NotFound.p2": "Venligst kontakt ejeren til webstedet, som førte dig frem denne URL, og informer dem om at linket ikke virker.", diff --git a/packages/docusaurus-theme-translations/locales/de/theme-common.json b/packages/docusaurus-theme-translations/locales/de/theme-common.json index a4b6cd2290..b0fce33736 100644 --- a/packages/docusaurus-theme-translations/locales/de/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/de/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "Die Seite ist abgestürzt.", "theme.ErrorPageContent.tryAgain": "Nochmal versuchen", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "Wir konnten nicht finden, wonach Sie gesucht haben.", "theme.NotFound.p2": "Bitte kontaktieren Sie den Besitzer der Seite, die Sie mit der ursprünglichen URL verlinkt hat, und teilen Sie ihm mit, dass der Link nicht mehr funktioniert.", diff --git a/packages/docusaurus-theme-translations/locales/es/theme-common.json b/packages/docusaurus-theme-translations/locales/es/theme-common.json index a9c0f5be49..bfaa6b906a 100644 --- a/packages/docusaurus-theme-translations/locales/es/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/es/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Ampliar la categoría '{label}' de la barra lateral", "theme.ErrorPageContent.title": "Esta página ha fallado.", "theme.ErrorPageContent.tryAgain": "Intente de nuevo", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Principal", "theme.NotFound.p1": "No pudimos encontrar lo que buscaba.", "theme.NotFound.p2": "Comuníquese con el dueño del sitio que le proporcionó la URL original y hágale saber que su vínculo está roto.", diff --git a/packages/docusaurus-theme-translations/locales/et/theme-common.json b/packages/docusaurus-theme-translations/locales/et/theme-common.json index adce580ff8..89e1055b67 100644 --- a/packages/docusaurus-theme-translations/locales/et/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/et/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Ava külgrea kategooria '{label}'", "theme.ErrorPageContent.title": "See leht jooksis kokku.", "theme.ErrorPageContent.tryAgain": "Proovi uuesti", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Peamine", "theme.NotFound.p1": "Vabandame, kuid lehte ei leitud.", "theme.NotFound.p2": "Kui arvad, et see on viga, palun võta meiega ühendust.", diff --git a/packages/docusaurus-theme-translations/locales/fa/theme-common.json b/packages/docusaurus-theme-translations/locales/fa/theme-common.json index 5166cc78e2..b4153a4832 100644 --- a/packages/docusaurus-theme-translations/locales/fa/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/fa/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "باز کردن دسته بندی در نوار کناری '{label}'", "theme.ErrorPageContent.title": "بارگذاری صفحه با خطا روبرو شد.", "theme.ErrorPageContent.tryAgain": "تلاش مجدد", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "صفحه اصلی", "theme.NotFound.p1": "صفحه‌ای که دنبال آن بودید پیدا نشد.", "theme.NotFound.p2": "لطفا با صاحب وبسایت تماس بگیرید و ایشان را از مشکل پیش آمده مطلع کنید.", diff --git a/packages/docusaurus-theme-translations/locales/fil/theme-common.json b/packages/docusaurus-theme-translations/locales/fil/theme-common.json index 27de696ad9..04d89a095c 100644 --- a/packages/docusaurus-theme-translations/locales/fil/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/fil/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "This page crashed.", "theme.ErrorPageContent.tryAgain": "Try again", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "Hindi namin mahanap ang iyong hinananap.", "theme.NotFound.p2": "Mangyaring makipag-ugnayan sa may-ari ng site na nag-link sa iyo sa orihinal na URL at sabihin sa kanila na ang kanilang link ay putol.", diff --git a/packages/docusaurus-theme-translations/locales/fr/theme-common.json b/packages/docusaurus-theme-translations/locales/fr/theme-common.json index 598928765c..36037b5bff 100644 --- a/packages/docusaurus-theme-translations/locales/fr/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/fr/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Développer la catégorie '{label}' de la barre latérale", "theme.ErrorPageContent.title": "Cette page a planté.", "theme.ErrorPageContent.tryAgain": "Réessayer", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "Nous n'avons pas trouvé ce que vous recherchez.", "theme.NotFound.p2": "Veuillez contacter le propriétaire du site qui vous a lié à l'URL d'origine et leur faire savoir que leur lien est cassé.", diff --git a/packages/docusaurus-theme-translations/locales/he/theme-common.json b/packages/docusaurus-theme-translations/locales/he/theme-common.json index 87e0593b8b..5e4806e8c3 100644 --- a/packages/docusaurus-theme-translations/locales/he/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/he/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "This page crashed.", "theme.ErrorPageContent.tryAgain": "Try again", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "אנחנו לא מוצאים את מה שאתה מנסה לחפש.", "theme.NotFound.p2": "הקישור אינו תקין, אנא פנה למנהל האתר ממנו קיבלת קישור זה.", diff --git a/packages/docusaurus-theme-translations/locales/hi/theme-common.json b/packages/docusaurus-theme-translations/locales/hi/theme-common.json index 5f5a4f5d35..8fe459cf0d 100644 --- a/packages/docusaurus-theme-translations/locales/hi/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/hi/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "This page crashed.", "theme.ErrorPageContent.tryAgain": "Try again", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "हमें वह नहीं मिला, जिसकी आपको तलाश थी।", "theme.NotFound.p2": "कृपया उस साइट के मालिक से संपर्क करें जिसने आपको मूल URL से जोड़ा है और उन्हें बताएं कि उनका लिंक टूट गया है।", diff --git a/packages/docusaurus-theme-translations/locales/hu/theme-common.json b/packages/docusaurus-theme-translations/locales/hu/theme-common.json index b01e4922d3..7d9514ea99 100644 --- a/packages/docusaurus-theme-translations/locales/hu/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/hu/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "A(z) '{label}' nevű oldalsáv kategória kinyitása", "theme.ErrorPageContent.title": "Hiba történt a oldalon.", "theme.ErrorPageContent.tryAgain": "Próbáld újra", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Fő", "theme.NotFound.p1": "Sajnos nem találtuk azt az oldalt, amit kerestél.", "theme.NotFound.p2": "Kérjük, lépj kapcsolatba az oldal tulajdonosával, ahonnan erre a hivatkozásra léptél, hogy jelezd, hogy a hivatkozás nem működik.", diff --git a/packages/docusaurus-theme-translations/locales/id/theme-common.json b/packages/docusaurus-theme-translations/locales/id/theme-common.json index 454e94db88..b228dcc5b6 100644 --- a/packages/docusaurus-theme-translations/locales/id/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/id/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Perluas kategori bilah sisi '{label}'", "theme.ErrorPageContent.title": "Terjadi kesalahan.", "theme.ErrorPageContent.tryAgain": "Coba kembali", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Utama", "theme.NotFound.p1": "Kami tak dapat menemukan yang anda cari.", "theme.NotFound.p2": "Silakan hubungi pemilik situs yang mengarahkan anda ke URL asli dan beri tahu mereka bahwa tautan mereka salah.", diff --git a/packages/docusaurus-theme-translations/locales/is/theme-common.json b/packages/docusaurus-theme-translations/locales/is/theme-common.json index 95e0a23f64..9bc2e48265 100644 --- a/packages/docusaurus-theme-translations/locales/is/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/is/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Víkka spássíu flokk '{label}'", "theme.ErrorPageContent.title": "Síðan hrundi.", "theme.ErrorPageContent.tryAgain": "Reyndu aftur", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Aðal", "theme.NotFound.p1": "Við fundum ekki það sem þú leitaðir að.", "theme.NotFound.p2": "Vinsamlegast hafðu samband við eiganda síðunnar sem sendi þig hingað og láttu hann vita að hlekkurinn er brotinn.", diff --git a/packages/docusaurus-theme-translations/locales/it/theme-common.json b/packages/docusaurus-theme-translations/locales/it/theme-common.json index 7babe752f1..dc35eb97c8 100644 --- a/packages/docusaurus-theme-translations/locales/it/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/it/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "Questa pagina è andata in crash.", "theme.ErrorPageContent.tryAgain": "Prova di nuovo", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Principale", "theme.NotFound.p1": "Non siamo riusciti a trovare quello che stavi cercando.", "theme.NotFound.p2": "Contatta il proprietario del sito che ti ha collegato all'URL originale e fagli sapere che il loro collegamento è interrotto.", diff --git a/packages/docusaurus-theme-translations/locales/ja/theme-common.json b/packages/docusaurus-theme-translations/locales/ja/theme-common.json index baa3964a64..577f6a4831 100644 --- a/packages/docusaurus-theme-translations/locales/ja/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/ja/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "'{label}'の目次を開く", "theme.ErrorPageContent.title": "エラーが発生しました", "theme.ErrorPageContent.tryAgain": "もう一度試してください", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "ナビゲーション", "theme.NotFound.p1": "お探しのページが見つかりませんでした", "theme.NotFound.p2": "このページにリンクしているサイトの所有者にリンクが壊れていることを伝えてください", diff --git a/packages/docusaurus-theme-translations/locales/ko/theme-common.json b/packages/docusaurus-theme-translations/locales/ko/theme-common.json index 0eefc6ea49..0fc6e14665 100644 --- a/packages/docusaurus-theme-translations/locales/ko/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/ko/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "사이드바 분류 '{label}' 펼치기", "theme.ErrorPageContent.title": "페이지에 오류가 발생하였습니다.", "theme.ErrorPageContent.tryAgain": "다시 시도해 보세요", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "메인", "theme.NotFound.p1": "원하는 페이지를 찾을 수 없습니다.", "theme.NotFound.p2": "사이트 관리자에게 링크가 깨진 것을 알려주세요.", diff --git a/packages/docusaurus-theme-translations/locales/nb/theme-common.json b/packages/docusaurus-theme-translations/locales/nb/theme-common.json index 269df3c551..97d7c3eb77 100644 --- a/packages/docusaurus-theme-translations/locales/nb/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/nb/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "Denne siden krasjet.", "theme.ErrorPageContent.tryAgain": "Prøv på nytt", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Hoved", "theme.NotFound.p1": "Vi kunne ikke finne det du lette etter.", "theme.NotFound.p2": "Kontakt eieren av nettstedet som koblet deg til den opprinnelige nettadressen og la dem få vite at koblingen deres er ødelagt.", diff --git a/packages/docusaurus-theme-translations/locales/nl/theme-common.json b/packages/docusaurus-theme-translations/locales/nl/theme-common.json index 706e70871f..8059850dff 100644 --- a/packages/docusaurus-theme-translations/locales/nl/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/nl/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Categorie zijbalk uitklappen '{label}'", "theme.ErrorPageContent.title": "Deze pagina is gecrasht.", "theme.ErrorPageContent.tryAgain": "Probeer opnieuw", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "We kunnen niet vinden waar je naar op zoek bent.", "theme.NotFound.p2": "Neem contact op met de eigenaar van de website die naar de originele URL heeft geleid en laat weten dat de link niet meer werkt.", diff --git a/packages/docusaurus-theme-translations/locales/pl/theme-common.json b/packages/docusaurus-theme-translations/locales/pl/theme-common.json index 3a6f707943..5a74b63573 100644 --- a/packages/docusaurus-theme-translations/locales/pl/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/pl/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "Ta strona uległa awarii.", "theme.ErrorPageContent.tryAgain": "Spróbuj ponownie", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "Nie mogliśmy znaleźć strony której szukasz.", "theme.NotFound.p2": "Proszę skontaktuj się z właścielem strony, z której link doprowadził Cię tutaj i poinformuj go, że link jest nieprawidłowy.", diff --git a/packages/docusaurus-theme-translations/locales/pt-BR/theme-common.json b/packages/docusaurus-theme-translations/locales/pt-BR/theme-common.json index d848584d66..5d39829d8d 100644 --- a/packages/docusaurus-theme-translations/locales/pt-BR/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/pt-BR/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expandir a categoria '{label}'", "theme.ErrorPageContent.title": "Esta página deu erro.", "theme.ErrorPageContent.tryAgain": "Tentar novamente", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Navegação principal", "theme.NotFound.p1": "Não foi possível encontrar o que você está procurando.", "theme.NotFound.p2": "Por favor, entre em contato com o dono do site que ligou você à URL original e informe que o link está quebrado.", diff --git a/packages/docusaurus-theme-translations/locales/pt-PT/theme-common.json b/packages/docusaurus-theme-translations/locales/pt-PT/theme-common.json index 9904d6c177..af7fff8e74 100644 --- a/packages/docusaurus-theme-translations/locales/pt-PT/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/pt-PT/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "This page crashed.", "theme.ErrorPageContent.tryAgain": "Try again", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "Não foi possível encontrar o que procura.", "theme.NotFound.p2": "Por favor, contacte o proprietário do site que o trouxe aqui e informe-lhe que o link está partido.", diff --git a/packages/docusaurus-theme-translations/locales/ru/theme-common.json b/packages/docusaurus-theme-translations/locales/ru/theme-common.json index e432ddb2c0..0dbeaf6aed 100644 --- a/packages/docusaurus-theme-translations/locales/ru/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/ru/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "На странице произошёл сбой.", "theme.ErrorPageContent.tryAgain": "Попробуйте ещё раз", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "К сожалению, мы не смогли найти запрашиваемую вами страницу.", "theme.NotFound.p2": "Пожалуйста, обратитесь к владельцу сайта, с которого вы перешли на эту ссылку, чтобы сообщить ему, что ссылка не работает.", diff --git a/packages/docusaurus-theme-translations/locales/sl/theme-common.json b/packages/docusaurus-theme-translations/locales/sl/theme-common.json index ecec838635..6cdefa9bd1 100644 --- a/packages/docusaurus-theme-translations/locales/sl/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/sl/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Razširite kategorijo stranske vrstice '{label}'", "theme.ErrorPageContent.title": "Ta stran se je zrušila.", "theme.ErrorPageContent.tryAgain": "Poskusite ponovno", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Glavna navigacija", "theme.NotFound.p1": "Iskane strani ni bilo možno najti", "theme.NotFound.p2": "Prosim kontaktirajte lastnike strani, s katere ste sledili povezavi in jih obvestite, da povezava ne deluje.", diff --git a/packages/docusaurus-theme-translations/locales/sr/theme-common.json b/packages/docusaurus-theme-translations/locales/sr/theme-common.json index 8bbe9459bb..82b658edb1 100644 --- a/packages/docusaurus-theme-translations/locales/sr/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/sr/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "This page crashed.", "theme.ErrorPageContent.tryAgain": "Try again", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "Тражени резултат не постоји.", "theme.NotFound.p2": "Молимо вас да контактирате власника сајта који вас је упутио овде и обавестите га да је њихова веза нетачна.", diff --git a/packages/docusaurus-theme-translations/locales/sv/theme-common.json b/packages/docusaurus-theme-translations/locales/sv/theme-common.json index c37e11ac95..201816a092 100644 --- a/packages/docusaurus-theme-translations/locales/sv/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/sv/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", "theme.ErrorPageContent.title": "Denna sida har kraschat.", "theme.ErrorPageContent.tryAgain": "Försök igen", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "Vi kunde inte hitta det du letade efter.", "theme.NotFound.p2": "Vänligen kontakta ägaren av webbplatsen som länkade dig till den ursprungliga webbadressen och låt dem veta att denna länk är trasig.", diff --git a/packages/docusaurus-theme-translations/locales/tk/theme-common.json b/packages/docusaurus-theme-translations/locales/tk/theme-common.json index 406db5528a..7c4558bff1 100644 --- a/packages/docusaurus-theme-translations/locales/tk/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/tk/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Gapdal paneli görkez'{label}'", "theme.ErrorPageContent.title": "Sahypada näsazlyk ýüze çykdy.", "theme.ErrorPageContent.tryAgain": "Gaýtadan synanyşyň", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Esasy", "theme.NotFound.p1": "Gynansakda, ýüzlenen sahypaňyz tapylmady", "theme.NotFound.p2": "Web sahypanyň dolandyryjylaryna habar bermegiňizi sizden haýyş edýäris", diff --git a/packages/docusaurus-theme-translations/locales/tr/theme-common.json b/packages/docusaurus-theme-translations/locales/tr/theme-common.json index de75f52498..433b7d0c67 100644 --- a/packages/docusaurus-theme-translations/locales/tr/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/tr/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Kenar çubuğu kategorisini genişlet '{label}'", "theme.ErrorPageContent.title": "Bu sayfa çöktü.", "theme.ErrorPageContent.tryAgain": "Tekrar deneyin", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Ana menü", "theme.NotFound.p1": "Aradığınız şeyi bulamadık.", "theme.NotFound.p2": "Lütfen sizi orijinal URL'ye yönlendiren sitenin sahibiyle iletişime geçin ve bağlantısının bozuk olduğunu bildirin.", diff --git a/packages/docusaurus-theme-translations/locales/uk/theme-common.json b/packages/docusaurus-theme-translations/locales/uk/theme-common.json index 72ee02cdf7..759ca2716f 100644 --- a/packages/docusaurus-theme-translations/locales/uk/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/uk/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Розгорнути категорію в сайдбарі '{label}'", "theme.ErrorPageContent.title": "На сторінці стався збій.", "theme.ErrorPageContent.tryAgain": "Спробуйте ще раз", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Головна", "theme.NotFound.p1": "На жаль, ми не змогли знайти сторінку, яку ви запитували.", "theme.NotFound.p2": "Будь ласка, зверніться до власника сайту, з якого ви перейшли на це посилання, щоб повідомити, що посилання не працює.", diff --git a/packages/docusaurus-theme-translations/locales/vi/theme-common.json b/packages/docusaurus-theme-translations/locales/vi/theme-common.json index 33994fd5e2..04ba9c6b75 100644 --- a/packages/docusaurus-theme-translations/locales/vi/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/vi/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "Xem thêm danh mục '{label}'", "theme.ErrorPageContent.title": "Trang này đã gặp lỗi.", "theme.ErrorPageContent.tryAgain": "Thử lại", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "Thanh điều hướng", "theme.NotFound.p1": "Chúng tôi không thể tìm thấy nội dung bạn đang tìm kiếm.", "theme.NotFound.p2": "Vui lòng liên hệ với trang web đã đưa bạn đến đây và thông báo rằng đường dẫn này bị lỗi.", diff --git a/packages/docusaurus-theme-translations/locales/zh-Hans/theme-common.json b/packages/docusaurus-theme-translations/locales/zh-Hans/theme-common.json index f9e580a264..0fc0dfd17d 100644 --- a/packages/docusaurus-theme-translations/locales/zh-Hans/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/zh-Hans/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "展开侧边栏分类 '{label}'", "theme.ErrorPageContent.title": "页面已崩溃。", "theme.ErrorPageContent.tryAgain": "重试", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "主导航", "theme.NotFound.p1": "我们找不到您要找的页面。", "theme.NotFound.p2": "请联系原始链接来源网站的所有者,并告知他们链接已损坏。", diff --git a/packages/docusaurus-theme-translations/locales/zh-Hant/theme-common.json b/packages/docusaurus-theme-translations/locales/zh-Hant/theme-common.json index 1ba88ded27..4ec1bbf99e 100644 --- a/packages/docusaurus-theme-translations/locales/zh-Hant/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/zh-Hant/theme-common.json @@ -9,6 +9,7 @@ "theme.DocSidebarItem.expandCategoryAriaLabel": "展開側邊欄分類 '{label}'", "theme.ErrorPageContent.title": "此頁已當機。", "theme.ErrorPageContent.tryAgain": "重試", + "theme.IconExternalLink.ariaLabel": "(opens in new tab)", "theme.NavBar.navAriaLabel": "主導航", "theme.NotFound.p1": "我們沒有您要找的頁面。", "theme.NotFound.p2": "請聯絡原始連結來源網站的所有者,並通知他們連結已毀損。", From 942094af3c827a249dc9886ff8ffcf44dd150751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 31 Jul 2025 13:48:00 +0200 Subject: [PATCH 045/103] fix(theme): Doc sidebar links/categories with long labels should display properly (#11356) Co-authored-by: slorber <749374+slorber@users.noreply.github.com> --- .../theme/DocSidebarItem/Category/index.tsx | 64 +++++++++++-------- .../DocSidebarItem/Category/styles.module.css | 26 ++++++++ .../src/theme/DocSidebarItem/Link/index.tsx | 10 ++- .../DocSidebarItem/Link/styles.module.css | 8 +++ project-words.txt | 1 + .../doc1.mdx | 1 + .../doc1.mdx | 1 + ...ong long long long long long long long.mdx | 1 + ...nglonglonglonglonglonglonglonglonglong.mdx | 1 + .../tests/sidebar-display/_category_.json | 9 +++ 10 files changed, 93 insertions(+), 29 deletions(-) create mode 100644 packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/styles.module.css create mode 100644 website/_dogfooding/_docs tests/tests/sidebar-display/Category 2 Long Long Long Long Long Long Long Long Long Long Long/doc1.mdx create mode 100644 website/_dogfooding/_docs tests/tests/sidebar-display/Category1LongLongLongLongLongLongLongLongLongLong/doc1.mdx create mode 100644 website/_dogfooding/_docs tests/tests/sidebar-display/Category1LongLongLongLongLongLongLongLongLongLong/doc2 long long long long long long long long long long long long.mdx create mode 100644 website/_dogfooding/_docs tests/tests/sidebar-display/Category1LongLongLongLongLongLongLongLongLongLong/doc3longlonglonglonglonglonglonglonglonglonglonglong.mdx create mode 100644 website/_dogfooding/_docs tests/tests/sidebar-display/_category_.json diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx index 22270f21a3..9a49be27d1 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx @@ -31,6 +31,8 @@ import useIsBrowser from '@docusaurus/useIsBrowser'; import DocSidebarItems from '@theme/DocSidebarItems'; import type {Props} from '@theme/DocSidebarItem/Category'; +import styles from './styles.module.css'; + // If we navigate to a category and it becomes active, it should automatically // expand itself function useAutoExpandActiveCategory({ @@ -126,6 +128,14 @@ function CollapseButton({ ); } +function CategoryLinkLabel({label}: {label: string}) { + return ( + + {label} + + ); +} + export default function DocSidebarItemCategory({ item, onItemClick, @@ -179,6 +189,29 @@ export default function DocSidebarItemCategory({ } }, [collapsible, expandedItem, index, setCollapsed, autoCollapseCategories]); + const handleItemClick: ComponentProps<'a'>['onClick'] = (e) => { + onItemClick?.(item); + if (collapsible) { + if (href) { + // When already on the category's page, we collapse it + // We don't use "isActive" because it would collapse the + // category even when we browse a children element + // See https://github.com/facebook/docusaurus/issues/11213 + if (isCurrentPage) { + e.preventDefault(); + updateCollapsed(); + } else { + // When navigating to a new category, we always expand + // see https://github.com/facebook/docusaurus/issues/10854#issuecomment-2609616182 + updateCollapsed(false); + } + } else { + e.preventDefault(); + updateCollapsed(); + } + } + }; + return (
  • { - onItemClick?.(item); - if (href) { - // When already on the category's page, we collapse it - // We don't use "isActive" because it would collapse the - // category even when we browse a children element - // See https://github.com/facebook/docusaurus/issues/11213 - if (isCurrentPage) { - e.preventDefault(); - updateCollapsed(); - } else { - // When navigating to a new category, we always expand - // see https://github.com/facebook/docusaurus/issues/10854#issuecomment-2609616182 - updateCollapsed(false); - } - } else { - e.preventDefault(); - updateCollapsed(); - } - } - : () => { - onItemClick?.(item); - } - } + onClick={handleItemClick} aria-current={isCurrentPage ? 'page' : undefined} role={collapsible && !href ? 'button' : undefined} aria-expanded={collapsible && !href ? !collapsed : undefined} href={collapsible ? hrefWithSSRFallback ?? '#' : hrefWithSSRFallback} {...props}> - {label} + {href && collapsible && ( + {label} + + ); +} + export default function DocSidebarItemLink({ item, onItemClick, @@ -51,7 +59,7 @@ export default function DocSidebarItemLink({ onClick: onItemClick ? () => onItemClick(item) : undefined, })} {...props}> - {label} + {!isInternalLink && }
  • diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Link/styles.module.css b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Link/styles.module.css index 4abcb56762..a48f210974 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Link/styles.module.css +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Link/styles.module.css @@ -8,3 +8,11 @@ .menuExternalLink { align-items: center; } + +.linkLabel { + overflow: hidden; + display: -webkit-box; + line-clamp: 2; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; +} diff --git a/project-words.txt b/project-words.txt index 36c96b80c8..03eeb8db4d 100644 --- a/project-words.txt +++ b/project-words.txt @@ -136,6 +136,7 @@ lifecycles lightningcss Linkify linkify +longlonglonglonglonglonglonglonglonglonglonglong Lorber lorber Lorber's diff --git a/website/_dogfooding/_docs tests/tests/sidebar-display/Category 2 Long Long Long Long Long Long Long Long Long Long Long/doc1.mdx b/website/_dogfooding/_docs tests/tests/sidebar-display/Category 2 Long Long Long Long Long Long Long Long Long Long Long/doc1.mdx new file mode 100644 index 0000000000..02823ef8d5 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/sidebar-display/Category 2 Long Long Long Long Long Long Long Long Long Long Long/doc1.mdx @@ -0,0 +1 @@ +# Doc 1 diff --git a/website/_dogfooding/_docs tests/tests/sidebar-display/Category1LongLongLongLongLongLongLongLongLongLong/doc1.mdx b/website/_dogfooding/_docs tests/tests/sidebar-display/Category1LongLongLongLongLongLongLongLongLongLong/doc1.mdx new file mode 100644 index 0000000000..02823ef8d5 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/sidebar-display/Category1LongLongLongLongLongLongLongLongLongLong/doc1.mdx @@ -0,0 +1 @@ +# Doc 1 diff --git a/website/_dogfooding/_docs tests/tests/sidebar-display/Category1LongLongLongLongLongLongLongLongLongLong/doc2 long long long long long long long long long long long long.mdx b/website/_dogfooding/_docs tests/tests/sidebar-display/Category1LongLongLongLongLongLongLongLongLongLong/doc2 long long long long long long long long long long long long.mdx new file mode 100644 index 0000000000..816e33bf62 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/sidebar-display/Category1LongLongLongLongLongLongLongLongLongLong/doc2 long long long long long long long long long long long long.mdx @@ -0,0 +1 @@ +# Doc 2 long long long long long long long long long long long long diff --git a/website/_dogfooding/_docs tests/tests/sidebar-display/Category1LongLongLongLongLongLongLongLongLongLong/doc3longlonglonglonglonglonglonglonglonglonglonglong.mdx b/website/_dogfooding/_docs tests/tests/sidebar-display/Category1LongLongLongLongLongLongLongLongLongLong/doc3longlonglonglonglonglonglonglonglonglonglonglong.mdx new file mode 100644 index 0000000000..0d0eb1de3d --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/sidebar-display/Category1LongLongLongLongLongLongLongLongLongLong/doc3longlonglonglonglonglonglonglonglonglonglonglong.mdx @@ -0,0 +1 @@ +# Doc 3 longlonglonglonglonglonglonglonglonglonglonglong diff --git a/website/_dogfooding/_docs tests/tests/sidebar-display/_category_.json b/website/_dogfooding/_docs tests/tests/sidebar-display/_category_.json new file mode 100644 index 0000000000..8dcbb76c67 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/sidebar-display/_category_.json @@ -0,0 +1,9 @@ +{ + "label": "Sidebar Display", + "link": { + "type": "generated-index", + "title": "Sidebar Display", + "description": "Testing edge cases of how the docs sidebar is displayed" + }, + "position": 1 +} From b1391349f5ef4093b2793d2aa801701fc5bf8823 Mon Sep 17 00:00:00 2001 From: Maria Stellini Date: Thu, 31 Jul 2025 13:58:37 +0200 Subject: [PATCH 046/103] docs: clarify impact of document ID on the URL (#11339) Co-authored-by: sebastien --- website/docs/guides/docs/docs-create-doc.mdx | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/website/docs/guides/docs/docs-create-doc.mdx b/website/docs/guides/docs/docs-create-doc.mdx index caf8e2ea77..b45cf6d331 100644 --- a/website/docs/guides/docs/docs-create-doc.mdx +++ b/website/docs/guides/docs/docs-create-doc.mdx @@ -128,13 +128,15 @@ The ID is used to refer to a document when hand-writing sidebars, or when using ### Doc URLs {#doc-urls} -By default, a document's URL location is its file path relative to the `docs` folder, with a few exceptions. Namely, if a file is named one the following, the file name won't be included in the URL: +By default, the document's URL location is derived from the [document `id`](#document-id), which in turn is based on the document's file path. + +If a file is named one of the following, the file name won't be included in the URL: - Named as `index` (case-insensitive): `docs/Guides/index.md` - Named as `README` (case-insensitive): `docs/Guides/README.mdx` - Same name as parent folder: `docs/Guides/Guides.md` -In all cases, the default slug would only be `/Guides`, without the `/index`, `/README`, or duplicate `/Guides` segment. +In all cases, the default `slug` would only be `/Guides`, without the `/index`, `/README`, or duplicate `/Guides` segment. :::note @@ -142,7 +144,7 @@ This convention is exactly the same as [the category index convention](./sidebar ::: -Use the `slug` front matter to change a document's URL. +Use the `slug` front matter to provide an explicit document URL and override the default one. For example, suppose your site structure looks like this: @@ -153,7 +155,7 @@ website # Root directory of your site └── hello.md ``` -By default `hello.md` will be available at `/docs/guide/hello`. You can change its URL location to `/docs/bonjour`: +By default, `hello.md` will be available at `/docs/guide/hello`. You can change its URL location to `/docs/bonjour`: ```md --- @@ -174,6 +176,14 @@ It is possible to use: ::: +:::tip + +Changing a document's filename or `id`, will change its default URL. To prevent breaking permalinks when renaming files, we recommend setting an explicit `slug` to keep your URLs stable. + +::: + +#### Making a document available at the root + If you want a document to be available at the root, and have a path like `https://docusaurus.io/docs/`, you can use the slug front matter: ```md From 27945b3b345d28bde1237d442a6ef5737eaa6943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Mon, 4 Aug 2025 13:30:35 +0200 Subject: [PATCH 047/103] fix(theme): Add translate no to heading anchors and blog authors (#11360) --- .../src/theme/Blog/Components/Author/index.tsx | 8 ++++++-- .../docusaurus-theme-classic/src/theme/Heading/index.tsx | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme/Blog/Components/Author/index.tsx b/packages/docusaurus-theme-classic/src/theme/Blog/Components/Author/index.tsx index 6742eabe2b..54b7160c44 100644 --- a/packages/docusaurus-theme-classic/src/theme/Blog/Components/Author/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Blog/Components/Author/index.tsx @@ -30,10 +30,14 @@ function AuthorTitle({title}: {title: string}) { function AuthorName({name, as}: {name: string; as: Props['as']}) { if (!as) { - return {name}; + return ( + + {name} + + ); } else { return ( - + {name} ); diff --git a/packages/docusaurus-theme-classic/src/theme/Heading/index.tsx b/packages/docusaurus-theme-classic/src/theme/Heading/index.tsx index 64d737470a..8f7c4fc2bf 100644 --- a/packages/docusaurus-theme-classic/src/theme/Heading/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Heading/index.tsx @@ -54,7 +54,8 @@ export default function Heading({as: As, id, ...props}: Props): ReactNode { className="hash-link" to={`#${id}`} aria-label={anchorTitle} - title={anchorTitle}> + title={anchorTitle} + translate="no"> ​ From a4c33bfea56b231b302adbf819a45c2de217a01d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 12:40:41 +0100 Subject: [PATCH 048/103] chore(deps): bump actions/checkout from 4 to 5 (#11365) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/argos.yml | 2 +- .github/workflows/build-blog-only.yml | 2 +- .github/workflows/build-hash-router.yml | 2 +- .github/workflows/build-perf.yml | 4 ++-- .github/workflows/canary-release.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/continuous-releases.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/lighthouse-report.yml | 2 +- .github/workflows/lint-autofix.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/showcase-test.yml | 2 +- .github/workflows/tests-e2e.yml | 10 +++++----- .github/workflows/tests-swizzle.yml | 2 +- .github/workflows/tests-windows.yml | 2 +- .github/workflows/tests.yml | 2 +- 16 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/argos.yml b/.github/workflows/argos.yml index c1c6be47ef..fdb784c21d 100644 --- a/.github/workflows/argos.yml +++ b/.github/workflows/argos.yml @@ -27,7 +27,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 diff --git a/.github/workflows/build-blog-only.yml b/.github/workflows/build-blog-only.yml index 334ae73dea..c91717b73f 100644 --- a/.github/workflows/build-blog-only.yml +++ b/.github/workflows/build-blog-only.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: diff --git a/.github/workflows/build-hash-router.yml b/.github/workflows/build-hash-router.yml index e99ec20433..ae8d253db0 100644 --- a/.github/workflows/build-hash-router.yml +++ b/.github/workflows/build-hash-router.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: diff --git a/.github/workflows/build-perf.yml b/.github/workflows/build-perf.yml index aa46d31b8e..16ee737ade 100644 --- a/.github/workflows/build-perf.yml +++ b/.github/workflows/build-perf.yml @@ -41,7 +41,7 @@ jobs: DOCUSAURUS_INFRA: ['SLOWER', 'FASTER'] steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: @@ -73,7 +73,7 @@ jobs: DOCUSAURUS_INFRA: ['SLOWER', 'FASTER'] steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: diff --git a/.github/workflows/canary-release.yml b/.github/workflows/canary-release.yml index cf417eb044..474045988f 100644 --- a/.github/workflows/canary-release.yml +++ b/.github/workflows/canary-release.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 # Needed to get the commit number with "git rev-list --count HEAD" - name: Set up Node diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6a8990b04a..62f62d5d1d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -33,7 +33,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Initialize CodeQL uses: github/codeql-action/init@2c779ab0d087cd7fe7b826087247c2c81f27bfa6 # 3.26.5 diff --git a/.github/workflows/continuous-releases.yml b/.github/workflows/continuous-releases.yml index 13431aef77..67d56fb230 100644 --- a/.github/workflows/continuous-releases.yml +++ b/.github/workflows/continuous-releases.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 5d9fc5e2ed..5fc359d8ed 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -13,6 +13,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Dependency Review uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # 4.7.1 diff --git a/.github/workflows/lighthouse-report.yml b/.github/workflows/lighthouse-report.yml index ce28df365e..6a0dcb8bae 100644 --- a/.github/workflows/lighthouse-report.yml +++ b/.github/workflows/lighthouse-report.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 diff --git a/.github/workflows/lint-autofix.yml b/.github/workflows/lint-autofix.yml index dd42164b3b..4f8976e20d 100644 --- a/.github/workflows/lint-autofix.yml +++ b/.github/workflows/lint-autofix.yml @@ -19,7 +19,7 @@ jobs: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.head_ref }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b7a477806d..457878b276 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: diff --git a/.github/workflows/showcase-test.yml b/.github/workflows/showcase-test.yml index ff3a8018f8..4c5e459e56 100644 --- a/.github/workflows/showcase-test.yml +++ b/.github/workflows/showcase-test.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: diff --git a/.github/workflows/tests-e2e.yml b/.github/workflows/tests-e2e.yml index 875910efaa..650e413229 100644 --- a/.github/workflows/tests-e2e.yml +++ b/.github/workflows/tests-e2e.yml @@ -41,7 +41,7 @@ jobs: node: ['18.0', '20', '22', '24'] steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js ${{ matrix.node }} uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: @@ -78,7 +78,7 @@ jobs: runs-on: windows-8-core steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js LTS uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: @@ -124,7 +124,7 @@ jobs: variant: [-s, -st] steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js LTS uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: @@ -193,7 +193,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js LTS uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: @@ -233,7 +233,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js LTS uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: diff --git a/.github/workflows/tests-swizzle.yml b/.github/workflows/tests-swizzle.yml index 92a15de818..44702e4c3a 100644 --- a/.github/workflows/tests-swizzle.yml +++ b/.github/workflows/tests-swizzle.yml @@ -26,7 +26,7 @@ jobs: variant: ['js', 'ts'] steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node LTS uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: diff --git a/.github/workflows/tests-windows.yml b/.github/workflows/tests-windows.yml index 018eb41268..d168a7d4ba 100644 --- a/.github/workflows/tests-windows.yml +++ b/.github/workflows/tests-windows.yml @@ -32,7 +32,7 @@ jobs: - name: Support longpaths run: git config --system core.longpaths true - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js ${{ matrix.node }} uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4163b3131f..c21fe9baf8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -30,7 +30,7 @@ jobs: node: ['18.0', '20', '22', '24'] steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js ${{ matrix.node }} uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: From 87d878471e3c5da1fb1f32d444d1ea2cdb8cd148 Mon Sep 17 00:00:00 2001 From: Jaime Iniesta Date: Sun, 24 Aug 2025 12:05:52 +0200 Subject: [PATCH 049/103] docs: adds link to latest accessibility stats and reports in Rocket Validator (#11376) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 70fe727319..c91522b7a5 100644 --- a/README.md +++ b/README.md @@ -120,4 +120,4 @@ The Docusaurus documentation (e.g., `.md` files in the `/docs` folder) is [Creat [![Rocket Validator logo](./admin/img/rocketvalidator-logo.png)](https://rocketvalidator.com/) -[Rocket Validator](https://rocketvalidator.com/) helps us find HTML markup or accessibility issues. +[Rocket Validator](https://rocketvalidator.com/) helps us find [HTML markup and accessibility issues](https://rocketvalidator.com/stats/docusaurus.io). From 34b355b550eac64e2787ffc5dd813cbbd4f152ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 12:06:16 +0200 Subject: [PATCH 050/103] chore(deps): bump actions/dependency-review-action from 4.7.1 to 4.7.2 (#11373) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 5fc359d8ed..be47a2249b 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -15,4 +15,4 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Dependency Review - uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # 4.7.1 + uses: actions/dependency-review-action@bc41886e18ea39df68b1b1245f4184881938e050 # 4.7.2 From c131034bc2e2a748408521831f860fae1a42d76d Mon Sep 17 00:00:00 2001 From: ya-dvorovenko <35799486+ya-dvorovenko@users.noreply.github.com> Date: Sun, 24 Aug 2025 12:11:22 +0200 Subject: [PATCH 051/103] docs: remove stray character in plugin overview page (#11368) --- website/docs/api/plugins/overview.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/api/plugins/overview.mdx b/website/docs/api/plugins/overview.mdx index 6109d4eb20..94ecbed65c 100644 --- a/website/docs/api/plugins/overview.mdx +++ b/website/docs/api/plugins/overview.mdx @@ -31,4 +31,4 @@ These plugins will add a useful behavior to your Docusaurus site. - [@docusaurus/plugin-google-analytics](./plugin-google-analytics.mdx) - [@docusaurus/plugin-google-gtag](./plugin-google-gtag.mdx) - [@docusaurus/plugin-google-tag-manager](./plugin-google-tag-manager.mdx) -- [@docusaurus/plugin-css-cascade-layers](./plugin-css-cascade-layers.mdx) u +- [@docusaurus/plugin-css-cascade-layers](./plugin-css-cascade-layers.mdx) From 305910758b1cfcfad053726ae7cff8d7c6ab0cc1 Mon Sep 17 00:00:00 2001 From: Feez2403 Date: Sun, 24 Aug 2025 20:11:21 +0200 Subject: [PATCH 052/103] feat(mermaid): support elk layout (#11357) Co-authored-by: sebastien --- .../docusaurus-theme-mermaid/package.json | 8 +- .../src/client/index.ts | 8 +- .../src/client/layouts.ts | 34 ++++++++ .../docusaurus-theme-mermaid/src/index.ts | 36 +++++++- project-words.txt | 1 + website/_dogfooding/_pages tests/diagrams.mdx | 85 +++++++++++++++++++ .../markdown-features-diagrams.mdx | 33 +++++++ website/package.json | 1 + yarn.lock | 13 +++ 9 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 packages/docusaurus-theme-mermaid/src/client/layouts.ts diff --git a/packages/docusaurus-theme-mermaid/package.json b/packages/docusaurus-theme-mermaid/package.json index c97bc97f59..47ecf7dca5 100644 --- a/packages/docusaurus-theme-mermaid/package.json +++ b/packages/docusaurus-theme-mermaid/package.json @@ -46,7 +46,13 @@ }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" + "react-dom": "^18.0.0 || ^19.0.0", + "@mermaid-js/layout-elk": "^0.1.9" + }, + "peerDependenciesMeta": { + "@mermaid-js/layout-elk": { + "optional": true + } }, "engines": { "node": ">=18.0" diff --git a/packages/docusaurus-theme-mermaid/src/client/index.ts b/packages/docusaurus-theme-mermaid/src/client/index.ts index 5ab3871813..8e86fc6c45 100644 --- a/packages/docusaurus-theme-mermaid/src/client/index.ts +++ b/packages/docusaurus-theme-mermaid/src/client/index.ts @@ -8,6 +8,8 @@ import {useState, useEffect, useMemo} from 'react'; import {useColorMode, useThemeConfig} from '@docusaurus/theme-common'; import mermaid from 'mermaid'; +import {ensureLayoutsRegistered} from './layouts'; + import type {RenderResult, MermaidConfig} from 'mermaid'; import type {ThemeConfig} from '@docusaurus/theme-mermaid'; @@ -37,7 +39,7 @@ function useMermaidId(): string { Note: Mermaid doesn't like values provided by Rect.useId() and throws */ - // TODO 2025-2026: check if useId() now works + // TODO Docusaurus v4: check if useId() now works // It could work thanks to https://github.com/facebook/react/pull/32001 // return useId(); // tried that, doesn't work ('#d:re:' is not a valid selector.) @@ -53,6 +55,8 @@ async function renderMermaid({ text: string; config: MermaidConfig; }): Promise { + await ensureLayoutsRegistered(); + /* Mermaid API is really weird :s It is a big mutable singleton with multiple config levels @@ -71,7 +75,7 @@ async function renderMermaid({ To use a new mermaid config (on colorMode change for example) we should update siteConfig, and it can only be done with initialize() */ - mermaid.mermaidAPI.initialize(config); + mermaid.initialize(config); try { return await mermaid.render(id, text); diff --git a/packages/docusaurus-theme-mermaid/src/client/layouts.ts b/packages/docusaurus-theme-mermaid/src/client/layouts.ts new file mode 100644 index 0000000000..25a26d1501 --- /dev/null +++ b/packages/docusaurus-theme-mermaid/src/client/layouts.ts @@ -0,0 +1,34 @@ +/** + * 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 mermaid from 'mermaid'; + +declare global { + // Global variable provided by bundler DefinePlugin + /* eslint-disable-next-line no-underscore-dangle */ + const __DOCUSAURUS_MERMAID_LAYOUT_ELK_ENABLED__: boolean; +} + +async function registerOptionalElkLayout() { + // Mermaid does not support ELK layouts by default + // See https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid-layout-elk + // ELK layouts are heavy, so we made it an optional peer dependency + // See https://github.com/facebook/docusaurus/pull/11357 + if (__DOCUSAURUS_MERMAID_LAYOUT_ELK_ENABLED__) { + const elkLayout = (await import('@mermaid-js/layout-elk')).default; + mermaid.registerLayoutLoaders(elkLayout); + } +} + +// Ensure we only try to register layouts once +let layoutsRegistered = false; +export async function ensureLayoutsRegistered(): Promise { + if (!layoutsRegistered) { + await registerOptionalElkLayout(); + layoutsRegistered = true; + } +} diff --git a/packages/docusaurus-theme-mermaid/src/index.ts b/packages/docusaurus-theme-mermaid/src/index.ts index 82b1636c59..622c6b2ef7 100644 --- a/packages/docusaurus-theme-mermaid/src/index.ts +++ b/packages/docusaurus-theme-mermaid/src/index.ts @@ -7,7 +7,26 @@ import type {Plugin} from '@docusaurus/types'; -export default function themeMermaid(): Plugin { +/** + * Check if the optional @mermaid-js/layout-elk package is available. + * It's an optional peer dependency because it's heavy and most Mermaid users + * might not need it. + */ +async function isElkLayoutPackageAvailable() { + try { + await import('@mermaid-js/layout-elk'); + return true; + } catch (e) { + return false; + } +} + +export default async function themeMermaid(): Promise> { + // For now, we infer based on package availability + // In the future, we could make it configurable so that users can disable it + // even if the package is installed? + const elkLayoutEnabled = await isElkLayoutPackageAvailable(); + return { name: 'docusaurus-theme-mermaid', @@ -17,6 +36,21 @@ export default function themeMermaid(): Plugin { getTypeScriptThemePath() { return '../src/theme'; }, + + configureWebpack(config, isServer, utils) { + return { + plugins: [ + new utils.currentBundler.instance.DefinePlugin({ + __DOCUSAURUS_MERMAID_LAYOUT_ELK_ENABLED__: JSON.stringify( + // We only need to include the layout registration code on the + // client side. This also solves a weird Webpack-only bug when + // compiling the server config due to the module being ESM-only. + !isServer && elkLayoutEnabled, + ), + }), + ], + }; + }, }; } diff --git a/project-words.txt b/project-words.txt index 03eeb8db4d..14a45f9141 100644 --- a/project-words.txt +++ b/project-words.txt @@ -48,6 +48,7 @@ Csapo Csvg Dabit dabit +dagre Daishi Datagit datagit diff --git a/website/_dogfooding/_pages tests/diagrams.mdx b/website/_dogfooding/_pages tests/diagrams.mdx index 1b11aa8d37..aba7585578 100644 --- a/website/_dogfooding/_pages tests/diagrams.mdx +++ b/website/_dogfooding/_pages tests/diagrams.mdx @@ -447,3 +447,88 @@ architecture-beta disk1:T -- B:server disk2:T -- B:db ``` + +## ELK Styling + +Mermaid provides an [ELK layout](https://mermaid.js.org/syntax/entityRelationshipDiagram.html#layout) + +### Dagre + +This is a "classical" Mermaid diagram, using the default Dagre layout. + +```mermaid +erDiagram + + COMPANY ||--o{ DEPARTMENT : has + COMPANY ||--o{ PROJECT : undertakes + COMPANY ||--o{ LOCATION : operates_in + COMPANY ||--o{ CLIENT : serves + + DEPARTMENT ||--o{ EMPLOYEE : employs + DEPARTMENT ||--o{ PROJECT : manages + DEPARTMENT ||--o{ BUDGET : allocated + + EMPLOYEE }o--o{ PROJECT : works_on + EMPLOYEE ||--|| ADDRESS : lives_at + EMPLOYEE }o--o{ SKILL : has + EMPLOYEE ||--o{ DEPENDENT : supports + + PROJECT ||--o{ CLIENT : for + PROJECT ||--o{ TASK : contains + +``` + +### ELK er diagram layout + +This ER diagram should look different, using the ELK layout. + +```mermaid +--- +config: + layout: elk +--- +erDiagram + + COMPANY ||--o{ DEPARTMENT : has + COMPANY ||--o{ PROJECT : undertakes + COMPANY ||--o{ LOCATION : operates_in + COMPANY ||--o{ CLIENT : serves + + DEPARTMENT ||--o{ EMPLOYEE : employs + DEPARTMENT ||--o{ PROJECT : manages + DEPARTMENT ||--o{ BUDGET : allocated + + EMPLOYEE }o--o{ PROJECT : works_on + EMPLOYEE ||--|| ADDRESS : lives_at + EMPLOYEE }o--o{ SKILL : has + EMPLOYEE ||--o{ DEPENDENT : supports + + PROJECT ||--o{ CLIENT : for + PROJECT ||--o{ TASK : contains + +``` + +Mermaid also provides a way of setting config parameters using a directive `%%{init:{"layout":"elk"}}%%` + +```mermaid +%%{init:{"layout":"elk"}}%% +erDiagram + + COMPANY ||--o{ DEPARTMENT : has + COMPANY ||--o{ PROJECT : undertakes + COMPANY ||--o{ LOCATION : operates_in + COMPANY ||--o{ CLIENT : serves + + DEPARTMENT ||--o{ EMPLOYEE : employs + DEPARTMENT ||--o{ PROJECT : manages + DEPARTMENT ||--o{ BUDGET : allocated + + EMPLOYEE }o--o{ PROJECT : works_on + EMPLOYEE ||--|| ADDRESS : lives_at + EMPLOYEE }o--o{ SKILL : has + EMPLOYEE ||--o{ DEPENDENT : supports + + PROJECT ||--o{ CLIENT : for + PROJECT ||--o{ TASK : contains + +``` diff --git a/website/docs/guides/markdown-features/markdown-features-diagrams.mdx b/website/docs/guides/markdown-features/markdown-features-diagrams.mdx index b8d652c0a3..829f971eeb 100644 --- a/website/docs/guides/markdown-features/markdown-features-diagrams.mdx +++ b/website/docs/guides/markdown-features/markdown-features-diagrams.mdx @@ -99,3 +99,36 @@ import Mermaid from '@theme/Mermaid'; C-->D;`} /> ``` + +## Layouts + +Mermaid supports different [layout engines](https://mermaid.js.org/intro/syntax-reference.html#layout-and-look): + +- The `dagre` layout engine is supported by default in Docusaurus. +- The `elk` layout engine is heavier and can be enabled by installing the optional `@mermaid-js/layout-elk` dependency. + +````md +```mermaid +--- +config: + layout: elk +--- +graph TD; + A-->B; + A-->C; + B-->D; + C-->D; +``` +```` + +```mermaid +--- +config: + layout: elk +--- +graph TD; + A-->B; + A-->C; + B-->D; + C-->D; +``` diff --git a/website/package.json b/website/package.json index 15fe623c78..7c2f4aa96c 100644 --- a/website/package.json +++ b/website/package.json @@ -53,6 +53,7 @@ "@docusaurus/theme-mermaid": "3.8.1", "@docusaurus/utils": "3.8.1", "@docusaurus/utils-common": "3.8.1", + "@mermaid-js/layout-elk": "^0.1.9", "clsx": "^2.0.0", "color": "^4.2.3", "fs-extra": "^11.1.1", diff --git a/yarn.lock b/yarn.lock index 38003b5fcb..19295194bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2591,6 +2591,14 @@ dependencies: "@types/mdx" "^2.0.0" +"@mermaid-js/layout-elk@^0.1.9": + version "0.1.9" + resolved "https://registry.yarnpkg.com/@mermaid-js/layout-elk/-/layout-elk-0.1.9.tgz#c773b9454875858a2f45412fe04502bccec83cf2" + integrity sha512-HuvaqFZBr6yT9PpWYockvKAZPJVd89yn/UjOYPxhzbZxlybL2v+2BjVCg7MVH6vRs1irUohb/s42HEdec1CCZw== + dependencies: + d3 "^7.9.0" + elkjs "^0.9.3" + "@mermaid-js/parser@^0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@mermaid-js/parser/-/parser-0.4.0.tgz#c1de1f5669f8fcbd0d0c9d124927d36ddc00d8a6" @@ -7937,6 +7945,11 @@ electron-to-chromium@^1.5.160: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz#477b0957e42f071905a86f7c905a9848f95d2bdb" integrity sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw== +elkjs@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/elkjs/-/elkjs-0.9.3.tgz#16711f8ceb09f1b12b99e971b138a8384a529161" + integrity sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ== + emittery@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" From ece9432b3a68cc4e3e2b7a644864beea8fd777bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Mon, 25 Aug 2025 14:22:10 +0200 Subject: [PATCH 053/103] fix(ssg): HTML minifier should preserve `` for `og:image` crawlers (#11383) --- packages/docusaurus-bundler/src/minifyHtml.ts | 4 + packages/docusaurus-faster/package.json | 2 +- yarn.lock | 108 +++++++++--------- 3 files changed, 59 insertions(+), 55 deletions(-) diff --git a/packages/docusaurus-bundler/src/minifyHtml.ts b/packages/docusaurus-bundler/src/minifyHtml.ts index d9dc29135f..8c564986f8 100644 --- a/packages/docusaurus-bundler/src/minifyHtml.ts +++ b/packages/docusaurus-bundler/src/minifyHtml.ts @@ -84,6 +84,10 @@ async function getSwcMinifier(): Promise { // TODO maybe it's fine to only keep React comments? preserveComments: [], + // Keep tag: important for social image crawlers like LinkedIn + // See https://github.com/swc-project/swc/issues/10994 + tagOmission: 'keep-head-and-body', + // Sorting these attributes (class) can lead to React hydration errors sortSpaceSeparatedAttributeValues: false, sortAttributes: false, diff --git a/packages/docusaurus-faster/package.json b/packages/docusaurus-faster/package.json index 0fe018b679..2fc0bba999 100644 --- a/packages/docusaurus-faster/package.json +++ b/packages/docusaurus-faster/package.json @@ -21,7 +21,7 @@ "@docusaurus/types": "3.8.1", "@rspack/core": "^1.4.0", "@swc/core": "^1.7.39", - "@swc/html": "^1.7.39", + "@swc/html": "^1.13.5", "browserslist": "^4.24.2", "lightningcss": "^1.27.0", "swc-loader": "^0.2.6", diff --git a/yarn.lock b/yarn.lock index 19295194bc..b176b5f639 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3662,73 +3662,73 @@ resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== -"@swc/html-darwin-arm64@1.7.39": - version "1.7.39" - resolved "https://registry.yarnpkg.com/@swc/html-darwin-arm64/-/html-darwin-arm64-1.7.39.tgz#a467ae253a8f8a3262195e907620ced6c54b5152" - integrity sha512-1A3A7CBp/AA2odEm+UduRXMsTKAfYcb3uaT2QdLBbLbDl81xSaYGOz/TSh1uGoA7Y9c+bYn2OFAGzsWq0HteEw== +"@swc/html-darwin-arm64@1.13.5": + version "1.13.5" + resolved "https://registry.yarnpkg.com/@swc/html-darwin-arm64/-/html-darwin-arm64-1.13.5.tgz#f2fd892c4b73334c10899b8ad636d545f2516df4" + integrity sha512-5r4kGFQJm85EKOxSiP9pUT/9T1uq+tx0s5HRqfM/J1hVZmpIq2GudBVYS8CGklVWAVQ0tBHhBuP9SysAb/pcSA== -"@swc/html-darwin-x64@1.7.39": - version "1.7.39" - resolved "https://registry.yarnpkg.com/@swc/html-darwin-x64/-/html-darwin-x64-1.7.39.tgz#aa297224af5b2d07b816ac7a843d7b3c73d263d4" - integrity sha512-MsISR4Hc91j/M8OxpNduIsURGCVMAYwH7dUkOYJdY6+1lettmGQqQsc+9i+FrCcIbUtpebsg0nheZRIl+BsZXA== +"@swc/html-darwin-x64@1.13.5": + version "1.13.5" + resolved "https://registry.yarnpkg.com/@swc/html-darwin-x64/-/html-darwin-x64-1.13.5.tgz#6c07a0089f53c80d5e64e6f9cffe76eb9797b1ce" + integrity sha512-bCY0BSfxrmbKpInB/wZFX0DH4hgEQBwWLeKNwZhafIR5R/tvzuiIvb/VdkeKv8+26r2lkedbp+EreCFnDqQ2BQ== -"@swc/html-linux-arm-gnueabihf@1.7.39": - version "1.7.39" - resolved "https://registry.yarnpkg.com/@swc/html-linux-arm-gnueabihf/-/html-linux-arm-gnueabihf-1.7.39.tgz#784cfe54280add7fc70c9ec80ebaf0842feef055" - integrity sha512-94h8eQD0XzKi03CJiwVrSAZbkBRJmt8gMKrnJeQd7x4mX7AuojXrdmCcUyGt8AMvCJtp3qI09A64ZGgBRRregQ== +"@swc/html-linux-arm-gnueabihf@1.13.5": + version "1.13.5" + resolved "https://registry.yarnpkg.com/@swc/html-linux-arm-gnueabihf/-/html-linux-arm-gnueabihf-1.13.5.tgz#c811bc0adf45b7f60f164936637c2c343b4df577" + integrity sha512-o6TVZERfx7Z8btauYE7nHgMEPPIVemqAZL3ViUTuBK6asF9wfJ4m2YAbsrlzi8xaLgaizWvdUV7W1qE5yfOxPg== -"@swc/html-linux-arm64-gnu@1.7.39": - version "1.7.39" - resolved "https://registry.yarnpkg.com/@swc/html-linux-arm64-gnu/-/html-linux-arm64-gnu-1.7.39.tgz#58be30a360ec432c54ce0dc79ff62214e0977b50" - integrity sha512-lugg4Ylmi5UKjm6iBVsPXGEFEM89Xo1sPShfIkU50FSRviBMUvN8rY7k03R+liVAj8cFB0qeisghGcQBCeCgjQ== +"@swc/html-linux-arm64-gnu@1.13.5": + version "1.13.5" + resolved "https://registry.yarnpkg.com/@swc/html-linux-arm64-gnu/-/html-linux-arm64-gnu-1.13.5.tgz#5363ca1587d34b0fb44526cc4007ebe89e3b32c4" + integrity sha512-I/Ip5FtCfQ0wYg2MurytkEWPZrFB1SOPOeTNu4n+PAWDBjEcX3q+wgmMpzoGgVljvpEAQviJ+jzRyLW2tDDVHA== -"@swc/html-linux-arm64-musl@1.7.39": - version "1.7.39" - resolved "https://registry.yarnpkg.com/@swc/html-linux-arm64-musl/-/html-linux-arm64-musl-1.7.39.tgz#a7d90220f48a78ea5155886799735ad29e3e4cbd" - integrity sha512-9BpGPzaWBMvTPXNyp64YY3dKo5wFEjfrZiMwd4fkqHSrE6MhA/ZnfYS98RpkqiTFExjvymxV6QSFg29SaWnr8A== +"@swc/html-linux-arm64-musl@1.13.5": + version "1.13.5" + resolved "https://registry.yarnpkg.com/@swc/html-linux-arm64-musl/-/html-linux-arm64-musl-1.13.5.tgz#d3da87913d92d154a301c6144add21dfaf51a7d0" + integrity sha512-q8RTISYZuI5qOR8wEhox2oC+ZBo5IBaT6N43b5W+JRSIMKIsY7hVgC3gSI/tG4/6K14hv2QrqtAUFzVpLwtkyA== -"@swc/html-linux-x64-gnu@1.7.39": - version "1.7.39" - resolved "https://registry.yarnpkg.com/@swc/html-linux-x64-gnu/-/html-linux-x64-gnu-1.7.39.tgz#22f2bc94d7ce962788ab4fea30fc13f414a996ab" - integrity sha512-4e+yWBSv5oOQEfnVZIsU8hTsoD5nuWdyF4mcLPKXIgdq77VTPd7j+m02DoIik2yiGrbfe+melhEjF6U9Ee/CwQ== +"@swc/html-linux-x64-gnu@1.13.5": + version "1.13.5" + resolved "https://registry.yarnpkg.com/@swc/html-linux-x64-gnu/-/html-linux-x64-gnu-1.13.5.tgz#4be7854414ca3484827d56de1772c0e78177f3a8" + integrity sha512-YFU0/xVWzjAtg5V6QREW510O5/SNILrm18Vo2qF1bTktCB2eCjNSjCHOdicvPXTImEUlTp0ey6wO+QvEuvRFAg== -"@swc/html-linux-x64-musl@1.7.39": - version "1.7.39" - resolved "https://registry.yarnpkg.com/@swc/html-linux-x64-musl/-/html-linux-x64-musl-1.7.39.tgz#65e32aedabe0eeeeb32d7c83559a5927a486f9e0" - integrity sha512-DPHlxiGpCQoIkR6RRpwh2vHnOdK8UjxiFBYuHLCe1v3JoocYWukoqa47vNFOGtEth/0QGoq254cf6dYcuXyq1g== +"@swc/html-linux-x64-musl@1.13.5": + version "1.13.5" + resolved "https://registry.yarnpkg.com/@swc/html-linux-x64-musl/-/html-linux-x64-musl-1.13.5.tgz#9c7ca5a35a0b657455bddf6d32d2791a379d6f46" + integrity sha512-/ilgZm7umDQTea97FlE0pIcoHTAlICE+aSoVvLi+ONL3wr4g1ebwlgQ5Cxpgp5cxnKeghDYpqP/mFLh+Ztl8DQ== -"@swc/html-win32-arm64-msvc@1.7.39": - version "1.7.39" - resolved "https://registry.yarnpkg.com/@swc/html-win32-arm64-msvc/-/html-win32-arm64-msvc-1.7.39.tgz#7e0ea15c8412287e65ae94fa121c3add84ead78e" - integrity sha512-hwhIRlXtjmcgIVu+46ved35Hd6sfMAOEOFbGr9aPQxFWUB3Lswp0V3FctSqNSqH+Tf7EkqVbJR31JnKR8IEG5w== +"@swc/html-win32-arm64-msvc@1.13.5": + version "1.13.5" + resolved "https://registry.yarnpkg.com/@swc/html-win32-arm64-msvc/-/html-win32-arm64-msvc-1.13.5.tgz#4d5ec4adb785f5ecd61a48f0334dc1ad4f1264c9" + integrity sha512-aLZvyEhzM6e7E53jelEp9ob/CrZ4K0atmsq+ctsaki8PNOu8shM03CEK1yQNCdZLR1kKkUgytyUVMEbhqz+IQQ== -"@swc/html-win32-ia32-msvc@1.7.39": - version "1.7.39" - resolved "https://registry.yarnpkg.com/@swc/html-win32-ia32-msvc/-/html-win32-ia32-msvc-1.7.39.tgz#233a9eb765a2b143466110d9b6e39b207485a890" - integrity sha512-2w3JSbdS8em6KxIiAi7s400IiNSS4rd7LjR3X9+m/fO7vTPxz2/evPDV5CCtQJQvkilCQkM5iiYX8ldS4iZRcQ== +"@swc/html-win32-ia32-msvc@1.13.5": + version "1.13.5" + resolved "https://registry.yarnpkg.com/@swc/html-win32-ia32-msvc/-/html-win32-ia32-msvc-1.13.5.tgz#f2c905581f963d1764a3b44a578f4e6e9e337056" + integrity sha512-51QXTdKMmgRriRmTzH0gkeyHLY4knJdAKEY1kPTBeguXCjgLIUX2nMQd24oe9ovJfPce0NCOmCSrODri8PiduQ== -"@swc/html-win32-x64-msvc@1.7.39": - version "1.7.39" - resolved "https://registry.yarnpkg.com/@swc/html-win32-x64-msvc/-/html-win32-x64-msvc-1.7.39.tgz#9427ab2eb8d59d0319598ad275e0b69ee4f44ab1" - integrity sha512-3Ww0GH6EVG4HmhWg98+b8d2UiKKVqwnvEYrsnBjh7x38DpLF893jkG0BWnEMnH9FfudtHtwM5cw9aXAioMWTAQ== +"@swc/html-win32-x64-msvc@1.13.5": + version "1.13.5" + resolved "https://registry.yarnpkg.com/@swc/html-win32-x64-msvc/-/html-win32-x64-msvc-1.13.5.tgz#cb144e422a4f703c463da6646842dda7a40fdcde" + integrity sha512-MnU1fMNZijEKkKTp12SKbNuH7rglgHhXSFZr+zjDhQmtVPEF4goCrBfoY8ZJ4j9FjOGyodFcYH6ulz95l9/QwQ== -"@swc/html@^1.7.39": - version "1.7.39" - resolved "https://registry.yarnpkg.com/@swc/html/-/html-1.7.39.tgz#b4cff2808764c4b939e27e58b9b92985895c65e6" - integrity sha512-ijsiFl7NrDjdef0qzp7yglr7bPsULrYZLoRRfx8CU2+gf4qj+je9iYu72whJ0FU6W/JVWDnwoJQlTK+jl9azqw== +"@swc/html@^1.13.5": + version "1.13.5" + resolved "https://registry.yarnpkg.com/@swc/html/-/html-1.13.5.tgz#0c0f3bcf4152c3afde5302d1046ce12d38f95aec" + integrity sha512-eVAyb3kk6wltz4FnWNRL06iYnqkQuTfpe5Fin9oLLmcpIYr2DgHcrGgeDJF4vJc9YZwACvEYmV8DC+1NfdzAJQ== dependencies: "@swc/counter" "^0.1.3" optionalDependencies: - "@swc/html-darwin-arm64" "1.7.39" - "@swc/html-darwin-x64" "1.7.39" - "@swc/html-linux-arm-gnueabihf" "1.7.39" - "@swc/html-linux-arm64-gnu" "1.7.39" - "@swc/html-linux-arm64-musl" "1.7.39" - "@swc/html-linux-x64-gnu" "1.7.39" - "@swc/html-linux-x64-musl" "1.7.39" - "@swc/html-win32-arm64-msvc" "1.7.39" - "@swc/html-win32-ia32-msvc" "1.7.39" - "@swc/html-win32-x64-msvc" "1.7.39" + "@swc/html-darwin-arm64" "1.13.5" + "@swc/html-darwin-x64" "1.13.5" + "@swc/html-linux-arm-gnueabihf" "1.13.5" + "@swc/html-linux-arm64-gnu" "1.13.5" + "@swc/html-linux-arm64-musl" "1.13.5" + "@swc/html-linux-x64-gnu" "1.13.5" + "@swc/html-linux-x64-musl" "1.13.5" + "@swc/html-win32-arm64-msvc" "1.13.5" + "@swc/html-win32-ia32-msvc" "1.13.5" + "@swc/html-win32-x64-msvc" "1.13.5" "@swc/jest@^0.2.36": version "0.2.36" From bfdcc73e178830b5eb7fc1b4902e30c857baed0d Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Thu, 28 Aug 2025 08:32:17 -0400 Subject: [PATCH 054/103] meta: add a section on AI-assisted PRs in CONTRIBUTING guide (#11388) --- CONTRIBUTING.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2247b52162..de66b73be0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -82,7 +82,7 @@ Apart from the `good first issue`, the following labels are also worth looking a - [`help wanted`](https://github.com/facebook/docusaurus/labels/help%20wanted): if you have specific knowledge in one domain, working on these issues can make your expertise shine. - [`status: accepting pr`](https://github.com/facebook/docusaurus/labels/status%3A%20accepting%20pr): community contributors can feel free to claim any of these. -If you want to work on any of these issues, just drop a message saying "I'd like to work on this", and we will assign the issue to you and update the issue's status as "claimed". **You are expected to send a pull request within seven days** after that, so we can still delegate the issue to someone else if you are unavailable. +If you want to work on any of these issues, just drop a message saying "I am working on this". **You do not need to ask for assignment to work on any issue explicitly marked as welcoming external contributions.** However, don't "cookie lick", or squat on an issue without actually sending a PR. You are automatically considered as giving up if you don't **send a PR within seven days after your comment**, and the issue automatically becomes up for grabs again. Alternatively, when opening an issue, you can also click the "self service" checkbox to indicate that you'd like to work on the issue yourself, which will also make us see the issue as "claimed". @@ -214,6 +214,16 @@ After you have signed the CLA, the CLA bot would automatically update the PR sta If it happens that you were unavailable and your PR gets closed, feel free to reopen once it's ready! We are still happy to review it, help you complete it, and eventually merge it. +### AI-assisted PRs + +We welcome the use of AI tools for authoring PRs, and we love to see people pushing the boundaries of AI capabilities. The core team actively uses different AI tools in our development process. However, we are aware that **many people are sending entirely AI-generated PRs as a low-effort way to farm OSS contributions**, so please be mindful of the following etiquette to show your respect for our time and our codebase: + +- **Be transparent**: If a significant portion of your code is AI generated, please indicate that in your PR description. +- **Be accountable**: You are responsible for the code you submit, regardless of whether it was generated by AI or written by you. You should be able to explain every line of the code, ensure all tests pass, and address our reviews. +- **Be reasonable**: Sometimes we receive 1k LOC PRs that are obviously AI-generated and implement unsolicited features. Please note that significant changes require prior communication and approval from the team in the form of an issue. + +We retain the right to close any PR that we deem as unproductive or low-effort, even when we agree with the spirit of the change. + ### Breaking Changes When adding a new breaking change, follow this template in your pull request: @@ -227,6 +237,10 @@ When adding a new breaking change, follow this template in your pull request: - **Severity (number of people affected x effort)**: ``` +> [!NOTE] +> +> Breaking changes should be discussed in the issue tracker before being implemented. + ### What Happens Next? The core Docusaurus team will be monitoring pull requests. Do help us by keeping pull requests consistent by following the guidelines above. From 6021faf97fdf3d39abf6e351df741d50d8d01588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 29 Aug 2025 19:00:11 +0200 Subject: [PATCH 055/103] fix(theme): render sidebar category index with unlisted children as a simple doc/link item (#11389) Co-authored-by: slorber <749374+slorber@users.noreply.github.com> --- .../theme/DocSidebarItem/Category/index.tsx | 49 ++++++++++++++++++- project-words.txt | 1 + .../unlisted-except-index/index.mdx | 7 +++ .../unlisted-except-index/unlisted1.mdx | 7 +++ .../unlisted-except-index/unlisted2.mdx | 7 +++ 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 website/_dogfooding/_docs tests/tests/visibility/unlisted-except-index/index.mdx create mode 100644 website/_dogfooding/_docs tests/tests/visibility/unlisted-except-index/unlisted1.mdx create mode 100644 website/_dogfooding/_docs tests/tests/visibility/unlisted-except-index/unlisted2.mdx diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx index 9a49be27d1..8f6a2a84a7 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category/index.tsx @@ -24,13 +24,19 @@ import { isActiveSidebarItem, findFirstSidebarItemLink, useDocSidebarItemsExpandedState, + useVisibleSidebarItems, } from '@docusaurus/plugin-content-docs/client'; import Link from '@docusaurus/Link'; import {translate} from '@docusaurus/Translate'; import useIsBrowser from '@docusaurus/useIsBrowser'; import DocSidebarItems from '@theme/DocSidebarItems'; +import DocSidebarItemLink from '@theme/DocSidebarItem/Link'; import type {Props} from '@theme/DocSidebarItem/Category'; +import type { + PropSidebarItemCategory, + PropSidebarItemLink, +} from '@docusaurus/plugin-content-docs'; import styles from './styles.module.css'; // If we navigate to a category and it becomes active, it should automatically @@ -136,7 +142,48 @@ function CategoryLinkLabel({label}: {label: string}) { ); } -export default function DocSidebarItemCategory({ +export default function DocSidebarItemCategory(props: Props): ReactNode { + const visibleChildren = useVisibleSidebarItems( + props.item.items, + props.activePath, + ); + if (visibleChildren.length === 0) { + return ; + } else { + return ; + } +} + +function isCategoryWithHref( + category: PropSidebarItemCategory, +): category is PropSidebarItemCategory & {href: string} { + return typeof category.href === 'string'; +} + +// If a category doesn't have any visible children, we render it as a link +function DocSidebarItemCategoryEmpty({item, ...props}: Props): ReactNode { + // If the category has no link, we don't render anything + // It's not super useful to render a category you can't open nor click + if (!isCategoryWithHref(item)) { + return null; + } + // We remove props that don't make sense for a link and forward the rest + const { + type, + collapsed, + collapsible, + items, + linkUnlisted, + ...forwardableProps + } = item; + const linkItem: PropSidebarItemLink = { + type: 'link', + ...forwardableProps, + }; + return ; +} + +function DocSidebarItemCategoryCollapsible({ item, onItemClick, activePath, diff --git a/project-words.txt b/project-words.txt index 14a45f9141..e377036d12 100644 --- a/project-words.txt +++ b/project-words.txt @@ -85,6 +85,7 @@ Fienny flac Flightcontrol Flightcontrol's +forwardable FOUC Français froms diff --git a/website/_dogfooding/_docs tests/tests/visibility/unlisted-except-index/index.mdx b/website/_dogfooding/_docs tests/tests/visibility/unlisted-except-index/index.mdx new file mode 100644 index 0000000000..84cb0f1feb --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/visibility/unlisted-except-index/index.mdx @@ -0,0 +1,7 @@ +# Unlisted Except Index + +This index page is listed, but the other pages are unlisted. + +import DocCardList from '@theme/DocCardList'; + + diff --git a/website/_dogfooding/_docs tests/tests/visibility/unlisted-except-index/unlisted1.mdx b/website/_dogfooding/_docs tests/tests/visibility/unlisted-except-index/unlisted1.mdx new file mode 100644 index 0000000000..e6ef3a75fe --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/visibility/unlisted-except-index/unlisted1.mdx @@ -0,0 +1,7 @@ +--- +unlisted: true +--- + +# Unlisted 1 + +This page is unlisted. diff --git a/website/_dogfooding/_docs tests/tests/visibility/unlisted-except-index/unlisted2.mdx b/website/_dogfooding/_docs tests/tests/visibility/unlisted-except-index/unlisted2.mdx new file mode 100644 index 0000000000..78a643b1c8 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/visibility/unlisted-except-index/unlisted2.mdx @@ -0,0 +1,7 @@ +--- +unlisted: true +--- + +# Unlisted 2 + +This page is unlisted. From 72c48b5806f587a6af6af39ae887a6249b8799e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Mon, 1 Sep 2025 15:21:14 +0200 Subject: [PATCH 056/103] chore(ci): Change Lighthouse trigger from pull_request_target to pull_request (#11393) --- .github/workflows/lighthouse-report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lighthouse-report.yml b/.github/workflows/lighthouse-report.yml index 6a0dcb8bae..f69bfd8541 100644 --- a/.github/workflows/lighthouse-report.yml +++ b/.github/workflows/lighthouse-report.yml @@ -1,7 +1,7 @@ name: Lighthouse Report on: - pull_request_target: + pull_request: branches: - main - docusaurus-v** From 3dacdf33c9eeec14a1e7ca05f9dc83a69d8fd506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 4 Sep 2025 15:29:26 +0200 Subject: [PATCH 057/103] feat(mdx): resolve `@site/*` markdown links, fix resolution priority bugs (#11397) --- .../src/__tests__/markdownLinks.test.ts | 56 +++++++++++++++++++ .../docusaurus-utils/src/markdownLinks.ts | 50 ++++++++++++----- .../tests/links/resolution/index.mdx | 19 +++++++ .../markdown-features-links.mdx | 14 +++-- 4 files changed, 120 insertions(+), 19 deletions(-) create mode 100644 website/_dogfooding/_docs tests/tests/links/resolution/index.mdx diff --git a/packages/docusaurus-utils/src/__tests__/markdownLinks.test.ts b/packages/docusaurus-utils/src/__tests__/markdownLinks.test.ts index 9a3e0ddfaa..0cf953b5b8 100644 --- a/packages/docusaurus-utils/src/__tests__/markdownLinks.test.ts +++ b/packages/docusaurus-utils/src/__tests__/markdownLinks.test.ts @@ -75,4 +75,60 @@ describe('resolveMarkdownLinkPathname', () => { test('api/classes/divine_uri.URI.md', '/docs/api/classes/uri'); test('another.md', '/docs/another'); }); + + it('uses relative file paths in priority - Fix #11099', () => { + // Unit test to fix bug https://github.com/facebook/docusaurus/issues/11099 + + const context: Context = { + siteDir: '.', + sourceFilePath: 'docs/test/file.mdx', + contentPaths: { + contentPath: 'docs', + contentPathLocalized: 'i18n/docs-localized', + }, + sourceToPermalink: new Map( + Object.entries({ + '@site/docs/file.mdx': '/docs/file', + '@site/docs/test/file.mdx': '/docs/test/file', + }), + ), + }; + + function test(linkPathname: string, expectedOutput: string) { + const output = resolveMarkdownLinkPathname(linkPathname, context); + expect(output).toEqual(expectedOutput); + } + + test('./file.mdx', '/docs/test/file'); + test('file.mdx', '/docs/test/file'); + }); + + it('can resolve @site/ links', () => { + const context: Context = { + siteDir: '.', + sourceFilePath: 'docs/test/file.mdx', + contentPaths: { + contentPath: 'docs', + contentPathLocalized: 'i18n/docs-localized', + }, + sourceToPermalink: new Map( + Object.entries({ + '@site/docs/file.mdx': '/docs/file', + '@site/docs/dir with spaces/file.mdx': '/docs/dir-with-spaces/file', + }), + ), + }; + + function test(linkPathname: string, expectedOutput: string) { + const output = resolveMarkdownLinkPathname(linkPathname, context); + expect(output).toEqual(expectedOutput); + } + + test('@site/docs/file.mdx', '/docs/file'); + test('@site/docs/dir with spaces/file.mdx', '/docs/dir-with-spaces/file'); + test( + '@site/docs/dir%20with%20spaces/file.mdx', + '/docs/dir-with-spaces/file', + ); + }); }); diff --git a/packages/docusaurus-utils/src/markdownLinks.ts b/packages/docusaurus-utils/src/markdownLinks.ts index a045ab4cd5..5a7ad51495 100644 --- a/packages/docusaurus-utils/src/markdownLinks.ts +++ b/packages/docusaurus-utils/src/markdownLinks.ts @@ -47,9 +47,6 @@ export type SourceToPermalink = Map< string // Permalink: "/docs/content" >; -// Note this is historical logic extracted during a 2024 refactor -// The algo has been kept exactly as before for retro compatibility -// See also https://github.com/facebook/docusaurus/pull/10168 export function resolveMarkdownLinkPathname( linkPathname: string, context: { @@ -60,20 +57,45 @@ export function resolveMarkdownLinkPathname( }, ): string | null { const {sourceFilePath, sourceToPermalink, contentPaths, siteDir} = context; - const sourceDirsToTry: string[] = []; - // ./file.md and ../file.md are always relative to the current file - if (!linkPathname.startsWith('./') && !linkPathname.startsWith('../')) { - sourceDirsToTry.push(...getContentPathList(contentPaths), siteDir); - } - // /file.md is never relative to the source file path - if (!linkPathname.startsWith('/')) { - sourceDirsToTry.push(path.dirname(sourceFilePath)); + + // If the link is already @site aliased, there's no need to resolve it + if (linkPathname.startsWith('@site/')) { + return sourceToPermalink.get(decodeURIComponent(linkPathname)) ?? null; } - const aliasedSourceMatch = sourceDirsToTry + // Get the dirs to "look into", ordered by priority, when resolving the link + function getSourceDirsToTry() { + // /file.md is always resolved from + // - the plugin content paths, + // - then siteDir + if (linkPathname.startsWith('/')) { + return [...getContentPathList(contentPaths), siteDir]; + } + // ./file.md and ../file.md are always resolved from + // - the current file dir + else if (linkPathname.startsWith('./') || linkPathname.startsWith('../')) { + return [path.dirname(sourceFilePath)]; + } + // file.md is resolved from + // - the current file dir, + // - then from the plugin content paths, + // - then siteDir + else { + return [ + path.dirname(sourceFilePath), + ...getContentPathList(contentPaths), + siteDir, + ]; + } + } + + const sourcesToTry = getSourceDirsToTry() .map((sourceDir) => path.join(sourceDir, decodeURIComponent(linkPathname))) - .map((source) => aliasedSitePath(source, siteDir)) - .find((source) => sourceToPermalink.has(source)); + .map((source) => aliasedSitePath(source, siteDir)); + + const aliasedSourceMatch = sourcesToTry.find((source) => + sourceToPermalink.has(source), + ); return aliasedSourceMatch ? sourceToPermalink.get(aliasedSourceMatch) ?? null diff --git a/website/_dogfooding/_docs tests/tests/links/resolution/index.mdx b/website/_dogfooding/_docs tests/tests/links/resolution/index.mdx new file mode 100644 index 0000000000..7b842a7c02 --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/links/resolution/index.mdx @@ -0,0 +1,19 @@ +# Link resolution tests + +## Test for issue [#11099](https://github.com/facebook/docusaurus/issues/11099) + +These links should target the root `index.mdx` file: + +[`/index.mdx`](/index.mdx) + +[`@site/_dogfooding/_docs tests/index.mdx`](@site/_dogfooding/_docs%20tests/index.mdx) + +These links should target the current `index.mdx` file: + +[`/tests/links/index.mdx`](/tests/links/resolution/index.mdx) + +[`@site/_dogfooding/_docs tests/tests/links/resolution/index.mdx`](@site/_dogfooding/_docs%20tests/tests/links/resolution/index.mdx) + +[`index.mdx`](index.mdx) + +[`./index.mdx`](./index.mdx) diff --git a/website/docs/guides/markdown-features/markdown-features-links.mdx b/website/docs/guides/markdown-features/markdown-features-links.mdx index 47a37100ca..5bd0127855 100644 --- a/website/docs/guides/markdown-features/markdown-features-links.mdx +++ b/website/docs/guides/markdown-features/markdown-features-links.mdx @@ -29,13 +29,17 @@ Reference to another [document in a subfolder](subfolder/doc3.mdx). Relative file paths are resolved against the current file's directory. Absolute file paths, on the other hand, are resolved relative to the **content root**, usually `docs/`, `blog/`, or [localized ones](../../i18n/i18n-tutorial.mdx) like `i18n/zh-Hans/plugin-content-docs/current`. -Absolute file paths can also be relative to the site directory. However, beware that links that begin with `/docs/` or `/blog/` are **not portable** as you would need to manually update them if you create new doc versions or localize them. +Here are some examples of file path links and how they get resolved, assuming the current file is `website/docs/category/source.mdx`: -```md -You can write [links](/otherFolder/doc4.mdx) relative to the content root (`/docs/`). +- `[link](./target.mdx)` is resolved from the current file's directory `website/docs/category`. +- `[link](../target.mdx)` is resolved from the parent file's directory `website/docs`. +- `[link](/target.mdx)` is resolved from the docs content root `website/docs`, using in priority the localized docs. +- `[link](target.mdx)` is resolved from the current directory `website/docs/category`, then from the docs content roots, then from the site root. -You can also write [links](/docs/otherFolder/doc4.mdx) relative to the site directory, but it's not recommended. -``` +Absolute file paths can also be relative to the site directory. However, beware that links that begin with `/docs/`, `/blog/` or `@site/` are **not portable** as you would need to manually update them if you create new doc versions or localize them: + +- `[link](/docs/target.mdx)` is resolved from the site root `website` (⚠️ less portable). +- `[link](@site/docs/target.mdx)` is relative to the site root `website` (⚠️ less portable). Using relative _file_ paths (with `.md` extensions) instead of relative _URL_ links provides the following benefits: From 7d4e430cf9ce6c3f55893b4a872e5f1275b49bd6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 14:34:04 +0200 Subject: [PATCH 058/103] chore(deps): bump actions/setup-node from 4.4.0 to 5.0.0 (#11403) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/argos.yml | 2 +- .github/workflows/build-blog-only.yml | 2 +- .github/workflows/build-hash-router.yml | 2 +- .github/workflows/build-perf.yml | 4 ++-- .github/workflows/canary-release.yml | 2 +- .github/workflows/continuous-releases.yml | 2 +- .github/workflows/lighthouse-report.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/showcase-test.yml | 2 +- .github/workflows/tests-e2e.yml | 10 +++++----- .github/workflows/tests-swizzle.yml | 2 +- .github/workflows/tests-windows.yml | 2 +- .github/workflows/tests.yml | 2 +- 13 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/argos.yml b/.github/workflows/argos.yml index fdb784c21d..7350e86e39 100644 --- a/.github/workflows/argos.yml +++ b/.github/workflows/argos.yml @@ -30,7 +30,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn diff --git a/.github/workflows/build-blog-only.yml b/.github/workflows/build-blog-only.yml index c91717b73f..8e70227b59 100644 --- a/.github/workflows/build-blog-only.yml +++ b/.github/workflows/build-blog-only.yml @@ -24,7 +24,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn diff --git a/.github/workflows/build-hash-router.yml b/.github/workflows/build-hash-router.yml index ae8d253db0..219fb09036 100644 --- a/.github/workflows/build-hash-router.yml +++ b/.github/workflows/build-hash-router.yml @@ -27,7 +27,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn diff --git a/.github/workflows/build-perf.yml b/.github/workflows/build-perf.yml index 16ee737ade..37e92f0d31 100644 --- a/.github/workflows/build-perf.yml +++ b/.github/workflows/build-perf.yml @@ -43,7 +43,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn @@ -75,7 +75,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn diff --git a/.github/workflows/canary-release.yml b/.github/workflows/canary-release.yml index 474045988f..5e18cd297c 100644 --- a/.github/workflows/canary-release.yml +++ b/.github/workflows/canary-release.yml @@ -24,7 +24,7 @@ jobs: with: fetch-depth: 0 # Needed to get the commit number with "git rev-list --count HEAD" - name: Set up Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn diff --git a/.github/workflows/continuous-releases.yml b/.github/workflows/continuous-releases.yml index 67d56fb230..b53397e873 100644 --- a/.github/workflows/continuous-releases.yml +++ b/.github/workflows/continuous-releases.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn diff --git a/.github/workflows/lighthouse-report.yml b/.github/workflows/lighthouse-report.yml index f69bfd8541..2a9dff8bd3 100644 --- a/.github/workflows/lighthouse-report.yml +++ b/.github/workflows/lighthouse-report.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 457878b276..6a5aa29ec4 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -22,7 +22,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn diff --git a/.github/workflows/showcase-test.yml b/.github/workflows/showcase-test.yml index 4c5e459e56..22678784af 100644 --- a/.github/workflows/showcase-test.yml +++ b/.github/workflows/showcase-test.yml @@ -24,7 +24,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn diff --git a/.github/workflows/tests-e2e.yml b/.github/workflows/tests-e2e.yml index 650e413229..ab6cfe059f 100644 --- a/.github/workflows/tests-e2e.yml +++ b/.github/workflows/tests-e2e.yml @@ -43,7 +43,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: ${{ matrix.node }} cache: yarn @@ -80,7 +80,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js LTS - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn @@ -126,7 +126,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js LTS - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn @@ -195,7 +195,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js LTS - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn @@ -235,7 +235,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js LTS - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn diff --git a/.github/workflows/tests-swizzle.yml b/.github/workflows/tests-swizzle.yml index 44702e4c3a..0f499f6a76 100644 --- a/.github/workflows/tests-swizzle.yml +++ b/.github/workflows/tests-swizzle.yml @@ -28,7 +28,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up Node LTS - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: lts/* cache: yarn diff --git a/.github/workflows/tests-windows.yml b/.github/workflows/tests-windows.yml index d168a7d4ba..4e18fe892a 100644 --- a/.github/workflows/tests-windows.yml +++ b/.github/workflows/tests-windows.yml @@ -34,7 +34,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: ${{ matrix.node }} cache: yarn diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c21fe9baf8..d902b011ea 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,7 +32,7 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: ${{ matrix.node }} cache: yarn From 3b7778a57ac05eec7b4d05367826ed661e7e06b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 14:34:12 +0200 Subject: [PATCH 059/103] chore(deps): bump actions/dependency-review-action from 4.7.2 to 4.7.3 (#11401) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index be47a2249b..21e1046e50 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -15,4 +15,4 @@ jobs: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Dependency Review - uses: actions/dependency-review-action@bc41886e18ea39df68b1b1245f4184881938e050 # 4.7.2 + uses: actions/dependency-review-action@595b5aeba73380359d98a5e087f648dbb0edce1b # 4.7.3 From e8f72697a5ec7a46ec69b6c5b7e1bc66e8ad8440 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 14:34:20 +0200 Subject: [PATCH 060/103] chore(deps): bump actions/github-script from 7.0.1 to 8.0.0 (#11402) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lighthouse-report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lighthouse-report.yml b/.github/workflows/lighthouse-report.yml index 2a9dff8bd3..53b34be6ad 100644 --- a/.github/workflows/lighthouse-report.yml +++ b/.github/workflows/lighthouse-report.yml @@ -53,7 +53,7 @@ jobs: - name: Format lighthouse score id: format_lighthouse_score - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # 7.0.1 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # 8.0.0 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | From 1c484e1d5903ea4c9f35a07224538b958794f6f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 12 Sep 2025 18:48:12 +0200 Subject: [PATCH 061/103] chore: drop support for Node 18, that reached End-of-Life (#11408) --- .github/workflows/tests-e2e.yml | 2 +- .github/workflows/tests-windows.yml | 2 +- .github/workflows/tests.yml | 2 +- packages/create-docusaurus/package.json | 2 +- .../templates/classic-typescript/package.json | 2 +- .../templates/classic/package.json | 2 +- .../templates/shared/docs/intro.md | 2 +- packages/docusaurus-babel/package.json | 2 +- packages/docusaurus-bundler/package.json | 2 +- packages/docusaurus-cssnano-preset/package.json | 2 +- packages/docusaurus-faster/package.json | 2 +- packages/docusaurus-logger/package.json | 2 +- packages/docusaurus-mdx-loader/package.json | 2 +- .../package.json | 2 +- .../docusaurus-plugin-content-blog/package.json | 2 +- .../docusaurus-plugin-content-docs/package.json | 2 +- .../docusaurus-plugin-content-pages/package.json | 2 +- .../package.json | 2 +- packages/docusaurus-plugin-debug/package.json | 2 +- .../package.json | 2 +- .../docusaurus-plugin-google-gtag/package.json | 2 +- .../package.json | 2 +- .../docusaurus-plugin-ideal-image/package.json | 2 +- packages/docusaurus-plugin-pwa/package.json | 2 +- packages/docusaurus-plugin-rsdoctor/package.json | 2 +- packages/docusaurus-plugin-sitemap/package.json | 2 +- packages/docusaurus-plugin-svgr/package.json | 2 +- .../package.json | 2 +- packages/docusaurus-preset-classic/package.json | 2 +- .../package.json | 2 +- packages/docusaurus-theme-classic/package.json | 2 +- packages/docusaurus-theme-common/package.json | 2 +- .../docusaurus-theme-live-codeblock/package.json | 2 +- packages/docusaurus-theme-mermaid/package.json | 2 +- .../docusaurus-theme-search-algolia/package.json | 2 +- .../docusaurus-theme-translations/package.json | 2 +- packages/docusaurus-utils-common/package.json | 2 +- .../docusaurus-utils-validation/package.json | 2 +- packages/docusaurus-utils/package.json | 2 +- packages/docusaurus/package.json | 2 +- packages/docusaurus/src/server/i18n.ts | 1 + packages/eslint-plugin/package.json | 2 +- packages/lqip-loader/package.json | 2 +- website/community/5-release-process.mdx | 16 ++++++++++++++++ website/docs/installation.mdx | 2 +- 45 files changed, 60 insertions(+), 43 deletions(-) diff --git a/.github/workflows/tests-e2e.yml b/.github/workflows/tests-e2e.yml index ab6cfe059f..f54352b3c4 100644 --- a/.github/workflows/tests-e2e.yml +++ b/.github/workflows/tests-e2e.yml @@ -38,7 +38,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: ['18.0', '20', '22', '24'] + node: ['20.0', '20', '22', '24'] steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 diff --git a/.github/workflows/tests-windows.yml b/.github/workflows/tests-windows.yml index 4e18fe892a..119a7d4b79 100644 --- a/.github/workflows/tests-windows.yml +++ b/.github/workflows/tests-windows.yml @@ -27,7 +27,7 @@ jobs: runs-on: windows-latest strategy: matrix: - node: ['18.0', '20', '22', '24'] + node: ['20.0', '20', '22', '24'] steps: - name: Support longpaths run: git config --system core.longpaths true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d902b011ea..1299065136 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -27,7 +27,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: ['18.0', '20', '22', '24'] + node: ['20.0', '20', '22', '24'] steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 diff --git a/packages/create-docusaurus/package.json b/packages/create-docusaurus/package.json index 7c2ce37e28..d48cff9740 100755 --- a/packages/create-docusaurus/package.json +++ b/packages/create-docusaurus/package.json @@ -37,6 +37,6 @@ "@types/supports-color": "^8.1.1" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/create-docusaurus/templates/classic-typescript/package.json b/packages/create-docusaurus/templates/classic-typescript/package.json index 543f44f99b..6232d002b2 100644 --- a/packages/create-docusaurus/templates/classic-typescript/package.json +++ b/packages/create-docusaurus/templates/classic-typescript/package.json @@ -42,6 +42,6 @@ ] }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/create-docusaurus/templates/classic/package.json b/packages/create-docusaurus/templates/classic/package.json index 91083729fd..34ac77fad3 100644 --- a/packages/create-docusaurus/templates/classic/package.json +++ b/packages/create-docusaurus/templates/classic/package.json @@ -39,6 +39,6 @@ ] }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/create-docusaurus/templates/shared/docs/intro.md b/packages/create-docusaurus/templates/shared/docs/intro.md index 45e8604c8b..88f9571445 100644 --- a/packages/create-docusaurus/templates/shared/docs/intro.md +++ b/packages/create-docusaurus/templates/shared/docs/intro.md @@ -14,7 +14,7 @@ Or **try Docusaurus immediately** with **[docusaurus.new](https://docusaurus.new ### What you'll need -- [Node.js](https://nodejs.org/en/download/) version 18.0 or above: +- [Node.js](https://nodejs.org/en/download/) version 20.0 or above: - When installing Node.js, you are recommended to check all checkboxes related to dependencies. ## Generate a new site diff --git a/packages/docusaurus-babel/package.json b/packages/docusaurus-babel/package.json index 1c111b7c8b..262d3163a2 100644 --- a/packages/docusaurus-babel/package.json +++ b/packages/docusaurus-babel/package.json @@ -45,6 +45,6 @@ "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-bundler/package.json b/packages/docusaurus-bundler/package.json index 6b6e252cdf..098eea624d 100644 --- a/packages/docusaurus-bundler/package.json +++ b/packages/docusaurus-bundler/package.json @@ -55,6 +55,6 @@ "@total-typescript/shoehorn": "^0.1.2" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-cssnano-preset/package.json b/packages/docusaurus-cssnano-preset/package.json index d4d8fbacd1..9458712ef6 100644 --- a/packages/docusaurus-cssnano-preset/package.json +++ b/packages/docusaurus-cssnano-preset/package.json @@ -26,6 +26,6 @@ "to-vfile": "^6.1.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-faster/package.json b/packages/docusaurus-faster/package.json index 2fc0bba999..dbb59ca34c 100644 --- a/packages/docusaurus-faster/package.json +++ b/packages/docusaurus-faster/package.json @@ -29,7 +29,7 @@ "webpack": "^5.95.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "peerDependencies": { "@docusaurus/types": "*" diff --git a/packages/docusaurus-logger/package.json b/packages/docusaurus-logger/package.json index 14a58f1009..3f280dad8a 100644 --- a/packages/docusaurus-logger/package.json +++ b/packages/docusaurus-logger/package.json @@ -24,7 +24,7 @@ "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "devDependencies": { "@types/supports-color": "^8.1.1" diff --git a/packages/docusaurus-mdx-loader/package.json b/packages/docusaurus-mdx-loader/package.json index 46ba90b8bc..ed3f544c5e 100644 --- a/packages/docusaurus-mdx-loader/package.json +++ b/packages/docusaurus-mdx-loader/package.json @@ -62,6 +62,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-client-redirects/package.json b/packages/docusaurus-plugin-client-redirects/package.json index 7dcee5be1f..8520c63a8e 100644 --- a/packages/docusaurus-plugin-client-redirects/package.json +++ b/packages/docusaurus-plugin-client-redirects/package.json @@ -36,6 +36,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json index 615ce75013..4a4d3cd21c 100644 --- a/packages/docusaurus-plugin-content-blog/package.json +++ b/packages/docusaurus-plugin-content-blog/package.json @@ -56,7 +56,7 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "devDependencies": { "@total-typescript/shoehorn": "^0.1.2", diff --git a/packages/docusaurus-plugin-content-docs/package.json b/packages/docusaurus-plugin-content-docs/package.json index 7ac48ffa89..4f5f836ab5 100644 --- a/packages/docusaurus-plugin-content-docs/package.json +++ b/packages/docusaurus-plugin-content-docs/package.json @@ -65,6 +65,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-content-pages/package.json b/packages/docusaurus-plugin-content-pages/package.json index 16d3d9ed16..dd3beced4d 100644 --- a/packages/docusaurus-plugin-content-pages/package.json +++ b/packages/docusaurus-plugin-content-pages/package.json @@ -32,6 +32,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-css-cascade-layers/package.json b/packages/docusaurus-plugin-css-cascade-layers/package.json index 56c9bc6b34..1adc84cf55 100644 --- a/packages/docusaurus-plugin-css-cascade-layers/package.json +++ b/packages/docusaurus-plugin-css-cascade-layers/package.json @@ -25,6 +25,6 @@ "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-debug/package.json b/packages/docusaurus-plugin-debug/package.json index 6c7987ea9d..a58da46b00 100644 --- a/packages/docusaurus-plugin-debug/package.json +++ b/packages/docusaurus-plugin-debug/package.json @@ -32,6 +32,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-google-analytics/package.json b/packages/docusaurus-plugin-google-analytics/package.json index 1bba44dfff..9d4225ecb9 100644 --- a/packages/docusaurus-plugin-google-analytics/package.json +++ b/packages/docusaurus-plugin-google-analytics/package.json @@ -28,6 +28,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-google-gtag/package.json b/packages/docusaurus-plugin-google-gtag/package.json index 477dafd9b7..36a36170df 100644 --- a/packages/docusaurus-plugin-google-gtag/package.json +++ b/packages/docusaurus-plugin-google-gtag/package.json @@ -29,6 +29,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-google-tag-manager/package.json b/packages/docusaurus-plugin-google-tag-manager/package.json index 47444e2590..79e1c182bb 100644 --- a/packages/docusaurus-plugin-google-tag-manager/package.json +++ b/packages/docusaurus-plugin-google-tag-manager/package.json @@ -28,6 +28,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-ideal-image/package.json b/packages/docusaurus-plugin-ideal-image/package.json index 80244aa619..a6e77f5621 100644 --- a/packages/docusaurus-plugin-ideal-image/package.json +++ b/packages/docusaurus-plugin-ideal-image/package.json @@ -45,6 +45,6 @@ } }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-pwa/package.json b/packages/docusaurus-plugin-pwa/package.json index 824070ac91..411778c7ab 100644 --- a/packages/docusaurus-plugin-pwa/package.json +++ b/packages/docusaurus-plugin-pwa/package.json @@ -49,6 +49,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-rsdoctor/package.json b/packages/docusaurus-plugin-rsdoctor/package.json index 49bb6ed894..d7e57cbf86 100644 --- a/packages/docusaurus-plugin-rsdoctor/package.json +++ b/packages/docusaurus-plugin-rsdoctor/package.json @@ -30,6 +30,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-sitemap/package.json b/packages/docusaurus-plugin-sitemap/package.json index 62cd1ceb1c..54dab7877e 100644 --- a/packages/docusaurus-plugin-sitemap/package.json +++ b/packages/docusaurus-plugin-sitemap/package.json @@ -36,6 +36,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-svgr/package.json b/packages/docusaurus-plugin-svgr/package.json index a395bbfc46..6e303179e3 100644 --- a/packages/docusaurus-plugin-svgr/package.json +++ b/packages/docusaurus-plugin-svgr/package.json @@ -32,6 +32,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-plugin-vercel-analytics/package.json b/packages/docusaurus-plugin-vercel-analytics/package.json index 3cd3a72593..69671f0f5a 100644 --- a/packages/docusaurus-plugin-vercel-analytics/package.json +++ b/packages/docusaurus-plugin-vercel-analytics/package.json @@ -31,6 +31,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-preset-classic/package.json b/packages/docusaurus-preset-classic/package.json index 0ce142ee55..e9688ac1a1 100644 --- a/packages/docusaurus-preset-classic/package.json +++ b/packages/docusaurus-preset-classic/package.json @@ -39,6 +39,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-remark-plugin-npm2yarn/package.json b/packages/docusaurus-remark-plugin-npm2yarn/package.json index c8c62b2c2f..22f16b013b 100644 --- a/packages/docusaurus-remark-plugin-npm2yarn/package.json +++ b/packages/docusaurus-remark-plugin-npm2yarn/package.json @@ -30,6 +30,6 @@ "to-vfile": "^6.1.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index 1b76c00b8a..c2c887ef79 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -60,6 +60,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-theme-common/package.json b/packages/docusaurus-theme-common/package.json index 16de5ceb7a..0448a7c441 100644 --- a/packages/docusaurus-theme-common/package.json +++ b/packages/docusaurus-theme-common/package.json @@ -56,6 +56,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-theme-live-codeblock/package.json b/packages/docusaurus-theme-live-codeblock/package.json index 696adb8180..541cea0db2 100644 --- a/packages/docusaurus-theme-live-codeblock/package.json +++ b/packages/docusaurus-theme-live-codeblock/package.json @@ -42,6 +42,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-theme-mermaid/package.json b/packages/docusaurus-theme-mermaid/package.json index 47ecf7dca5..327e8a29e4 100644 --- a/packages/docusaurus-theme-mermaid/package.json +++ b/packages/docusaurus-theme-mermaid/package.json @@ -55,6 +55,6 @@ } }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-theme-search-algolia/package.json b/packages/docusaurus-theme-search-algolia/package.json index cd20a55108..c536cd4c29 100644 --- a/packages/docusaurus-theme-search-algolia/package.json +++ b/packages/docusaurus-theme-search-algolia/package.json @@ -58,6 +58,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-theme-translations/package.json b/packages/docusaurus-theme-translations/package.json index dd6d77946d..78ddde4b82 100644 --- a/packages/docusaurus-theme-translations/package.json +++ b/packages/docusaurus-theme-translations/package.json @@ -30,6 +30,6 @@ "lodash": "^4.17.21" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-utils-common/package.json b/packages/docusaurus-utils-common/package.json index a4d9b37692..cc2e54cd21 100644 --- a/packages/docusaurus-utils-common/package.json +++ b/packages/docusaurus-utils-common/package.json @@ -23,6 +23,6 @@ "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-utils-validation/package.json b/packages/docusaurus-utils-validation/package.json index faa78bddb5..a8c40528d4 100644 --- a/packages/docusaurus-utils-validation/package.json +++ b/packages/docusaurus-utils-validation/package.json @@ -31,6 +31,6 @@ "tmp-promise": "^3.0.3" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus-utils/package.json b/packages/docusaurus-utils/package.json index efcdce2b34..030266b428 100644 --- a/packages/docusaurus-utils/package.json +++ b/packages/docusaurus-utils/package.json @@ -41,7 +41,7 @@ "webpack": "^5.88.1" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "devDependencies": { "@types/dedent": "^0.7.0", diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index 1f48d810b4..c93d2e1a33 100644 --- a/packages/docusaurus/package.json +++ b/packages/docusaurus/package.json @@ -96,6 +96,6 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/docusaurus/src/server/i18n.ts b/packages/docusaurus/src/server/i18n.ts index 9b0021ae87..7c1aae5bcd 100644 --- a/packages/docusaurus/src/server/i18n.ts +++ b/packages/docusaurus/src/server/i18n.ts @@ -76,6 +76,7 @@ function getDefaultDirection(localeStr: string) { // see https://github.com/tc39/proposal-intl-locale-info // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getTextInfo // Node 18.0 implements a former version of the getTextInfo() proposal + // TODO Docusaurus v4: remove the fallback to locale.textInfo // @ts-expect-error: The TC39 proposal was updated const textInto = locale.getTextInfo?.() ?? locale.textInfo; return textInto.direction; diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 3a0548254a..c968b537e2 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -31,6 +31,6 @@ "eslint": ">=6" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" } } diff --git a/packages/lqip-loader/package.json b/packages/lqip-loader/package.json index 8f9fc307bd..3a89e0dd02 100644 --- a/packages/lqip-loader/package.json +++ b/packages/lqip-loader/package.json @@ -24,7 +24,7 @@ "tslib": "^2.6.0" }, "engines": { - "node": ">=18.0" + "node": ">=20.0" }, "devDependencies": { "@types/file-loader": "^5.0.1" diff --git a/website/community/5-release-process.mdx b/website/community/5-release-process.mdx index 5377f3dd65..a30cdaaddc 100644 --- a/website/community/5-release-process.mdx +++ b/website/community/5-release-process.mdx @@ -49,6 +49,12 @@ If you only use our [public API surface](#public-api-surface), you should be abl ::: +:::caution About End-of-Life Node.js versions + +We may drop support for End-of-Life Node.js versions in minor Docusaurus versions. Check the [Node.js support policy](#nodejs-support) section for more details. + +::: + ### Patch versions {#patch-versions} The `patch` version number is incremented on bugfixes releases. @@ -57,6 +63,16 @@ Whenever a new patch version is released, we publish: - an exhaustive changelog entry +## Node.js support policy {#nodejs-support} + +Each major version of Docusaurus supports a minimum Node.js version. This retro-compatibility will be preserved all along that release line. This runtime backward compatibility will be preserved throughout all the minor versions of the release line, except for End-of-Life Node.js versions. + +:::caution Support for End-of-Life versions + +On minor releases, we reserve the right to drop support for Node.js versions that reached End-of-Life ([Node.js release process and schedule](https://nodejs.org/en/about/previous-releases). **We do not consider it a Docusaurus breaking change**. We highly recommend using a maintained Node.js version. Beware that [End-of-Life Node.js versions do not receive security updates anymore](https://nodejs.org/en/blog/announcements/node-18-eol-support). + +::: + ## Versions {#versions} ```mdx-code-block diff --git a/website/docs/installation.mdx b/website/docs/installation.mdx index 1295709b94..df6ffa3d7d 100644 --- a/website/docs/installation.mdx +++ b/website/docs/installation.mdx @@ -21,7 +21,7 @@ Use **[docusaurus.new](https://docusaurus.new)** to test Docusaurus immediately ## Requirements {#requirements} -- [Node.js](https://nodejs.org/en/download/) version 18.0 or above (which can be checked by running `node -v`). You can use [nvm](https://github.com/nvm-sh/nvm) to manage multiple Node.js versions on a single machine. +- [Node.js](https://nodejs.org/en/download/) version 20.0 or above (which can be checked by running `node -v`). You can use [nvm](https://github.com/nvm-sh/nvm) to manage multiple Node.js versions on a single machine. - When installing Node.js, it is recommended to check all checkboxes related to dependencies. ## Scaffold project website {#scaffold-project-website} From 24d01bb839fd66021d399f80146ae326eead4058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 12 Sep 2025 19:37:30 +0200 Subject: [PATCH 062/103] fix(theme): fix `useColorMode()` visual glitches due to provider unmounts/remounts (#11405) --- .../src/contexts/colorMode.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/docusaurus-theme-common/src/contexts/colorMode.tsx b/packages/docusaurus-theme-common/src/contexts/colorMode.tsx index 4a2482f907..6f4def96b9 100644 --- a/packages/docusaurus-theme-common/src/contexts/colorMode.tsx +++ b/packages/docusaurus-theme-common/src/contexts/colorMode.tsx @@ -13,6 +13,7 @@ import React, { useMemo, type ReactNode, } from 'react'; +import useIsBrowser from '@docusaurus/useIsBrowser'; import {ReactContextError} from '../utils/reactUtils'; import {createStorageSlot} from '../utils/storageUtils'; import {useThemeConfig} from '../utils/useThemeConfig'; @@ -124,10 +125,17 @@ function useColorModeState() { const { colorMode: {defaultMode}, } = useThemeConfig(); + const isBrowser = useIsBrowser(); - const [colorMode, setColorModeState] = useState(defaultMode); - const [colorModeChoice, setColorModeChoiceState] = - useState(null); + // Since the provider may unmount/remount on client navigation, we need to + // reinitialize the state with the correct values to avoid visual glitches. + // See also https://github.com/facebook/docusaurus/issues/11399#issuecomment-3279181314 + const [colorMode, setColorModeState] = useState( + isBrowser ? ColorModeAttribute.get() : defaultMode, + ); + const [colorModeChoice, setColorModeChoiceState] = useState( + isBrowser ? ColorModeChoiceAttribute.get() : null, + ); useEffect(() => { setColorModeState(ColorModeAttribute.get()); From af3d5caf86051bce4bf7f4f7dae807d92beda27b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 12 Sep 2025 19:51:22 +0200 Subject: [PATCH 063/103] fix(deps): upgrade webpack-dev-server to v5, fix security warning (#11410) --- packages/docusaurus/package.json | 2 +- yarn.lock | 488 +++++++++++++++++++------------ 2 files changed, 295 insertions(+), 195 deletions(-) diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index c93d2e1a33..9bab02348a 100644 --- a/packages/docusaurus/package.json +++ b/packages/docusaurus/package.json @@ -73,7 +73,7 @@ "update-notifier": "^6.0.2", "webpack": "^5.95.0", "webpack-bundle-analyzer": "^4.10.2", - "webpack-dev-server": "^4.15.2", + "webpack-dev-server": "^5.2.2", "webpack-merge": "^6.0.1" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index b176b5f639..9411138512 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2448,6 +2448,50 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jsonjoy.com/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/base64/-/base64-1.1.2.tgz#cf8ea9dcb849b81c95f14fc0aaa151c6b54d2578" + integrity sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA== + +"@jsonjoy.com/buffers@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/buffers/-/buffers-1.0.0.tgz#ade6895b7d3883d70f87b5743efaa12c71dfef7a" + integrity sha512-NDigYR3PHqCnQLXYyoLbnEdzMMvzeiCWo1KOut7Q0CoIqg9tUAPKJ1iq/2nFhc5kZtexzutNY0LFjdwWL3Dw3Q== + +"@jsonjoy.com/codegen@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz#5c23f796c47675f166d23b948cdb889184b93207" + integrity sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g== + +"@jsonjoy.com/json-pack@^1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/json-pack/-/json-pack-1.11.0.tgz#3d40d3d8042f5e9eeb005658a76b788e8ca84ac0" + integrity sha512-nLqSTAYwpk+5ZQIoVp7pfd/oSKNWlEdvTq2LzVA4r2wtWZg6v+5u0VgBOaDJuUfNOuw/4Ysq6glN5QKSrOCgrA== + dependencies: + "@jsonjoy.com/base64" "^1.1.2" + "@jsonjoy.com/buffers" "^1.0.0" + "@jsonjoy.com/codegen" "^1.0.0" + "@jsonjoy.com/json-pointer" "^1.0.1" + "@jsonjoy.com/util" "^1.9.0" + hyperdyperid "^1.2.0" + thingies "^2.5.0" + +"@jsonjoy.com/json-pointer@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz#049cb530ac24e84cba08590c5e36b431c4843408" + integrity sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg== + dependencies: + "@jsonjoy.com/codegen" "^1.0.0" + "@jsonjoy.com/util" "^1.9.0" + +"@jsonjoy.com/util@^1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/util/-/util-1.9.0.tgz#7ee95586aed0a766b746cd8d8363e336c3c47c46" + integrity sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ== + dependencies: + "@jsonjoy.com/buffers" "^1.0.0" + "@jsonjoy.com/codegen" "^1.0.0" + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" @@ -3849,10 +3893,10 @@ "@types/connect" "*" "@types/node" "*" -"@types/bonjour@^3.5.9": - version "3.5.10" - resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" - integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== +"@types/bonjour@^3.5.13": + version "3.5.13" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956" + integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ== dependencies: "@types/node" "*" @@ -3892,7 +3936,7 @@ resolved "https://registry.yarnpkg.com/@types/configstore/-/configstore-6.0.2.tgz#0b3d5e176cc5db6c1636a87a333d333693243f3a" integrity sha512-OS//b51j9uyR3zvwD04Kfs5kHpve2qalQ18JhY/ho3voGYUTPLEG90/ocfKPI48hyHH8T04f7KEEbK6Ue60oZQ== -"@types/connect-history-api-fallback@^1.3.5": +"@types/connect-history-api-fallback@^1.5.4": version "1.5.4" resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3" integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw== @@ -4183,7 +4227,7 @@ "@types/range-parser" "*" "@types/send" "*" -"@types/express-serve-static-core@^4.17.33": +"@types/express-serve-static-core@^4.17.21", "@types/express-serve-static-core@^4.17.33": version "4.19.6" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz#e01324c2a024ff367d92c66f48553ced0ab50267" integrity sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A== @@ -4203,10 +4247,10 @@ "@types/qs" "*" "@types/serve-static" "*" -"@types/express@^4.17.13": - version "4.17.17" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" - integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== +"@types/express@^4.17.21": + version "4.17.23" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.23.tgz#35af3193c640bfd4d7fe77191cd0ed411a433bef" + integrity sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^4.17.33" @@ -4411,6 +4455,13 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== +"@types/node-forge@^1.3.0": + version "1.3.14" + resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.14.tgz#006c2616ccd65550560c2757d8472eb6d3ecea0b" + integrity sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw== + dependencies: + "@types/node" "*" + "@types/node@*", "@types/node@>=10.0.0": version "22.7.9" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.9.tgz#2bf2797b5e84702d8262ea2cf843c3c3c880d0e9" @@ -4531,10 +4582,10 @@ resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== -"@types/retry@0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" - integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== +"@types/retry@0.12.2": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a" + integrity sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow== "@types/rtlcss@^3.5.1": version "3.5.4" @@ -4570,17 +4621,17 @@ dependencies: "@types/node" "*" -"@types/serve-index@^1.9.1": - version "1.9.1" - resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" - integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== +"@types/serve-index@^1.9.4": + version "1.9.4" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898" + integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug== dependencies: "@types/express" "*" -"@types/serve-static@*", "@types/serve-static@^1.13.10": - version "1.15.7" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" - integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== +"@types/serve-static@*", "@types/serve-static@^1.15.5": + version "1.15.8" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.8.tgz#8180c3fbe4a70e8f00b9f70b9ba7f08f35987877" + integrity sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg== dependencies: "@types/http-errors" "*" "@types/node" "*" @@ -4594,10 +4645,10 @@ "@types/glob" "~7.2.0" "@types/node" "*" -"@types/sockjs@^0.3.33": - version "0.3.33" - resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" - integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== +"@types/sockjs@^0.3.36": + version "0.3.36" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" + integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q== dependencies: "@types/node" "*" @@ -4698,10 +4749,10 @@ anymatch "^3.0.0" source-map "^0.6.0" -"@types/ws@^8.5.5": - version "8.5.5" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb" - integrity sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg== +"@types/ws@^8.5.10": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9" + integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg== dependencies: "@types/node" "*" @@ -5290,11 +5341,6 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== -array-flatten@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - array-ify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" @@ -5673,13 +5719,11 @@ body-parser@1.20.3: type-is "~1.6.18" unpipe "1.0.0" -bonjour-service@^1.0.11: - version "1.1.1" - resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.1.1.tgz#960948fa0e0153f5d26743ab15baf8e33752c135" - integrity sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg== +bonjour-service@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.3.0.tgz#80d867430b5a0da64e82a8047fc1e355bdb71722" + integrity sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA== dependencies: - array-flatten "^2.1.2" - dns-equal "^1.0.0" fast-deep-equal "^3.1.3" multicast-dns "^7.2.5" @@ -5803,6 +5847,13 @@ builtins@^5.0.0: dependencies: semver "^7.0.0" +bundle-name@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-4.1.0.tgz#f3b96b34160d6431a19d7688135af7cfb8797889" + integrity sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q== + dependencies: + run-applescript "^7.0.0" + byte-size@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-7.0.0.tgz#36528cd1ca87d39bd9abd51f5715dc93b6ceb032" @@ -6115,7 +6166,7 @@ chevrotain@~11.0.3: "@chevrotain/utils" "11.0.3" lodash-es "4.17.21" -chokidar@^3.5.3: +chokidar@^3.5.3, chokidar@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== @@ -6691,10 +6742,10 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== +cookie@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" + integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== cookie@~0.4.1: version "0.4.2" @@ -7623,12 +7674,18 @@ deepmerge@^4.2.2, deepmerge@^4.3.1: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== -default-gateway@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" - integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== +default-browser-id@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-5.0.0.tgz#a1d98bf960c15082d8a3fa69e83150ccccc3af26" + integrity sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA== + +default-browser@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-5.2.1.tgz#7b7ba61204ff3e425b556869ae6d3e9d9f1712cf" + integrity sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg== dependencies: - execa "^5.0.0" + bundle-name "^4.1.0" + default-browser-id "^5.0.0" defaults@^1.0.3: version "1.0.4" @@ -7656,6 +7713,11 @@ define-lazy-prop@^2.0.0: resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" @@ -7773,11 +7835,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== - dns-packet@^5.2.2: version "5.6.0" resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.0.tgz#2202c947845c7a63c23ece58f2f70ff6ab4c2f7d" @@ -8728,37 +8785,37 @@ exponential-backoff@^3.1.1: resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== -express@^4.17.3: - version "4.20.0" - resolved "https://registry.yarnpkg.com/express/-/express-4.20.0.tgz#f1d08e591fcec770c07be4767af8eb9bcfd67c48" - integrity sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw== +express@^4.21.2: + version "4.21.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32" + integrity sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA== dependencies: accepts "~1.3.8" array-flatten "1.1.1" body-parser "1.20.3" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.6.0" + cookie "0.7.1" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" encodeurl "~2.0.0" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "1.2.0" + finalhandler "1.3.1" fresh "0.5.2" http-errors "2.0.0" merge-descriptors "1.0.3" methods "~1.1.2" on-finished "2.4.1" parseurl "~1.3.3" - path-to-regexp "0.1.10" + path-to-regexp "0.1.12" proxy-addr "~2.0.7" - qs "6.11.0" + qs "6.13.0" range-parser "~1.2.1" safe-buffer "5.2.1" send "0.19.0" - serve-static "1.16.0" + serve-static "1.16.2" setprototypeof "1.2.0" statuses "2.0.1" type-is "~1.6.18" @@ -8961,13 +9018,13 @@ finalhandler@1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== +finalhandler@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== dependencies: debug "2.6.9" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" on-finished "2.4.1" parseurl "~1.3.3" @@ -9141,11 +9198,6 @@ fs-minipass@^3.0.0: dependencies: minipass "^5.0.0" -fs-monkey@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.4.tgz#ee8c1b53d3fe8bb7e5d2c5c5dfc0168afdd2f747" - integrity sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ== - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -9380,6 +9432,11 @@ glob-parent@^6.0.1, glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" +glob-to-regex.js@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/glob-to-regex.js/-/glob-to-regex.js-1.0.1.tgz#f71cc9cb8441471a9318626160bc8a35e1306b21" + integrity sha512-CG/iEvgQqfzoVsMUbxSJcwbG2JwyZ3naEqPkeltwl0BSS8Bp83k3xlGms+0QdWFUAwV+uvo80wNswKF6FWEkKg== + glob-to-regexp@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" @@ -9942,11 +9999,6 @@ html-encoding-sniffer@^3.0.0: dependencies: whatwg-encoding "^2.0.0" -html-entities@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.4.0.tgz#edd0cee70402584c8c76cc2c0556db09d1f45061" - integrity sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ== - html-escaper@^2.0.0, html-escaper@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -10073,7 +10125,7 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" -http-proxy-middleware@^2.0.3: +http-proxy-middleware@^2.0.9: version "2.0.9" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz#e9e63d68afaa4eee3d147f39149ab84c0c2815ef" integrity sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q== @@ -10131,6 +10183,11 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== +hyperdyperid@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/hyperdyperid/-/hyperdyperid-1.2.0.tgz#59668d323ada92228d2a869d3e474d5a33b69e6b" + integrity sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A== + iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -10369,10 +10426,10 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -ipaddr.js@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" - integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== +ipaddr.js@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== is-alphabetical@^2.0.0: version "2.0.1" @@ -10489,6 +10546,11 @@ is-docker@^2.0.0, is-docker@^2.1.1: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + is-extendable@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -10540,6 +10602,13 @@ is-hexadecimal@^2.0.0: resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz#86b5bf668fca307498d319dfc03289d781a90027" integrity sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg== +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + is-installed-globally@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" @@ -10573,6 +10642,11 @@ is-negative-zero@^2.0.3: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== +is-network-error@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-network-error/-/is-network-error-1.1.0.tgz#d26a760e3770226d11c169052f266a4803d9c997" + integrity sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g== + is-npm@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-6.0.0.tgz#b59e75e8915543ca5d881ecff864077cba095261" @@ -10759,6 +10833,13 @@ is-wsl@^2.1.1, is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" +is-wsl@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" + integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== + dependencies: + is-inside-container "^1.0.0" + is-yarn-global@^0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.4.1.tgz#b312d902b313f81e4eaf98b6361ba2b45cd694bb" @@ -11556,13 +11637,13 @@ latest-version@^7.0.0: dependencies: package-json "^8.1.0" -launch-editor@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.0.tgz#4c0c1a6ac126c572bd9ff9a30da1d2cae66defd7" - integrity sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ== +launch-editor@^2.6.1: + version "2.11.1" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.11.1.tgz#61a0b7314a42fd84a6cbb564573d9e9ffcf3d72b" + integrity sha512-SEET7oNfgSaB6Ym0jufAdCeo3meJVeCaaDyzRygy0xsp2BFKCprcfHljTq4QkzTLUxEKkFK6OK4811YM2oSrRg== dependencies: - picocolors "^1.0.0" - shell-quote "^1.7.3" + picocolors "^1.1.1" + shell-quote "^1.8.3" layout-base@^1.0.0: version "1.0.2" @@ -12421,12 +12502,17 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -memfs@^3.4.3: - version "3.6.0" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" - integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== +memfs@^4.6.0: + version "4.39.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-4.39.0.tgz#fa3bea08ba4eb736bbb024eced25859cb1d0e13a" + integrity sha512-tFRr2IkSXl2B6IAJsxjHIMTOsfLt9W+8+t2uNxCeQcz4tFqgQR8DYk8hlLH2HsucTctLuoHq3U0G08atyBE3yw== dependencies: - fs-monkey "^1.0.4" + "@jsonjoy.com/json-pack" "^1.11.0" + "@jsonjoy.com/util" "^1.9.0" + glob-to-regex.js "^1.0.1" + thingies "^2.5.0" + tree-dump "^1.0.3" + tslib "^2.0.0" memorystream@^0.3.1: version "0.3.1" @@ -12953,11 +13039,16 @@ micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.8: braces "^3.0.3" picomatch "^2.3.1" -mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": +mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== +"mime-db@>= 1.43.0 < 2", mime-db@^1.54.0: + version "1.54.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" + integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== + mime-db@~1.33.0: version "1.33.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" @@ -12970,13 +13061,20 @@ mime-types@2.1.18: dependencies: mime-db "~1.33.0" -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" +mime-types@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-3.0.1.tgz#b1d94d6997a9b32fd69ebaed0db73de8acb519ce" + integrity sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA== + dependencies: + mime-db "^1.54.0" + mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -13792,7 +13890,7 @@ obuf@^1.0.0, obuf@^1.1.2: resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== -on-finished@2.4.1: +on-finished@2.4.1, on-finished@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== @@ -13832,6 +13930,16 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" +open@^10.0.3: + version "10.2.0" + resolved "https://registry.yarnpkg.com/open/-/open-10.2.0.tgz#b9d855be007620e80b6fb05fac98141fe62db73c" + integrity sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA== + dependencies: + default-browser "^5.2.1" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + wsl-utils "^0.1.0" + open@^7.4.2: version "7.4.2" resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" @@ -13840,7 +13948,7 @@ open@^7.4.2: is-docker "^2.0.0" is-wsl "^2.1.1" -open@^8.0.9, open@^8.4.0, open@^8.4.2: +open@^8.4.0, open@^8.4.2: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== @@ -13994,12 +14102,13 @@ p-reduce@2.1.0, p-reduce@^2.0.0, p-reduce@^2.1.0: resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-2.1.0.tgz#09408da49507c6c274faa31f28df334bc712b64a" integrity sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw== -p-retry@^4.5.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" - integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== +p-retry@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-6.2.1.tgz#81828f8dc61c6ef5a800585491572cc9892703af" + integrity sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ== dependencies: - "@types/retry" "0.12.0" + "@types/retry" "0.12.2" + is-network-error "^1.0.0" retry "^0.13.1" p-timeout@^3.2.0: @@ -14307,10 +14416,10 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b" - integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w== +path-to-regexp@0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7" + integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ== path-to-regexp@3.3.0: version "3.3.0" @@ -15254,13 +15363,6 @@ q@^1.5.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - qs@6.13.0: version "6.13.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" @@ -16172,6 +16274,11 @@ rtlcss@^4.1.0: postcss "^8.4.21" strip-json-comments "^3.1.1" +run-applescript@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-7.1.0.tgz#2e9e54c4664ec3106c5b5630e249d3d6595c4911" + integrity sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q== + run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -16276,10 +16383,10 @@ schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: ajv "^6.12.5" ajv-keywords "^3.5.2" -schema-utils@^4.0.0, schema-utils@^4.0.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" - integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== +schema-utils@^4.0.0, schema-utils@^4.0.1, schema-utils@^4.2.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.2.tgz#0c10878bf4a73fd2b1dfd14b9462b26788c806ae" + integrity sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ== dependencies: "@types/json-schema" "^7.0.9" ajv "^8.9.0" @@ -16313,11 +16420,12 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== -selfsigned@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" - integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== +selfsigned@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" + integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== dependencies: + "@types/node-forge" "^1.3.0" node-forge "^1" semver-diff@^4.0.0: @@ -16356,25 +16464,6 @@ semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semve resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - send@0.19.0: version "0.19.0" resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" @@ -16427,16 +16516,6 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.16.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.0.tgz#2bf4ed49f8af311b519c46f272bf6ac3baf38a92" - integrity sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - serve-static@1.16.2: version "1.16.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" @@ -16544,10 +16623,10 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@^1.6.1, shell-quote@^1.7.3: - version "1.8.1" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" - integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== +shell-quote@^1.6.1, shell-quote@^1.8.3: + version "1.8.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.3.tgz#55e40ef33cf5c689902353a3d8cd1a6725f08b4b" + integrity sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw== shelljs@^0.8.5: version "0.8.5" @@ -17510,6 +17589,11 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" +thingies@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/thingies/-/thingies-2.5.0.tgz#5f7b882c933b85989f8466b528a6247a6881e04f" + integrity sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw== + through2@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -17646,6 +17730,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" integrity sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ== +tree-dump@^1.0.3: + version "1.1.0" + resolved "https://registry.yarnpkg.com/tree-dump/-/tree-dump-1.1.0.tgz#ab29129169dc46004414f5a9d4a3c6e89f13e8a4" + integrity sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA== + tree-node-cli@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/tree-node-cli/-/tree-node-cli-1.6.0.tgz#15b76fd7381be650746f5ea06bd70049a3448c08" @@ -17709,10 +17798,10 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.6.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.0.tgz#d124c86c3c05a40a91e6fdea4021bd31d377971b" - integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA== +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.6.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== tsutils@^3.21.0: version "3.21.0" @@ -18425,52 +18514,51 @@ webpack-bundle-analyzer@^4.10.2: sirv "^2.0.3" ws "^7.3.1" -webpack-dev-middleware@^5.3.4: - version "5.3.4" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz#eb7b39281cbce10e104eb2b8bf2b63fce49a3517" - integrity sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q== +webpack-dev-middleware@^7.4.2: + version "7.4.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-7.4.3.tgz#4e23b479a574549334641faa4e00670720f01839" + integrity sha512-5kA/PzpZzDz5mNOkcNLmU1UdjGeSSxd7rt1akWpI70jMNHLASiBPRaQZn0hgyhvhawfIwSnnLfDABIxL3ueyFg== dependencies: colorette "^2.0.10" - memfs "^3.4.3" - mime-types "^2.1.31" + memfs "^4.6.0" + mime-types "^3.0.1" + on-finished "^2.4.1" range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-dev-server@^4.15.2: - version "4.15.2" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz#9e0c70a42a012560860adb186986da1248333173" - integrity sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g== +webpack-dev-server@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz#96a143d50c58fef0c79107e61df911728d7ceb39" + integrity sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg== dependencies: - "@types/bonjour" "^3.5.9" - "@types/connect-history-api-fallback" "^1.3.5" - "@types/express" "^4.17.13" - "@types/serve-index" "^1.9.1" - "@types/serve-static" "^1.13.10" - "@types/sockjs" "^0.3.33" - "@types/ws" "^8.5.5" + "@types/bonjour" "^3.5.13" + "@types/connect-history-api-fallback" "^1.5.4" + "@types/express" "^4.17.21" + "@types/express-serve-static-core" "^4.17.21" + "@types/serve-index" "^1.9.4" + "@types/serve-static" "^1.15.5" + "@types/sockjs" "^0.3.36" + "@types/ws" "^8.5.10" ansi-html-community "^0.0.8" - bonjour-service "^1.0.11" - chokidar "^3.5.3" + bonjour-service "^1.2.1" + chokidar "^3.6.0" colorette "^2.0.10" compression "^1.7.4" connect-history-api-fallback "^2.0.0" - default-gateway "^6.0.3" - express "^4.17.3" + express "^4.21.2" graceful-fs "^4.2.6" - html-entities "^2.3.2" - http-proxy-middleware "^2.0.3" - ipaddr.js "^2.0.1" - launch-editor "^2.6.0" - open "^8.0.9" - p-retry "^4.5.0" - rimraf "^3.0.2" - schema-utils "^4.0.0" - selfsigned "^2.1.1" + http-proxy-middleware "^2.0.9" + ipaddr.js "^2.1.0" + launch-editor "^2.6.1" + open "^10.0.3" + p-retry "^6.2.0" + schema-utils "^4.2.0" + selfsigned "^2.4.1" serve-index "^1.9.1" sockjs "^0.3.24" spdy "^4.0.2" - webpack-dev-middleware "^5.3.4" - ws "^8.13.0" + webpack-dev-middleware "^7.4.2" + ws "^8.18.0" webpack-merge@^5.9.0: version "5.10.0" @@ -18957,11 +19045,23 @@ ws@^7.3.1: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== -ws@^8.11.0, ws@^8.13.0, ws@~8.17.1: +ws@^8.11.0, ws@^8.18.0: + version "8.18.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" + integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== + +ws@~8.17.1: version "8.17.1" resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== +wsl-utils@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/wsl-utils/-/wsl-utils-0.1.0.tgz#8783d4df671d4d50365be2ee4c71917a0557baab" + integrity sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw== + dependencies: + is-wsl "^3.1.0" + xdg-basedir@^5.0.1, xdg-basedir@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-5.1.0.tgz#1efba19425e73be1bc6f2a6ceb52a3d2c884c0c9" From 80a4518ffb6b4d91f01205268b8d1f8ebff8e1cb Mon Sep 17 00:00:00 2001 From: Bartosz Kaszubowski Date: Fri, 12 Sep 2025 22:19:51 +0200 Subject: [PATCH 064/103] fix(theme): remove hardcoded fill from Bluesky and LinkedIn icons (#11407) --- .../src/theme/Icon/Socials/Bluesky/index.tsx | 13 +++++++------ .../theme/Icon/Socials/Bluesky/styles.module.css | 14 ++++++++++++++ .../src/theme/Icon/Socials/LinkedIn/index.tsx | 13 +++++++------ .../theme/Icon/Socials/LinkedIn/styles.module.css | 14 ++++++++++++++ 4 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 packages/docusaurus-theme-classic/src/theme/Icon/Socials/Bluesky/styles.module.css create mode 100644 packages/docusaurus-theme-classic/src/theme/Icon/Socials/LinkedIn/styles.module.css diff --git a/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Bluesky/index.tsx b/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Bluesky/index.tsx index 0f0c400bb4..141bb4ed33 100644 --- a/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Bluesky/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Bluesky/index.tsx @@ -5,7 +5,9 @@ * LICENSE file in the root directory of this source tree. */ -import type {SVGProps, ReactNode} from 'react'; +import type {SVGProps, ReactNode, CSSProperties} from 'react'; +import clsx from 'clsx'; +import styles from './styles.module.css'; // SVG Source: https://svgl.app/ function Bluesky(props: SVGProps): ReactNode { @@ -16,11 +18,10 @@ function Bluesky(props: SVGProps): ReactNode { height="1em" preserveAspectRatio="xMidYMid" viewBox="0 0 256 226" - {...props}> - + style={{'--dark': '#0085ff', '--light': '#0085ff'} as CSSProperties} + {...props} + className={clsx(props.className, styles.blueskySvg)}> + ); } diff --git a/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Bluesky/styles.module.css b/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Bluesky/styles.module.css new file mode 100644 index 0000000000..b7ad757675 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Bluesky/styles.module.css @@ -0,0 +1,14 @@ +/** + * 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. + */ + +[data-theme='dark'] .blueskySvg { + fill: var(--light); +} + +[data-theme='light'] .blueskySvg { + fill: var(--dark); +} diff --git a/packages/docusaurus-theme-classic/src/theme/Icon/Socials/LinkedIn/index.tsx b/packages/docusaurus-theme-classic/src/theme/Icon/Socials/LinkedIn/index.tsx index 1970a5bcd1..ad339a2e98 100644 --- a/packages/docusaurus-theme-classic/src/theme/Icon/Socials/LinkedIn/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Icon/Socials/LinkedIn/index.tsx @@ -5,7 +5,9 @@ * LICENSE file in the root directory of this source tree. */ -import type {ReactNode, SVGProps} from 'react'; +import type {SVGProps, ReactNode, CSSProperties} from 'react'; +import clsx from 'clsx'; +import styles from './styles.module.css'; // SVG Source: https://svgl.app/ function LinkedIn(props: SVGProps): ReactNode { @@ -16,11 +18,10 @@ function LinkedIn(props: SVGProps): ReactNode { height="1em" preserveAspectRatio="xMidYMid" viewBox="0 0 256 256" - {...props}> - + style={{'--dark': '#0a66c2', '--light': '#ffffffe6'} as CSSProperties} + {...props} + className={clsx(props.className, styles.linkedinSvg)}> + ); } diff --git a/packages/docusaurus-theme-classic/src/theme/Icon/Socials/LinkedIn/styles.module.css b/packages/docusaurus-theme-classic/src/theme/Icon/Socials/LinkedIn/styles.module.css new file mode 100644 index 0000000000..dc1d40dc1e --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/Icon/Socials/LinkedIn/styles.module.css @@ -0,0 +1,14 @@ +/** + * 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. + */ + +[data-theme='dark'] .linkedinSvg { + fill: var(--light); +} + +[data-theme='light'] .linkedinSvg { + fill: var(--dark); +} From a9bab411adbd470d0e6f4e07825de1034d0eb6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 19 Sep 2025 12:11:39 +0200 Subject: [PATCH 065/103] feat(faster): upgrade Rspack to 1.5, use lazyBarrel experiment, remove deprecated option (#11415) Co-authored-by: slorber <749374+slorber@users.noreply.github.com> --- packages/docusaurus-faster/package.json | 2 +- packages/docusaurus/src/webpack/base.ts | 11 +- yarn.lock | 236 ++++++++++++------------ 3 files changed, 127 insertions(+), 122 deletions(-) diff --git a/packages/docusaurus-faster/package.json b/packages/docusaurus-faster/package.json index dbb59ca34c..37de17ee2b 100644 --- a/packages/docusaurus-faster/package.json +++ b/packages/docusaurus-faster/package.json @@ -19,7 +19,7 @@ "license": "MIT", "dependencies": { "@docusaurus/types": "3.8.1", - "@rspack/core": "^1.4.0", + "@rspack/core": "^1.5.0", "@swc/core": "^1.7.39", "@swc/html": "^1.13.5", "browserslist": "^4.24.2", diff --git a/packages/docusaurus/src/webpack/base.ts b/packages/docusaurus/src/webpack/base.ts index 3479d0041f..ed0b1f9fe5 100644 --- a/packages/docusaurus/src/webpack/base.ts +++ b/packages/docusaurus/src/webpack/base.ts @@ -181,9 +181,14 @@ export async function createBaseConfig({ experiments.incremental = false; } - if (process.env.ENABLE_RSPACK_LAZY_COMPILATION) { - console.log('Rspack lazyCompilation enabled'); - experiments.lazyCompilation = true; + // See https://rspack.rs/blog/announcing-1-5#barrel-file-optimization + if (process.env.DISABLE_RSPACK_LAZY_BARREL) { + console.log('Rspack lazyBarrel disabled'); + experiments.lazyBarrel = false; + } else { + // TODO remove after we upgrade to Rspack 1.6+ + // Enabled by default for Rspack >= 1.6 + experiments.lazyBarrel = true; } // TODO re-enable later, there's an Rspack performance issue diff --git a/yarn.lock b/yarn.lock index 9411138512..3d53a19683 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2062,25 +2062,25 @@ dependencies: loader-utils "^2.0.0" -"@emnapi/core@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.3.tgz#9ac52d2d5aea958f67e52c40a065f51de59b77d6" - integrity sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g== +"@emnapi/core@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.5.0.tgz#85cd84537ec989cebb2343606a1ee663ce4edaf0" + integrity sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg== dependencies: - "@emnapi/wasi-threads" "1.0.2" + "@emnapi/wasi-threads" "1.1.0" tslib "^2.4.0" -"@emnapi/runtime@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.3.tgz#c0564665c80dc81c448adac23f9dfbed6c838f7d" - integrity sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ== +"@emnapi/runtime@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.5.0.tgz#9aebfcb9b17195dce3ab53c86787a6b7d058db73" + integrity sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ== dependencies: tslib "^2.4.0" -"@emnapi/wasi-threads@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz#977f44f844eac7d6c138a415a123818c655f874c" - integrity sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA== +"@emnapi/wasi-threads@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf" + integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ== dependencies: tslib "^2.4.0" @@ -2650,57 +2650,57 @@ dependencies: langium "3.3.1" -"@module-federation/error-codes@0.15.0": - version "0.15.0" - resolved "https://registry.yarnpkg.com/@module-federation/error-codes/-/error-codes-0.15.0.tgz#1e3ae45186a4034d806875cc61dd721b3826f462" - integrity sha512-CFJSF+XKwTcy0PFZ2l/fSUpR4z247+Uwzp1sXVkdIfJ/ATsnqf0Q01f51qqSEA6MYdQi6FKos9FIcu3dCpQNdg== +"@module-federation/error-codes@0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@module-federation/error-codes/-/error-codes-0.18.0.tgz#00830ece3b5b6bcda0a874a8426bcd94599bf738" + integrity sha512-Woonm8ehyVIUPXChmbu80Zj6uJkC0dD9SJUZ/wOPtO8iiz/m+dkrOugAuKgoiR6qH4F+yorWila954tBz4uKsQ== -"@module-federation/runtime-core@0.15.0": - version "0.15.0" - resolved "https://registry.yarnpkg.com/@module-federation/runtime-core/-/runtime-core-0.15.0.tgz#353113beee4fc50aeb85c1214202214a995ac4b4" - integrity sha512-RYzI61fRDrhyhaEOXH3AgIGlHiot0wPFXu7F43cr+ZnTi+VlSYWLdlZ4NBuT9uV6JSmH54/c+tEZm5SXgKR2sQ== +"@module-federation/runtime-core@0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@module-federation/runtime-core/-/runtime-core-0.18.0.tgz#d696bce1001b42a3074613a9e51b1f9e843f5492" + integrity sha512-ZyYhrDyVAhUzriOsVfgL6vwd+5ebYm595Y13KeMf6TKDRoUHBMTLGQ8WM4TDj8JNsy7LigncK8C03fn97of0QQ== dependencies: - "@module-federation/error-codes" "0.15.0" - "@module-federation/sdk" "0.15.0" + "@module-federation/error-codes" "0.18.0" + "@module-federation/sdk" "0.18.0" -"@module-federation/runtime-tools@0.15.0": - version "0.15.0" - resolved "https://registry.yarnpkg.com/@module-federation/runtime-tools/-/runtime-tools-0.15.0.tgz#b84bd87f7722e572438c06f3ce3f244ada287234" - integrity sha512-kzFn3ObUeBp5vaEtN1WMxhTYBuYEErxugu1RzFUERD21X3BZ+b4cWwdFJuBDlsmVjctIg/QSOoZoPXRKAO0foA== +"@module-federation/runtime-tools@0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@module-federation/runtime-tools/-/runtime-tools-0.18.0.tgz#8eddf50178974e0b2caaf8ad42e798eff3ab98e2" + integrity sha512-fSga9o4t1UfXNV/Kh6qFvRyZpPp3EHSPRISNeyT8ZoTpzDNiYzhtw0BPUSSD8m6C6XQh2s/11rI4g80UY+d+hA== dependencies: - "@module-federation/runtime" "0.15.0" - "@module-federation/webpack-bundler-runtime" "0.15.0" + "@module-federation/runtime" "0.18.0" + "@module-federation/webpack-bundler-runtime" "0.18.0" -"@module-federation/runtime@0.15.0": - version "0.15.0" - resolved "https://registry.yarnpkg.com/@module-federation/runtime/-/runtime-0.15.0.tgz#8ea3fd190211f78e95f5a7b32f0ed3a428c2ea91" - integrity sha512-dTPsCNum9Bhu3yPOcrPYq0YnM9eCMMMNB1wuiqf1+sFbQlNApF0vfZxooqz3ln0/MpgE0jerVvFsLVGfqvC9Ug== +"@module-federation/runtime@0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@module-federation/runtime/-/runtime-0.18.0.tgz#875486c67a0038d474a7efc890be5ee6f579ad38" + integrity sha512-+C4YtoSztM7nHwNyZl6dQKGUVJdsPrUdaf3HIKReg/GQbrt9uvOlUWo2NXMZ8vDAnf/QRrpSYAwXHmWDn9Obaw== dependencies: - "@module-federation/error-codes" "0.15.0" - "@module-federation/runtime-core" "0.15.0" - "@module-federation/sdk" "0.15.0" + "@module-federation/error-codes" "0.18.0" + "@module-federation/runtime-core" "0.18.0" + "@module-federation/sdk" "0.18.0" -"@module-federation/sdk@0.15.0": - version "0.15.0" - resolved "https://registry.yarnpkg.com/@module-federation/sdk/-/sdk-0.15.0.tgz#31e0b1e443e9e5761345e298ba5e49eab273e51d" - integrity sha512-PWiYbGcJrKUD6JZiEPihrXhV3bgXdll4bV7rU+opV7tHaun+Z0CdcawjZ82Xnpb8MCPGmqHwa1MPFeUs66zksw== +"@module-federation/sdk@0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@module-federation/sdk/-/sdk-0.18.0.tgz#47bdbc23768fc2b9aae4f70bad47d6454349c1c1" + integrity sha512-Lo/Feq73tO2unjmpRfyyoUkTVoejhItXOk/h5C+4cistnHbTV8XHrW/13fD5e1Iu60heVdAhhelJd6F898Ve9A== -"@module-federation/webpack-bundler-runtime@0.15.0": - version "0.15.0" - resolved "https://registry.yarnpkg.com/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.15.0.tgz#50d8d863e310f53829e4c5cf8bd41ef94e682ff1" - integrity sha512-i+3wu2Ljh2TmuUpsnjwZVupOVqV50jP0ndA8PSP4gwMKlgdGeaZ4VH5KkHAXGr2eiYUxYLMrJXz1+eILJqeGDg== +"@module-federation/webpack-bundler-runtime@0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.18.0.tgz#ba81a43800e6ceaff104a6956d9088b84df5a496" + integrity sha512-TEvErbF+YQ+6IFimhUYKK3a5wapD90d90sLsNpcu2kB3QGT7t4nIluE25duXuZDVUKLz86tEPrza/oaaCWTpvQ== dependencies: - "@module-federation/runtime" "0.15.0" - "@module-federation/sdk" "0.15.0" + "@module-federation/runtime" "0.18.0" + "@module-federation/sdk" "0.18.0" -"@napi-rs/wasm-runtime@^0.2.11": - version "0.2.11" - resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz#192c1610e1625048089ab4e35bc0649ce478500e" - integrity sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA== +"@napi-rs/wasm-runtime@^1.0.1": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.5.tgz#1fc8952d993d476c9e57999a3b886239119ce476" + integrity sha512-TBr9Cf9onSAS2LQ2+QHx6XcC6h9+RIzJgbqG3++9TUZSH204AwEy5jg3BTQ0VATsyoGj4ee49tN/y6rvaOOtcg== dependencies: - "@emnapi/core" "^1.4.3" - "@emnapi/runtime" "^1.4.3" - "@tybys/wasm-util" "^0.9.0" + "@emnapi/core" "^1.5.0" + "@emnapi/runtime" "^1.5.0" + "@tybys/wasm-util" "^0.10.1" "@netlify/functions@^1.6.0": version "1.6.0" @@ -3356,81 +3356,81 @@ fs-extra "^11.1.1" lodash "^4.17.21" -"@rspack/binding-darwin-arm64@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.4.0.tgz#e6af3cc2dad3f0e38655f959f8783f26e7766ac5" - integrity sha512-fOvbe71PAu9mM4f9KYssielLlTaQ0RcaS6fARkOuQRS3HfmZnAcMJA9kDkMAWBdsHQSW2RPHLji0Ng7lumAFvg== +"@rspack/binding-darwin-arm64@1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.5.3.tgz#e0a67212e5cc8e38e482daa3eeb8e951949fc59b" + integrity sha512-8R1uqr5E2CzRZjsA1QLXkD4xwcsiHmLJTIzCNj9QJ4+lCw6XgtPqpHZuk3zNROLayijEKwotGXJFHJIbgv1clA== -"@rspack/binding-darwin-x64@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.4.0.tgz#1cf3b935dccead1a145eed72ca746000d5a6fde8" - integrity sha512-1U7u5LdB+FwC90i3U9WDNeQoD8xoCfQBZPI0M6nB8pBCLW3HIP6Lzd60hTSKPuWOW6ZuXroUGoRG0z/ba8QlNg== +"@rspack/binding-darwin-x64@1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.5.3.tgz#3b7f395a03ace62c1d91b642dda80a9751d2c893" + integrity sha512-R4sb+scZbaBasyS+TQ6dRvv+f/2ZaZ0nXgY7t/ehcuGRvUz3S7FTJF/Mr/Ocxj5oVfb06thDAm+zaAVg+hsM9A== -"@rspack/binding-linux-arm64-gnu@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.4.0.tgz#2c33af789717b89a773bd9fdff2b3f1907f4253e" - integrity sha512-XYOfmHDYo88jruqAtyjklTqrNeixigP2QjsiZDiB0YvRQyaoLTw3hZ7RvhJbVruxFibwF75yiMlMD9LJgDTxrg== +"@rspack/binding-linux-arm64-gnu@1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.5.3.tgz#03d0deafeef03bae9e5b45902fff87a2b0dee13f" + integrity sha512-NeDJJRNTLx8wOQT+si90th7cdt04I2F697Mp5w0a3Jf3XHAmsraBMn0phdLGWJoUWrrfVGthjgZDl5lcc1UHEA== -"@rspack/binding-linux-arm64-musl@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.4.0.tgz#ea9dc16b431afc3a77dc5ce57963197a47cc3934" - integrity sha512-IvQNw3wN5Dro1CeT4f95W7R/ZAKREcsf9s0Kqk4NtBhaPxcEf+nV72mMDBzPUakEI/g32e5Evb91w3y0EFWhIg== +"@rspack/binding-linux-arm64-musl@1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.5.3.tgz#3f01316ff115811b8ef8acf6a1336d0dd8134a6b" + integrity sha512-M9utPq9s7zJkKapUlyfwwYT/rjZ+XM56NHQMUH9MVYgMJIl+66QURgWUXCAbuogxf1XWayUGQaZsgypoOrTG9A== -"@rspack/binding-linux-x64-gnu@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.4.0.tgz#dae15219743b7c885b1fa8e296b2b6b65e3b2d6a" - integrity sha512-b71w0Iflh/7gvwrpdfJYC4FsCb84mQen3YDYtiBF7VWdXKTN5OzWoibX/3i68l3HBncCf0vmWRr9XFrdejEZEg== +"@rspack/binding-linux-x64-gnu@1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.5.3.tgz#6a0831ada5a02993b670b22b4d827e71bfa8f6cc" + integrity sha512-AsKqU4pIg0yYg1VvSEU0NspIwCexqXD2AYE0wujAAwBo0hOfbt5dl1JCK7idiZdIQvoFg86HbfGwdHIVcFLI0w== -"@rspack/binding-linux-x64-musl@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.4.0.tgz#ad2aab3ae6dbc0bfa1e089d992d35216831e4d05" - integrity sha512-aGanEWtYRBiuS6RdI3rOwcV/tetq5duyYRmm/i1RoGAyfGp7vtoPpKVl7PP/hODWp3lZ9PVn3FhxsEaV7LY36Q== +"@rspack/binding-linux-x64-musl@1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.5.3.tgz#af68555cb1e1c4b46ce4789b1b67a0a7b5926685" + integrity sha512-0aHuvDef92pFZaHhk8Mp8RP9TfTzhQ+Pjqrc2ixRS/FeJA+jVB2CSaYlAPP4QrgXdmW7tewSxEw8hYhF9CNv/A== -"@rspack/binding-wasm32-wasi@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.4.0.tgz#cda5fe008b250d62d90f276d58f23d4cf030f57a" - integrity sha512-3LMP/bs/qCQw7Os/Y9HXVZ15TyXhngM1EQtX0ULJLPdOaX5yO/znXwdzRCI03T8i3MIZxno9EdgHlg1FNt4Puw== +"@rspack/binding-wasm32-wasi@1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.5.3.tgz#05346195c6791991207b91704e6979f495aa313d" + integrity sha512-Y7KN/ZRuWcFdjCzuZE0JsPwTqJAz1aipJsEOI3whBUj9Va2RwbR9r3vbW6OscS0Wm3rTJAfqH0xwx9x3GksnAw== dependencies: - "@napi-rs/wasm-runtime" "^0.2.11" + "@napi-rs/wasm-runtime" "^1.0.1" -"@rspack/binding-win32-arm64-msvc@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.4.0.tgz#a8ae10945f82695ccf637f87db51fbcd12000f02" - integrity sha512-cduBQqs8bGMFui7gpq+NlMOq1lr78jCvfUNEvZ59hU9xIx3Xewq1yQRNKuCikx24HJCtKRgzYdSMKMpUwnNNMg== +"@rspack/binding-win32-arm64-msvc@1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.5.3.tgz#a89c2604d7e5712778c25e0195b01e9524005f48" + integrity sha512-I9SqobDwFwcIUNzr+VwvR2lUGqfarOpFDp7mZmA6+qO/V0yJxS0aqBIwNoZB/UFPbUh71OdmFavBzcTYE9vPSg== -"@rspack/binding-win32-ia32-msvc@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.4.0.tgz#730f2c834aa6bb7afa97651e25060ceb6e2a9fbb" - integrity sha512-ZNWutTwz4iL/9QD0rYk+JKpes5Nx+bQys5aBVM2z/BefvWInw+3beeIRV6SgY8UiO5jc5GEwmdwdv8duzUrhbg== +"@rspack/binding-win32-ia32-msvc@1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.5.3.tgz#2e20bbacd1f3ce977666e648c73ebdef11d5b917" + integrity sha512-pPSzSycfK03lLNxzwEkrRUfqETB7y0KEEbO0HcGX63EC9Ne4SILJfkkH55G0PO4aT/dfAosAlkf6V64ATgrHGA== -"@rspack/binding-win32-x64-msvc@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.4.0.tgz#7556a823d3dccd9951698aeca45398474b916b13" - integrity sha512-pNwpjFCVYQpmA156GgjEqnHly3UZqNXYCJPkouAnUvVE9m0Xoo9May7v7ovKUH4ayySTryL42Ii8tL4iStyJuA== +"@rspack/binding-win32-x64-msvc@1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.5.3.tgz#ce4e849f26afc6ad39850d3ce1560b9e4aea0b88" + integrity sha512-He/GrFVrCZ4gBrHSxGd7mnwk9A9BDkAeZZEBnfK4n/HfXxU32WX5jiAGacFoJQYFLDOWTAcmxFad37TSs61zXw== -"@rspack/binding@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@rspack/binding/-/binding-1.4.0.tgz#b07a41443c82467ad53e909683c0346481e3af56" - integrity sha512-Kex9H6w44oTYzaQK/goV/BhUJoeWL8rPI1symDjRRvSK4ca/P4OceHvlQzfU0WGg2VKnhTAxH3+KMlpYQFabOQ== +"@rspack/binding@1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@rspack/binding/-/binding-1.5.3.tgz#31f879d8a2dcef0e27ab54dc34aa3be679fd8aa3" + integrity sha512-bWAKligHxelx3XxOgFmK6k1vR+ANxjBXLXTmgOiZxsJNScHJap3HYViXWJHKj5jvdXEvg9sC8TE7WNctCfa8iQ== optionalDependencies: - "@rspack/binding-darwin-arm64" "1.4.0" - "@rspack/binding-darwin-x64" "1.4.0" - "@rspack/binding-linux-arm64-gnu" "1.4.0" - "@rspack/binding-linux-arm64-musl" "1.4.0" - "@rspack/binding-linux-x64-gnu" "1.4.0" - "@rspack/binding-linux-x64-musl" "1.4.0" - "@rspack/binding-wasm32-wasi" "1.4.0" - "@rspack/binding-win32-arm64-msvc" "1.4.0" - "@rspack/binding-win32-ia32-msvc" "1.4.0" - "@rspack/binding-win32-x64-msvc" "1.4.0" + "@rspack/binding-darwin-arm64" "1.5.3" + "@rspack/binding-darwin-x64" "1.5.3" + "@rspack/binding-linux-arm64-gnu" "1.5.3" + "@rspack/binding-linux-arm64-musl" "1.5.3" + "@rspack/binding-linux-x64-gnu" "1.5.3" + "@rspack/binding-linux-x64-musl" "1.5.3" + "@rspack/binding-wasm32-wasi" "1.5.3" + "@rspack/binding-win32-arm64-msvc" "1.5.3" + "@rspack/binding-win32-ia32-msvc" "1.5.3" + "@rspack/binding-win32-x64-msvc" "1.5.3" -"@rspack/core@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@rspack/core/-/core-1.4.0.tgz#40edc101bf81b7b85b7c96971c1a4a5035c782f9" - integrity sha512-eIzbMYdrpJLjfkelKFLpxUObuv2gAmAuebUJmXeyf2OlFT/DGgoWRDGOVX4MpIHgcE1XCi27sqvOdRU4HA7Zgw== +"@rspack/core@^1.5.0": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@rspack/core/-/core-1.5.3.tgz#bbb4fb0a9e2d431633a289c127235c27025440ad" + integrity sha512-EMNXysJyqsfd2aVys5C7GDZKaLEcoN5qgs7ZFhWOWJGKgBqjdKTljyRTd4RRZV4fV6iAko/WrxnAxmzZNk8mjA== dependencies: - "@module-federation/runtime-tools" "0.15.0" - "@rspack/binding" "1.4.0" + "@module-federation/runtime-tools" "0.18.0" + "@rspack/binding" "1.5.3" "@rspack/lite-tapable" "1.0.1" "@rspack/lite-tapable@1.0.1": @@ -3838,10 +3838,10 @@ "@tufjs/canonical-json" "1.0.0" minimatch "^9.0.0" -"@tybys/wasm-util@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.9.0.tgz#3e75eb00604c8d6db470bf18c37b7d984a0e3355" - integrity sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw== +"@tybys/wasm-util@^0.10.1": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" + integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg== dependencies: tslib "^2.4.0" From 9c689880ed2d51d1cb5f394870fe09df9ad7d6e4 Mon Sep 17 00:00:00 2001 From: Dylan Tientcheu Date: Fri, 19 Sep 2025 14:15:57 +0200 Subject: [PATCH 066/103] feat(search): add runtime support for DocSearch v4 (#11327) Co-authored-by: sebastien --- .eslintrc.js | 2 +- .github/workflows/tests-windows.yml | 8 +- .github/workflows/tests.yml | 8 +- package.json | 3 + .../src/theme/Navbar/Search/styles.module.css | 3 +- .../package.json | 4 +- .../src/__tests__/utils.test.ts | 47 +++ .../src/__tests__/validateThemeConfig.test.ts | 285 +++++++++++-- .../src/client/index.ts | 7 +- .../src/client/useAlgoliaAskAi.ts | 108 +++++ .../useAlgoliaContextualFacetFilters.ts | 18 +- .../src/client/utils.ts | 40 ++ .../src/theme-search-algolia.d.ts | 62 ++- .../src/theme/SearchBar/index.tsx | 58 ++- .../src/theme/SearchBar/styles.css | 4 + .../src/theme/SearchPage/index.tsx | 96 +++-- .../src/theme/SearchPage/styles.module.css | 16 +- .../src/theme/SearchTranslations/index.ts | 269 ++++++++++-- .../src/validateThemeConfig.ts | 95 ++++- .../locales/ar/theme-search-algolia.json | 29 +- .../locales/base/theme-search-algolia.json | 100 +++-- .../locales/bg/theme-search-algolia.json | 31 +- .../locales/bn/theme-search-algolia.json | 87 ++-- .../locales/cs/theme-search-algolia.json | 87 ++-- .../locales/da/theme-search-algolia.json | 29 +- .../locales/de/theme-search-algolia.json | 29 +- .../locales/es/theme-search-algolia.json | 27 +- .../locales/et/theme-search-algolia.json | 45 +- .../locales/fa/theme-search-algolia.json | 31 +- .../locales/fil/theme-search-algolia.json | 33 +- .../locales/fr/theme-search-algolia.json | 27 +- .../locales/he/theme-search-algolia.json | 31 +- .../locales/hi/theme-search-algolia.json | 37 +- .../locales/hu/theme-search-algolia.json | 32 +- .../locales/id/theme-search-algolia.json | 27 +- .../locales/is/theme-search-algolia.json | 27 +- .../locales/it/theme-search-algolia.json | 27 +- .../locales/ja/theme-search-algolia.json | 27 +- .../locales/ko/theme-search-algolia.json | 27 +- .../locales/nb/theme-search-algolia.json | 27 +- .../locales/nl/theme-search-algolia.json | 27 +- .../locales/pl/theme-search-algolia.json | 27 +- .../locales/pt-BR/theme-search-algolia.json | 27 +- .../locales/pt-PT/theme-search-algolia.json | 29 +- .../locales/ru/theme-search-algolia.json | 27 +- .../locales/sl/theme-search-algolia.json | 27 +- .../locales/sr/theme-search-algolia.json | 29 +- .../locales/sv/theme-search-algolia.json | 27 +- .../locales/tk/theme-search-algolia.json | 27 +- .../locales/tr/theme-search-algolia.json | 27 +- .../locales/uk/theme-search-algolia.json | 31 +- .../locales/vi/theme-search-algolia.json | 31 +- .../locales/zh-Hans/theme-search-algolia.json | 31 +- .../locales/zh-Hant/theme-search-algolia.json | 31 +- project-words.txt | 1 + website/docs/search.mdx | 50 +++ website/docusaurus.config.ts | 11 + yarn.lock | 399 +++++++++++------- 58 files changed, 2353 insertions(+), 456 deletions(-) create mode 100644 packages/docusaurus-theme-search-algolia/src/__tests__/utils.test.ts create mode 100644 packages/docusaurus-theme-search-algolia/src/client/useAlgoliaAskAi.ts create mode 100644 packages/docusaurus-theme-search-algolia/src/client/utils.ts diff --git a/.eslintrc.js b/.eslintrc.js index e8e026c966..41859a9031 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -304,7 +304,7 @@ module.exports = { 'jest/prefer-expect-resolves': WARNING, 'jest/prefer-lowercase-title': [WARNING, {ignore: ['describe']}], 'jest/prefer-spy-on': WARNING, - 'jest/prefer-to-be': WARNING, + 'jest/prefer-to-be': OFF, 'jest/prefer-to-have-length': WARNING, 'jest/require-top-level-describe': ERROR, 'jest/valid-title': [ diff --git a/.github/workflows/tests-windows.yml b/.github/workflows/tests-windows.yml index 119a7d4b79..411ee27918 100644 --- a/.github/workflows/tests-windows.yml +++ b/.github/workflows/tests-windows.yml @@ -56,12 +56,16 @@ jobs: run: yarn build:website:fast - name: TypeCheck website - # TODO temporary, remove TS skipLibCheck # see https://github.com/facebook/docusaurus/pull/10486 - run: yarn workspace website typecheck --project tsconfig.skipLibCheck.json + run: yarn workspace website typecheck - name: TypeCheck website - min version - v5.1 run: | yarn add typescript@5.1.6 --exact -D -W --ignore-scripts + + # DocSearch@4/ai@5 doesn't support TS 5.1 (with skipLibCheck=false) + jq '.resolutions."@docsearch/react" = "^3.9.0"' package.json > package.json.tmp && mv -Force package.json.tmp package.json + yarn add @docsearch/react@^3.9.0 --exact -D -W --ignore-scripts + yarn workspace website typecheck - name: TypeCheck website - max version - Latest # For latest TS there are often lib check errors, so we disable it diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1299065136..29aef870cc 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -55,12 +55,16 @@ jobs: run: yarn workspace website test:css-order - name: TypeCheck website - # TODO temporary, remove TS skipLibCheck # see https://github.com/facebook/docusaurus/pull/10486 - run: yarn workspace website typecheck --project tsconfig.skipLibCheck.json + run: yarn workspace website typecheck - name: TypeCheck website - min version - v5.1 run: | yarn add typescript@5.1.6 --exact -D -W --ignore-scripts + + # DocSearch@4/ai@5 doesn't support TS 5.1 (with skipLibCheck=false) + jq '.resolutions."@docsearch/react" = "^3.9.0"' package.json > package.json.tmp && mv -f package.json.tmp package.json + yarn add @docsearch/react@^3.9.0 --exact -D -W --ignore-scripts + yarn workspace website typecheck - name: TypeCheck website - max version - Latest # For latest TS there are often lib check errors, so we disable it diff --git a/package.json b/package.json index 0e9d63abf9..342345f82d 100644 --- a/package.json +++ b/package.json @@ -129,5 +129,8 @@ "stylelint-config-standard": "^29.0.0", "typescript": "~5.8.2" }, + "resolutions": { + "@docsearch/react": "^4.0.1" + }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/packages/docusaurus-theme-classic/src/theme/Navbar/Search/styles.module.css b/packages/docusaurus-theme-classic/src/theme/Navbar/Search/styles.module.css index b59d29e3fc..c58238dcf9 100644 --- a/packages/docusaurus-theme-classic/src/theme/Navbar/Search/styles.module.css +++ b/packages/docusaurus-theme-classic/src/theme/Navbar/Search/styles.module.css @@ -22,7 +22,6 @@ See https://github.com/facebook/docusaurus/pull/9385 @media (min-width: 997px) { .navbarSearchContainer { - padding: var(--ifm-navbar-item-padding-vertical) - var(--ifm-navbar-item-padding-horizontal); + padding: 0 var(--ifm-navbar-item-padding-horizontal); } } diff --git a/packages/docusaurus-theme-search-algolia/package.json b/packages/docusaurus-theme-search-algolia/package.json index c536cd4c29..25362274ab 100644 --- a/packages/docusaurus-theme-search-algolia/package.json +++ b/packages/docusaurus-theme-search-algolia/package.json @@ -41,8 +41,8 @@ "@docusaurus/theme-translations": "3.8.1", "@docusaurus/utils": "3.8.1", "@docusaurus/utils-validation": "3.8.1", - "algoliasearch": "^5.17.1", - "algoliasearch-helper": "^3.22.6", + "algoliasearch": "^5.37.0", + "algoliasearch-helper": "^3.26.0", "clsx": "^2.0.0", "eta": "^2.2.0", "fs-extra": "^11.1.1", diff --git a/packages/docusaurus-theme-search-algolia/src/__tests__/utils.test.ts b/packages/docusaurus-theme-search-algolia/src/__tests__/utils.test.ts new file mode 100644 index 0000000000..b3ed86fff0 --- /dev/null +++ b/packages/docusaurus-theme-search-algolia/src/__tests__/utils.test.ts @@ -0,0 +1,47 @@ +/** + * 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 {mergeFacetFilters} from '../client/utils'; + +describe('mergeFacetFilters', () => { + it('merges [string,string]', () => { + expect(mergeFacetFilters('f1', 'f2')).toEqual(['f1', 'f2']); + }); + + it('merges [string,array]', () => { + // TODO this looks wrong to me, should be ['f1', ['f2', 'f3']] ? + expect(mergeFacetFilters('f1', ['f2', 'f3'])).toEqual(['f1', 'f2', 'f3']); + }); + + it('merges [string,undefined]', () => { + expect(mergeFacetFilters('f1', undefined)).toEqual('f1'); + }); + + it('merges [undefined,string]', () => { + expect(mergeFacetFilters(undefined, 'f1')).toEqual('f1'); + }); + + it('merges [array,undefined]', () => { + expect(mergeFacetFilters(['f1', 'f2'], undefined)).toEqual(['f1', 'f2']); + }); + + it('merges [undefined,array]', () => { + expect(mergeFacetFilters(undefined, ['f1', 'f2'])).toEqual(['f1', 'f2']); + }); + + it('merges [array,array]', () => { + expect(mergeFacetFilters(['f1'], ['f2'])).toEqual(['f1', 'f2']); + + // TODO this looks wrong to me, should be [['f1', 'f2'], ['f3', 'f4']] ? + expect(mergeFacetFilters(['f1', 'f2'], ['f3', 'f4'])).toEqual([ + 'f1', + 'f2', + 'f3', + 'f4', + ]); + }); +}); diff --git a/packages/docusaurus-theme-search-algolia/src/__tests__/validateThemeConfig.test.ts b/packages/docusaurus-theme-search-algolia/src/__tests__/validateThemeConfig.test.ts index 7559aef403..b41f5bb73b 100644 --- a/packages/docusaurus-theme-search-algolia/src/__tests__/validateThemeConfig.test.ts +++ b/packages/docusaurus-theme-search-algolia/src/__tests__/validateThemeConfig.test.ts @@ -7,8 +7,17 @@ import {DEFAULT_CONFIG, validateThemeConfig} from '../validateThemeConfig'; import type {Joi} from '@docusaurus/utils-validation'; +import type { + ThemeConfig, + UserThemeConfig, +} from '@docusaurus/theme-search-algolia'; -function testValidateThemeConfig(themeConfig: {[key: string]: unknown}) { +// mock DocSearch to a v4 version to allow AskAI tests to pass +jest.mock('@docsearch/react', () => ({version: '4.0.0'})); + +type AlgoliaInput = UserThemeConfig['algolia']; + +function testValidateThemeConfig(algolia: AlgoliaInput) { function validate( schema: Joi.ObjectSchema<{[key: string]: unknown}>, cfg: {[key: string]: unknown}, @@ -22,17 +31,20 @@ function testValidateThemeConfig(themeConfig: {[key: string]: unknown}) { return value; } - return validateThemeConfig({themeConfig, validate}); + return validateThemeConfig({ + themeConfig: (algolia ? {algolia} : {}) as ThemeConfig, + validate, + }); } describe('validateThemeConfig', () => { it('minimal config', () => { - const algolia = { + const algolia: AlgoliaInput = { indexName: 'index', apiKey: 'apiKey', appId: 'BH4D9OD16A', }; - expect(testValidateThemeConfig({algolia})).toEqual({ + expect(testValidateThemeConfig(algolia)).toEqual({ algolia: { ...DEFAULT_CONFIG, ...algolia, @@ -41,13 +53,14 @@ describe('validateThemeConfig', () => { }); it('unknown attributes', () => { - const algolia = { + const algolia: AlgoliaInput = { indexName: 'index', apiKey: 'apiKey', + // @ts-expect-error: expected type error! unknownKey: 'unknownKey', appId: 'BH4D9OD16A', }; - expect(testValidateThemeConfig({algolia})).toEqual({ + expect(testValidateThemeConfig(algolia)).toEqual({ algolia: { ...DEFAULT_CONFIG, ...algolia, @@ -58,47 +71,64 @@ describe('validateThemeConfig', () => { it('undefined config', () => { const algolia = undefined; expect(() => - testValidateThemeConfig({algolia}), + testValidateThemeConfig(algolia), ).toThrowErrorMatchingInlineSnapshot(`""themeConfig.algolia" is required"`); }); - it('undefined config 2', () => { + it('empty config', () => { expect(() => - testValidateThemeConfig({}), - ).toThrowErrorMatchingInlineSnapshot(`""themeConfig.algolia" is required"`); + testValidateThemeConfig( + // @ts-expect-error: expected type error! + {}, + ), + ).toThrowErrorMatchingInlineSnapshot( + `""algolia.appId" is required. If you haven't migrated to the new DocSearch infra, please refer to the blog post for instructions: https://docusaurus.io/blog/2021/11/21/algolia-docsearch-migration"`, + ); }); it('missing indexName config', () => { - const algolia = {apiKey: 'apiKey', appId: 'BH4D9OD16A'}; + // @ts-expect-error: expected type error! + const algolia: AlgoliaInput = { + apiKey: 'apiKey', + appId: 'BH4D9OD16A', + }; expect(() => - testValidateThemeConfig({algolia}), + testValidateThemeConfig(algolia), ).toThrowErrorMatchingInlineSnapshot(`""algolia.indexName" is required"`); }); it('missing apiKey config', () => { - const algolia = {indexName: 'indexName', appId: 'BH4D9OD16A'}; + // @ts-expect-error: expected type error! + const algolia: AlgoliaInput = { + indexName: 'indexName', + appId: 'BH4D9OD16A', + }; expect(() => - testValidateThemeConfig({algolia}), + testValidateThemeConfig(algolia), ).toThrowErrorMatchingInlineSnapshot(`""algolia.apiKey" is required"`); }); it('missing appId config', () => { - const algolia = {indexName: 'indexName', apiKey: 'apiKey'}; + // @ts-expect-error: expected type error! + const algolia: AlgoliaInput = { + indexName: 'indexName', + apiKey: 'apiKey', + }; expect(() => - testValidateThemeConfig({algolia}), + testValidateThemeConfig(algolia), ).toThrowErrorMatchingInlineSnapshot( `""algolia.appId" is required. If you haven't migrated to the new DocSearch infra, please refer to the blog post for instructions: https://docusaurus.io/blog/2021/11/21/algolia-docsearch-migration"`, ); }); it('contextualSearch config', () => { - const algolia = { + const algolia: AlgoliaInput = { appId: 'BH4D9OD16A', indexName: 'index', apiKey: 'apiKey', contextualSearch: true, }; - expect(testValidateThemeConfig({algolia})).toEqual({ + expect(testValidateThemeConfig(algolia)).toEqual({ algolia: { ...DEFAULT_CONFIG, ...algolia, @@ -107,13 +137,13 @@ describe('validateThemeConfig', () => { }); it('externalUrlRegex config', () => { - const algolia = { + const algolia: AlgoliaInput = { appId: 'BH4D9OD16A', indexName: 'index', apiKey: 'apiKey', externalUrlRegex: 'http://external-domain.com', }; - expect(testValidateThemeConfig({algolia})).toEqual({ + expect(testValidateThemeConfig(algolia)).toEqual({ algolia: { ...DEFAULT_CONFIG, ...algolia, @@ -123,7 +153,7 @@ describe('validateThemeConfig', () => { describe('replaceSearchResultPathname', () => { it('escapes from string', () => { - const algolia = { + const algolia: AlgoliaInput = { appId: 'BH4D9OD16A', indexName: 'index', apiKey: 'apiKey', @@ -132,7 +162,7 @@ describe('validateThemeConfig', () => { to: '/abc', }, }; - expect(testValidateThemeConfig({algolia})).toEqual({ + expect(testValidateThemeConfig(algolia)).toEqual({ algolia: { ...DEFAULT_CONFIG, ...algolia, @@ -145,17 +175,18 @@ describe('validateThemeConfig', () => { }); it('converts from regexp to string', () => { - const algolia = { + const algolia: AlgoliaInput = { appId: 'BH4D9OD16A', indexName: 'index', apiKey: 'apiKey', replaceSearchResultPathname: { + // @ts-expect-error: test regexp input from: /^\/docs\/(?:1\.0|next)/, to: '/abc', }, }; - expect(testValidateThemeConfig({algolia})).toEqual({ + expect(testValidateThemeConfig(algolia)).toEqual({ algolia: { ...DEFAULT_CONFIG, ...algolia, @@ -169,7 +200,7 @@ describe('validateThemeConfig', () => { }); it('searchParameters.facetFilters search config', () => { - const algolia = { + const algolia: AlgoliaInput = { appId: 'BH4D9OD16A', indexName: 'index', apiKey: 'apiKey', @@ -177,11 +208,213 @@ describe('validateThemeConfig', () => { facetFilters: ['version:1.0'], }, }; - expect(testValidateThemeConfig({algolia})).toEqual({ + expect(testValidateThemeConfig(algolia)).toEqual({ algolia: { ...DEFAULT_CONFIG, ...algolia, }, }); }); + + describe('askAi config validation', () => { + it('accepts string format (assistantId)', () => { + const algolia: AlgoliaInput = { + appId: 'BH4D9OD16A', + indexName: 'index', + apiKey: 'apiKey', + askAi: 'my-assistant-id', + }; + expect(testValidateThemeConfig(algolia)).toEqual({ + algolia: { + ...DEFAULT_CONFIG, + ...algolia, + askAi: { + indexName: 'index', + apiKey: 'apiKey', + appId: 'BH4D9OD16A', + assistantId: 'my-assistant-id', + }, + }, + }); + }); + + it('accepts full object format', () => { + const algolia: AlgoliaInput = { + appId: 'BH4D9OD16A', + indexName: 'index', + apiKey: 'apiKey', + askAi: { + indexName: 'ai-index', + apiKey: 'ai-apiKey', + appId: 'ai-appId', + assistantId: 'my-assistant-id', + }, + }; + expect(testValidateThemeConfig(algolia)).toEqual({ + algolia: { + ...DEFAULT_CONFIG, + ...algolia, + }, + }); + }); + + it('rejects invalid type', () => { + const algolia: AlgoliaInput = { + appId: 'BH4D9OD16A', + indexName: 'index', + apiKey: 'apiKey', + // @ts-expect-error: expected type error + askAi: 123, // Invalid: should be string or object + }; + expect(() => + testValidateThemeConfig(algolia), + ).toThrowErrorMatchingInlineSnapshot( + `"askAi must be either a string (assistantId) or an object with indexName, apiKey, appId, and assistantId"`, + ); + }); + + it('rejects object missing required fields', () => { + const algolia: AlgoliaInput = { + appId: 'BH4D9OD16A', + indexName: 'index', + apiKey: 'apiKey', + // @ts-expect-error: expected type error: missing mandatory fields + askAi: { + assistantId: 'my-assistant-id', + // Missing indexName, apiKey, appId + }, + }; + expect(() => + testValidateThemeConfig(algolia), + ).toThrowErrorMatchingInlineSnapshot( + `""algolia.askAi.indexName" is required"`, + ); + }); + + it('accepts undefined askAi', () => { + const algolia: AlgoliaInput = { + appId: 'BH4D9OD16A', + indexName: 'index', + apiKey: 'apiKey', + }; + expect(testValidateThemeConfig(algolia)).toEqual({ + algolia: { + ...DEFAULT_CONFIG, + ...algolia, + }, + }); + }); + + describe('Ask AI search parameters', () => { + it('accepts Ask AI facet filters', () => { + const algolia = { + appId: 'BH4D9OD16A', + indexName: 'index', + apiKey: 'apiKey', + askAi: { + indexName: 'ai-index', + apiKey: 'ai-apiKey', + appId: 'ai-appId', + assistantId: 'my-assistant-id', + searchParameters: { + facetFilters: ['version:1.0'], + }, + }, + } satisfies AlgoliaInput; + + expect(testValidateThemeConfig(algolia)).toEqual({ + algolia: { + ...DEFAULT_CONFIG, + ...algolia, + }, + }); + }); + + it('accepts distinct Ask AI / algolia facet filters', () => { + const algolia = { + appId: 'BH4D9OD16A', + indexName: 'index', + apiKey: 'apiKey', + searchParameters: { + facetFilters: ['version:algolia'], + }, + askAi: { + indexName: 'ai-index', + apiKey: 'ai-apiKey', + appId: 'ai-appId', + assistantId: 'my-assistant-id', + searchParameters: { + facetFilters: ['version:askAi'], + }, + }, + } satisfies AlgoliaInput; + + expect(testValidateThemeConfig(algolia)).toEqual({ + algolia: { + ...DEFAULT_CONFIG, + ...algolia, + }, + }); + }); + + it('falls back to algolia facet filters', () => { + const algolia = { + appId: 'BH4D9OD16A', + indexName: 'index', + apiKey: 'apiKey', + searchParameters: { + facetFilters: ['version:1.0'], + }, + askAi: { + indexName: 'ai-index', + apiKey: 'ai-apiKey', + appId: 'ai-appId', + assistantId: 'my-assistant-id', + searchParameters: {}, + }, + } satisfies AlgoliaInput; + + expect(testValidateThemeConfig(algolia)).toEqual({ + algolia: { + ...DEFAULT_CONFIG, + ...algolia, + askAi: { + ...algolia.askAi, + searchParameters: { + facetFilters: ['version:1.0'], + }, + }, + }, + }); + }); + + it('falls back to algolia facet filters with AskAI string format (assistantId)', () => { + const algolia = { + appId: 'BH4D9OD16A', + indexName: 'index', + apiKey: 'apiKey', + searchParameters: { + facetFilters: ['version:1.0'], + }, + askAi: 'my-assistant-id', + } satisfies AlgoliaInput; + + expect(testValidateThemeConfig(algolia)).toEqual({ + algolia: { + ...DEFAULT_CONFIG, + ...algolia, + askAi: { + indexName: algolia.indexName, + apiKey: algolia.apiKey, + appId: algolia.appId, + assistantId: 'my-assistant-id', + searchParameters: { + facetFilters: ['version:1.0'], + }, + }, + }, + }); + }); + }); + }); }); diff --git a/packages/docusaurus-theme-search-algolia/src/client/index.ts b/packages/docusaurus-theme-search-algolia/src/client/index.ts index 5050ce6aa0..c2d61a668d 100644 --- a/packages/docusaurus-theme-search-algolia/src/client/index.ts +++ b/packages/docusaurus-theme-search-algolia/src/client/index.ts @@ -6,5 +6,10 @@ */ export {useAlgoliaThemeConfig} from './useAlgoliaThemeConfig'; -export {useAlgoliaContextualFacetFilters} from './useAlgoliaContextualFacetFilters'; +export { + useAlgoliaContextualFacetFilters, + useAlgoliaContextualFacetFiltersIfEnabled, +} from './useAlgoliaContextualFacetFilters'; export {useSearchResultUrlProcessor} from './useSearchResultUrlProcessor'; +export {useAlgoliaAskAi} from './useAlgoliaAskAi'; +export {mergeFacetFilters} from './utils'; diff --git a/packages/docusaurus-theme-search-algolia/src/client/useAlgoliaAskAi.ts b/packages/docusaurus-theme-search-algolia/src/client/useAlgoliaAskAi.ts new file mode 100644 index 0000000000..ec80891fc6 --- /dev/null +++ b/packages/docusaurus-theme-search-algolia/src/client/useAlgoliaAskAi.ts @@ -0,0 +1,108 @@ +/** + * 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 {useCallback, useMemo, useState} from 'react'; +import { + version as docsearchVersion, + type DocSearchModalProps, + type DocSearchTranslations, +} from '@docsearch/react'; +import translations from '@theme/SearchTranslations'; +import {useAlgoliaContextualFacetFiltersIfEnabled} from './useAlgoliaContextualFacetFilters'; +import {mergeFacetFilters} from './utils'; +import type {AskAiConfig} from '@docusaurus/theme-search-algolia'; +import type {FacetFilters} from 'algoliasearch/lite'; + +// The minimal props the hook needs from DocSearch v4 props +// TODO Docusaurus v4: cleanup after we drop support for DocSearch v3 +interface DocSearchV4PropsLite { + indexName: string; + apiKey: string; + appId: string; + placeholder?: string; + translations?: DocSearchTranslations; + searchParameters?: DocSearchModalProps['searchParameters']; + askAi?: AskAiConfig; +} + +const isV4 = docsearchVersion.startsWith('4.'); + +type UseAskAiResult = { + canHandleAskAi: boolean; + isAskAiActive: boolean; + currentPlaceholder: string | undefined; + onAskAiToggle: (active: boolean) => void; + askAi?: AskAiConfig; + extraAskAiProps: Partial & { + askAi?: AskAiConfig; + canHandleAskAi?: boolean; + isAskAiActive?: boolean; + onAskAiToggle?: (active: boolean) => void; + }; +}; + +// We need to apply contextualSearch facetFilters to AskAI filters +// This can't be done at config normalization time because contextual filters +// can only be determined at runtime +function applyAskAiContextualSearch( + askAi: AskAiConfig | undefined, + contextualSearchFilters: FacetFilters | undefined, +): AskAiConfig | undefined { + if (!askAi) { + return undefined; + } + if (!contextualSearchFilters) { + return askAi; + } + const askAiFacetFilters = askAi.searchParameters?.facetFilters; + return { + ...askAi, + searchParameters: { + ...askAi.searchParameters, + facetFilters: mergeFacetFilters( + askAiFacetFilters, + contextualSearchFilters, + ), + }, + }; +} + +export function useAlgoliaAskAi(props: DocSearchV4PropsLite): UseAskAiResult { + const [isAskAiActive, setIsAskAiActive] = useState(false); + const contextualSearchFilters = useAlgoliaContextualFacetFiltersIfEnabled(); + + const askAi = useMemo(() => { + return applyAskAiContextualSearch(props.askAi, contextualSearchFilters); + }, [props.askAi, contextualSearchFilters]); + + const canHandleAskAi = Boolean(askAi); + + const currentPlaceholder = + isAskAiActive && isV4 + ? translations.modal?.searchBox?.placeholderTextAskAi + : translations.modal?.searchBox?.placeholderText || props?.placeholder; + + const onAskAiToggle = useCallback((askAiToggle: boolean) => { + setIsAskAiActive(askAiToggle); + }, []); + + const extraAskAiProps: UseAskAiResult['extraAskAiProps'] = { + askAi, + canHandleAskAi, + isAskAiActive, + onAskAiToggle, + }; + + return { + canHandleAskAi, + isAskAiActive, + currentPlaceholder, + onAskAiToggle, + askAi, + extraAskAiProps, + }; +} diff --git a/packages/docusaurus-theme-search-algolia/src/client/useAlgoliaContextualFacetFilters.ts b/packages/docusaurus-theme-search-algolia/src/client/useAlgoliaContextualFacetFilters.ts index e12b113088..753ee166bd 100644 --- a/packages/docusaurus-theme-search-algolia/src/client/useAlgoliaContextualFacetFilters.ts +++ b/packages/docusaurus-theme-search-algolia/src/client/useAlgoliaContextualFacetFilters.ts @@ -8,6 +8,8 @@ import {DEFAULT_SEARCH_TAG} from '@docusaurus/theme-common/internal'; import {useDocsContextualSearchTags} from '@docusaurus/plugin-content-docs/client'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import {useAlgoliaThemeConfig} from './useAlgoliaThemeConfig'; +import type {FacetFilters} from 'algoliasearch/lite'; function useSearchTags() { // only docs have custom search tags per version @@ -16,7 +18,7 @@ function useSearchTags() { } // Translate search-engine agnostic search tags to Algolia search filters -export function useAlgoliaContextualFacetFilters(): [string, string[]] { +export function useAlgoliaContextualFacetFilters(): FacetFilters { const locale = useDocusaurusContext().i18n.currentLocale; const tags = useSearchTags(); @@ -27,3 +29,17 @@ export function useAlgoliaContextualFacetFilters(): [string, string[]] { return [languageFilter, tagsFilter]; } + +export function useAlgoliaContextualFacetFiltersIfEnabled(): + | FacetFilters + | undefined { + const { + algolia: {contextualSearch}, + } = useAlgoliaThemeConfig(); + const facetFilters = useAlgoliaContextualFacetFilters(); + if (contextualSearch) { + return facetFilters; + } else { + return undefined; + } +} diff --git a/packages/docusaurus-theme-search-algolia/src/client/utils.ts b/packages/docusaurus-theme-search-algolia/src/client/utils.ts new file mode 100644 index 0000000000..3ec1336779 --- /dev/null +++ b/packages/docusaurus-theme-search-algolia/src/client/utils.ts @@ -0,0 +1,40 @@ +/** + * 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 type {FacetFilters} from 'algoliasearch/lite'; + +export function mergeFacetFilters( + f1: FacetFilters, + f2: FacetFilters, +): FacetFilters; + +export function mergeFacetFilters( + f1: FacetFilters | undefined, + f2: FacetFilters | undefined, +): FacetFilters | undefined; + +export function mergeFacetFilters( + f1: FacetFilters | undefined, + f2: FacetFilters | undefined, +): FacetFilters | undefined { + if (f1 === undefined) { + return f2; + } + if (f2 === undefined) { + return f1; + } + + const normalize = (f: FacetFilters): FacetFilters => + typeof f === 'string' ? [f] : f; + + // Historical behavior: we flatten everything + // TODO I'm pretty sure this is incorrect + // see https://www.algolia.com/doc/api-reference/api-parameters/facetFilters/?client=javascript + // Note: Algolia is working to provide a reliable facet merging strategy + // see https://github.com/facebook/docusaurus/pull/11327#issuecomment-3284742923 + return [...normalize(f1), ...normalize(f2)]; +} diff --git a/packages/docusaurus-theme-search-algolia/src/theme-search-algolia.d.ts b/packages/docusaurus-theme-search-algolia/src/theme-search-algolia.d.ts index 9e12b5e2dd..b5e8a26bc3 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme-search-algolia.d.ts +++ b/packages/docusaurus-theme-search-algolia/src/theme-search-algolia.d.ts @@ -6,8 +6,21 @@ */ declare module '@docusaurus/theme-search-algolia' { - import type {DeepPartial} from 'utility-types'; + import type {DeepPartial, Overwrite} from 'utility-types'; + import type {DocSearchProps} from '@docsearch/react'; + import type {FacetFilters} from 'algoliasearch/lite'; + + // The config after normalization (e.g. AskAI string -> object) + export type AskAiConfig = { + indexName: string; + apiKey: string; + appId: string; + assistantId: string; + searchParameters?: { + facetFilters?: FacetFilters; + }; + }; // DocSearch props that Docusaurus exposes directly through props forwarding type DocusaurusDocSearchProps = Pick< @@ -20,9 +33,15 @@ declare module '@docusaurus/theme-search-algolia' { | 'searchParameters' | 'insights' | 'initialQuery' - >; + > & { + // Docusaurus normalizes the AskAI config to an object + askAi?: AskAiConfig; + }; + + export type ThemeConfigAlgolia = DocusaurusDocSearchProps & { + // TODO Docusaurus v4: upgrade to DocSearch v4, migrate indexName to indices + indexName: string; - type ThemeConfigAlgolia = DocusaurusDocSearchProps & { // Docusaurus custom options, not coming from DocSearch contextualSearch: boolean; externalUrlRegex?: string; @@ -33,21 +52,23 @@ declare module '@docusaurus/theme-search-algolia' { }; }; - export type ThemeConfig = DocusaurusDocSearchProps & { + export type ThemeConfig = { algolia: ThemeConfigAlgolia; }; - export type UserThemeConfig = DeepPartial; -} - -declare module '@docusaurus/theme-search-algolia/client' { - import type {ThemeConfig} from '@docusaurus/theme-search-algolia'; - - export function useAlgoliaThemeConfig(): ThemeConfig; - - export function useAlgoliaContextualFacetFilters(): [string, string[]]; - - export function useSearchResultUrlProcessor(): (url: string) => string; + export type UserThemeConfig = { + algolia?: Overwrite< + DeepPartial, + { + // Required fields: + appId: ThemeConfigAlgolia['appId']; + apiKey: ThemeConfigAlgolia['apiKey']; + indexName: ThemeConfigAlgolia['indexName']; + // askAi also accepts a shorter string form + askAi?: string | AskAiConfig; + } + >; + }; } declare module '@theme/SearchPage' { @@ -65,6 +86,15 @@ declare module '@theme/SearchBar' { declare module '@theme/SearchTranslations' { import type {DocSearchTranslations} from '@docsearch/react'; - const translations: DocSearchTranslations & {placeholder: string}; + const translations: DocSearchTranslations & { + placeholder: string; + // TODO Docusaurus v4: cleanup after we drop support for DocSearch v3 + modal?: { + searchBox?: { + placeholderText?: string; + placeholderTextAskAi?: string; + }; + }; + }; export default translations; } diff --git a/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx b/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx index f0dd1189bf..11f38a8ae1 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx +++ b/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx @@ -24,6 +24,8 @@ import { import { useAlgoliaContextualFacetFilters, useSearchResultUrlProcessor, + useAlgoliaAskAi, + mergeFacetFilters, } from '@docusaurus/theme-search-algolia/client'; import Translate from '@docusaurus/Translate'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; @@ -35,10 +37,13 @@ import type { StoredDocSearchHit, DocSearchTransformClient, DocSearchHit, + DocSearchTranslations, + UseDocSearchKeyboardEventsProps, } from '@docsearch/react'; import type {AutocompleteState} from '@algolia/autocomplete-core'; import type {FacetFilters} from 'algoliasearch/lite'; +import type {ThemeConfigAlgolia} from '@docusaurus/theme-search-algolia'; type DocSearchProps = Omit< DocSearchModalProps, @@ -47,8 +52,20 @@ type DocSearchProps = Omit< contextualSearch?: string; externalUrlRegex?: string; searchPagePath: boolean | string; + askAi?: Exclude< + (DocSearchModalProps & {askAi: unknown})['askAi'], + string | undefined + >; }; +// extend DocSearchProps for v4 features +// TODO Docusaurus v4: cleanup after we drop support for DocSearch v3 +interface DocSearchV4Props extends DocSearchProps { + indexName: string; + askAi?: ThemeConfigAlgolia['askAi']; + translations?: DocSearchTranslations; +} + let DocSearchModal: typeof DocSearchModalType | null = null; function importDocSearchModalIfNeeded() { @@ -135,7 +152,7 @@ function Hit({ children, }: { hit: InternalDocSearchHit | StoredDocSearchHit; - children: React.ReactNode; + children: ReactNode; }) { return {children}; } @@ -163,14 +180,7 @@ function useSearchParameters({ contextualSearch, ...props }: DocSearchProps): DocSearchProps['searchParameters'] { - function mergeFacetFilters(f1: FacetFilters, f2: FacetFilters): FacetFilters { - const normalize = (f: FacetFilters): FacetFilters => - typeof f === 'string' ? [f] : f; - return [...normalize(f1), ...normalize(f2)]; - } - - const contextualSearchFacetFilters = - useAlgoliaContextualFacetFilters() as FacetFilters; + const contextualSearchFacetFilters = useAlgoliaContextualFacetFilters(); const configFacetFilters: FacetFilters = props.searchParameters?.facetFilters ?? []; @@ -188,20 +198,22 @@ function useSearchParameters({ }; } -function DocSearch({externalUrlRegex, ...props}: DocSearchProps) { +function DocSearch({externalUrlRegex, ...props}: DocSearchV4Props) { const navigator = useNavigator({externalUrlRegex}); const searchParameters = useSearchParameters({...props}); const transformItems = useTransformItems(props); const transformSearchClient = useTransformSearchClient(); const searchContainer = useRef(null); - // TODO remove "as any" after React 19 upgrade - const searchButtonRef = useRef(null as any); + const searchButtonRef = useRef(null); const [isOpen, setIsOpen] = useState(false); const [initialQuery, setInitialQuery] = useState( undefined, ); + const {isAskAiActive, currentPlaceholder, onAskAiToggle, extraAskAiProps} = + useAlgoliaAskAi(props); + const prepareSearchContainer = useCallback(() => { if (!searchContainer.current) { const divElement = document.createElement('div'); @@ -219,7 +231,8 @@ function DocSearch({externalUrlRegex, ...props}: DocSearchProps) { setIsOpen(false); searchButtonRef.current?.focus(); setInitialQuery(undefined); - }, []); + onAskAiToggle(false); + }, [onAskAiToggle]); const handleInput = useCallback( (event: KeyboardEvent) => { @@ -243,7 +256,13 @@ function DocSearch({externalUrlRegex, ...props}: DocSearchProps) { onClose: closeModal, onInput: handleInput, searchButtonRef, - }); + isAskAiActive: isAskAiActive ?? false, + onAskAiToggle: onAskAiToggle ?? (() => {}), + } satisfies UseDocSearchKeyboardEventsProps & { + // TODO Docusaurus v4: cleanup after we drop support for DocSearch v3 + isAskAiActive: boolean; + onAskAiToggle: (askAiToggle: boolean) => void; + } as UseDocSearchKeyboardEventsProps); return ( <> @@ -269,8 +288,6 @@ function DocSearch({externalUrlRegex, ...props}: DocSearchProps) { {isOpen && DocSearchModal && - // TODO need to fix this React Compiler lint error - // eslint-disable-next-line react-compiler/react-compiler searchContainer.current && createPortal( , - // TODO need to fix this React Compiler lint error - // eslint-disable-next-line react-compiler/react-compiler searchContainer.current, )} @@ -299,5 +315,7 @@ function DocSearch({externalUrlRegex, ...props}: DocSearchProps) { export default function SearchBar(): ReactNode { const {siteConfig} = useDocusaurusContext(); - return ; + return ( + + ); } diff --git a/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/styles.css b/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/styles.css index c80dd71d37..78689effe4 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/styles.css +++ b/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/styles.css @@ -19,3 +19,7 @@ .DocSearch-Container { z-index: calc(var(--ifm-z-index-fixed) + 1); } + +.DocSearch-Button-Key { + padding: 0; +} diff --git a/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.tsx b/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.tsx index 0dd822f6e8..fb275f506b 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.tsx +++ b/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.tsx @@ -139,6 +139,65 @@ function SearchVersionSelectList({ ); } +function AlgoliaLogo(): ReactNode { + return ( + + + {/* eslint-disable-next-line @docusaurus/no-untranslated-text */} + + + + + + + + + + + + + ); +} + type ResultDispatcherState = { items: { title: string; @@ -435,36 +494,23 @@ function SearchPageContent(): ReactNode { documentsFoundPlural(searchResultState.totalResults)} -
    +
    + + {translate({ + id: 'theme.SearchPage.algoliaLabel', + message: 'Powered by', + description: + 'The text explain that the search powered by Algolia', + })} + - - - - - - - +
    diff --git a/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/styles.module.css b/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/styles.module.css index d00563767f..29c4389f55 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/styles.module.css +++ b/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/styles.module.css @@ -33,12 +33,20 @@ font-weight: bold; } -.algoliaLogo { - max-width: 150px; +.searchLogoColumn { + display: flex; + align-items: center; + gap: 0.5rem; + justify-content: flex-end; } -.algoliaLogoPathFill { - fill: var(--ifm-font-color-base); +.searchLogoColumn a { + display: flex; +} + +.searchLogoColumn span { + color: var(--docsearch-muted-color); + font-weight: normal; } .searchResultItem { diff --git a/packages/docusaurus-theme-search-algolia/src/theme/SearchTranslations/index.ts b/packages/docusaurus-theme-search-algolia/src/theme/SearchTranslations/index.ts index 40d0f44ec0..d0bf1b2b8c 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme/SearchTranslations/index.ts +++ b/packages/docusaurus-theme-search-algolia/src/theme/SearchTranslations/index.ts @@ -9,7 +9,62 @@ import {translate} from '@docusaurus/Translate'; import type {DocSearchTranslations} from '@docsearch/react'; -const translations: DocSearchTranslations & {placeholder: string} = { +// TODO Docusaurus v4: require DocSearch v4 +// This needs to be cleaned after the upgrade +// Docusaurus v3 was made compatible with both DocSearch v3 and v4 +// This implies that labels have been kept retro-compatible with v3 +// Once we upgrade, we should be able to rely on v4 types only +// and remove v3 retro-compatibility labels that do not exist anymore in v4 +const translations: DocSearchTranslations & { + placeholder: string; + modal: { + searchBox: { + placeholderText: string; + placeholderTextAskAi: string; + placeholderTextAskAiStreaming: string; + enterKeyHintAskAi: string; + searchInputLabel: string; + backToKeywordSearchButtonText: string; + backToKeywordSearchButtonAriaLabel: string; + enterKeyHint: string; + clearButtonTitle: string; + clearButtonAriaLabel: string; + closeButtonText: string; + resetButtonTitle: string; + resetButtonAriaLabel: string; + cancelButtonText: string; + cancelButtonAriaLabel: string; + closeButtonAriaLabel: string; + }; + startScreen: { + recentConversationsTitle: string; + removeRecentConversationButtonTitle: string; + }; + resultsScreen: { + askAiPlaceholder: string; + }; + askAiScreen: { + disclaimerText: string; + relatedSourcesText: string; + thinkingText: string; + copyButtonText: string; + copyButtonCopiedText: string; + copyButtonTitle: string; + likeButtonTitle: string; + dislikeButtonTitle: string; + thanksForFeedbackText: string; + preToolCallText: string; + duringToolCallText: string; + afterToolCallText: string; + }; + footer: { + submitQuestionText: string; + poweredByText: string; + backToSearchText: string; + searchByText: string; + }; + }; +} = { button: { buttonText: translate({ id: 'theme.SearchBar.label', @@ -44,6 +99,69 @@ const translations: DocSearchTranslations & {placeholder: string} = { message: 'Cancel', description: 'The label and ARIA label for search box cancel button', }), + + // v4 + clearButtonTitle: translate({ + id: 'theme.SearchModal.searchBox.resetButtonTitle', + message: 'Clear the query', + description: 'The label and ARIA label for search box reset button', + }), + clearButtonAriaLabel: translate({ + id: 'theme.SearchModal.searchBox.resetButtonTitle', + message: 'Clear the query', + description: 'The label and ARIA label for search box reset button', + }), + closeButtonText: translate({ + id: 'theme.SearchModal.searchBox.cancelButtonText', + message: 'Cancel', + description: 'The label and ARIA label for search box cancel button', + }), + closeButtonAriaLabel: translate({ + id: 'theme.SearchModal.searchBox.cancelButtonText', + message: 'Cancel', + description: 'The label and ARIA label for search box cancel button', + }), + placeholderText: translate({ + id: 'theme.SearchModal.searchBox.placeholderText', + message: 'Search docs', + description: 'The placeholder text for the main search input field', + }), + placeholderTextAskAi: translate({ + id: 'theme.SearchModal.searchBox.placeholderTextAskAi', + message: 'Ask another question...', + description: 'The placeholder text when in AI question mode', + }), + placeholderTextAskAiStreaming: translate({ + id: 'theme.SearchModal.searchBox.placeholderTextAskAiStreaming', + message: 'Answering...', + description: + 'The placeholder text for search box when AI is streaming an answer', + }), + enterKeyHint: translate({ + id: 'theme.SearchModal.searchBox.enterKeyHint', + message: 'search', + description: 'The hint for the search box enter key text', + }), + enterKeyHintAskAi: translate({ + id: 'theme.SearchModal.searchBox.enterKeyHintAskAi', + message: 'enter', + description: 'The hint for the Ask AI search box enter key text', + }), + searchInputLabel: translate({ + id: 'theme.SearchModal.searchBox.searchInputLabel', + message: 'Search', + description: 'The ARIA label for search input', + }), + backToKeywordSearchButtonText: translate({ + id: 'theme.SearchModal.searchBox.backToKeywordSearchButtonText', + message: 'Back to keyword search', + description: 'The text for back to keyword search button', + }), + backToKeywordSearchButtonAriaLabel: translate({ + id: 'theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel', + message: 'Back to keyword search', + description: 'The ARIA label for back to keyword search button', + }), }, startScreen: { recentSearchesTitle: translate({ @@ -54,17 +172,17 @@ const translations: DocSearchTranslations & {placeholder: string} = { noRecentSearchesText: translate({ id: 'theme.SearchModal.startScreen.noRecentSearchesText', message: 'No recent searches', - description: 'The text when no recent searches', + description: 'The text when there are no recent searches', }), saveRecentSearchButtonTitle: translate({ id: 'theme.SearchModal.startScreen.saveRecentSearchButtonTitle', message: 'Save this search', - description: 'The label for save recent search button', + description: 'The title for save recent search button', }), removeRecentSearchButtonTitle: translate({ id: 'theme.SearchModal.startScreen.removeRecentSearchButtonTitle', message: 'Remove this search from history', - description: 'The label for remove recent search button', + description: 'The title for remove recent search button', }), favoriteSearchesTitle: translate({ id: 'theme.SearchModal.startScreen.favoriteSearchesTitle', @@ -74,91 +192,178 @@ const translations: DocSearchTranslations & {placeholder: string} = { removeFavoriteSearchButtonTitle: translate({ id: 'theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle', message: 'Remove this search from favorites', - description: 'The label for remove favorite search button', + description: 'The title for remove favorite search button', + }), + recentConversationsTitle: translate({ + id: 'theme.SearchModal.startScreen.recentConversationsTitle', + message: 'Recent conversations', + description: 'The title for recent conversations', + }), + removeRecentConversationButtonTitle: translate({ + id: 'theme.SearchModal.startScreen.removeRecentConversationButtonTitle', + message: 'Remove this conversation from history', + description: 'The title for remove recent conversation button', }), }, errorScreen: { titleText: translate({ id: 'theme.SearchModal.errorScreen.titleText', message: 'Unable to fetch results', - description: 'The title for error screen of search modal', + description: 'The title for error screen', }), helpText: translate({ id: 'theme.SearchModal.errorScreen.helpText', message: 'You might want to check your network connection.', - description: 'The help text for error screen of search modal', + description: 'The help text for error screen', + }), + }, + resultsScreen: { + askAiPlaceholder: translate({ + id: 'theme.SearchModal.resultsScreen.askAiPlaceholder', + message: 'Ask AI: ', + description: 'The placeholder text for Ask AI input', + }), + }, + askAiScreen: { + disclaimerText: translate({ + id: 'theme.SearchModal.askAiScreen.disclaimerText', + message: + 'Answers are generated with AI which can make mistakes. Verify responses.', + description: 'The disclaimer text for AI answers', + }), + relatedSourcesText: translate({ + id: 'theme.SearchModal.askAiScreen.relatedSourcesText', + message: 'Related sources', + description: 'The text for related sources', + }), + thinkingText: translate({ + id: 'theme.SearchModal.askAiScreen.thinkingText', + message: 'Thinking...', + description: 'The text when AI is thinking', + }), + copyButtonText: translate({ + id: 'theme.SearchModal.askAiScreen.copyButtonText', + message: 'Copy', + description: 'The text for copy button', + }), + copyButtonCopiedText: translate({ + id: 'theme.SearchModal.askAiScreen.copyButtonCopiedText', + message: 'Copied!', + description: 'The text for copy button when copied', + }), + copyButtonTitle: translate({ + id: 'theme.SearchModal.askAiScreen.copyButtonTitle', + message: 'Copy', + description: 'The title for copy button', + }), + likeButtonTitle: translate({ + id: 'theme.SearchModal.askAiScreen.likeButtonTitle', + message: 'Like', + description: 'The title for like button', + }), + dislikeButtonTitle: translate({ + id: 'theme.SearchModal.askAiScreen.dislikeButtonTitle', + message: 'Dislike', + description: 'The title for dislike button', + }), + thanksForFeedbackText: translate({ + id: 'theme.SearchModal.askAiScreen.thanksForFeedbackText', + message: 'Thanks for your feedback!', + description: 'The text for thanks for feedback', + }), + preToolCallText: translate({ + id: 'theme.SearchModal.askAiScreen.preToolCallText', + message: 'Searching...', + description: 'The text before tool call', + }), + duringToolCallText: translate({ + id: 'theme.SearchModal.askAiScreen.duringToolCallText', + message: 'Searching for ', + description: 'The text during tool call', + }), + afterToolCallText: translate({ + id: 'theme.SearchModal.askAiScreen.afterToolCallText', + message: 'Searched for', + description: 'The text after tool call', }), }, footer: { selectText: translate({ id: 'theme.SearchModal.footer.selectText', - message: 'to select', - description: 'The explanatory text of the action for the enter key', + message: 'Select', + description: 'The select text for footer', + }), + submitQuestionText: translate({ + id: 'theme.SearchModal.footer.submitQuestionText', + message: 'Submit question', + description: 'The submit question text for footer', }), selectKeyAriaLabel: translate({ id: 'theme.SearchModal.footer.selectKeyAriaLabel', message: 'Enter key', - description: - 'The ARIA label for the Enter key button that makes the selection', + description: 'The ARIA label for select key in footer', }), navigateText: translate({ id: 'theme.SearchModal.footer.navigateText', - message: 'to navigate', - description: - 'The explanatory text of the action for the Arrow up and Arrow down key', + message: 'Navigate', + description: 'The navigate text for footer', }), navigateUpKeyAriaLabel: translate({ id: 'theme.SearchModal.footer.navigateUpKeyAriaLabel', message: 'Arrow up', - description: - 'The ARIA label for the Arrow up key button that makes the navigation', + description: 'The ARIA label for navigate up key in footer', }), navigateDownKeyAriaLabel: translate({ id: 'theme.SearchModal.footer.navigateDownKeyAriaLabel', message: 'Arrow down', - description: - 'The ARIA label for the Arrow down key button that makes the navigation', + description: 'The ARIA label for navigate down key in footer', }), closeText: translate({ id: 'theme.SearchModal.footer.closeText', - message: 'to close', - description: 'The explanatory text of the action for Escape key', + message: 'Close', + description: 'The close text for footer', }), closeKeyAriaLabel: translate({ id: 'theme.SearchModal.footer.closeKeyAriaLabel', message: 'Escape key', - description: - 'The ARIA label for the Escape key button that close the modal', + description: 'The ARIA label for close key in footer', + }), + poweredByText: translate({ + id: 'theme.SearchModal.footer.searchByText', + message: 'Powered by', + description: "The 'Powered by' text for footer", }), searchByText: translate({ id: 'theme.SearchModal.footer.searchByText', - message: 'Search by', - description: 'The text explain that the search is making by Algolia', + message: 'Powered by', + description: "The 'Powered by' text for footer", + }), + backToSearchText: translate({ + id: 'theme.SearchModal.footer.backToSearchText', + message: 'Back to search', + description: 'The back to search text for footer', }), }, noResultsScreen: { noResultsText: translate({ id: 'theme.SearchModal.noResultsScreen.noResultsText', - message: 'No results for', - description: - 'The text explains that there are no results for the following search', + message: 'No results found for', + description: 'The text when there are no results', }), suggestedQueryText: translate({ id: 'theme.SearchModal.noResultsScreen.suggestedQueryText', message: 'Try searching for', - description: - 'The text for the suggested query when no results are found for the following search', + description: 'The text for suggested query', }), reportMissingResultsText: translate({ id: 'theme.SearchModal.noResultsScreen.reportMissingResultsText', message: 'Believe this query should return results?', - description: - 'The text for the question where the user thinks there are missing results', + description: 'The text for reporting missing results', }), reportMissingResultsLinkText: translate({ id: 'theme.SearchModal.noResultsScreen.reportMissingResultsLinkText', message: 'Let us know.', - description: 'The text for the link to report missing results', + description: 'The link text for reporting missing results', }), }, }, diff --git a/packages/docusaurus-theme-search-algolia/src/validateThemeConfig.ts b/packages/docusaurus-theme-search-algolia/src/validateThemeConfig.ts index 2e1061d864..01a3bec255 100644 --- a/packages/docusaurus-theme-search-algolia/src/validateThemeConfig.ts +++ b/packages/docusaurus-theme-search-algolia/src/validateThemeConfig.ts @@ -7,22 +7,27 @@ import {escapeRegexp} from '@docusaurus/utils'; import {Joi} from '@docusaurus/utils-validation'; +import {version as docsearchVersion} from '@docsearch/react'; +import type {ThemeConfigValidationContext} from '@docusaurus/types'; import type { ThemeConfig, - ThemeConfigValidationContext, -} from '@docusaurus/types'; + ThemeConfigAlgolia, +} from '@docusaurus/theme-search-algolia'; export const DEFAULT_CONFIG = { // Enabled by default, as it makes sense in most cases // see also https://github.com/facebook/docusaurus/issues/5880 contextualSearch: true, - searchParameters: {}, searchPagePath: 'search', -}; +} satisfies Partial; + +const FacetFiltersSchema = Joi.array().items( + Joi.alternatives().try(Joi.string(), Joi.array().items(Joi.string())), +); export const Schema = Joi.object({ - algolia: Joi.object({ + algolia: Joi.object({ // Docusaurus attributes contextualSearch: Joi.boolean().default(DEFAULT_CONFIG.contextualSearch), externalUrlRegex: Joi.string().optional(), @@ -33,7 +38,9 @@ export const Schema = Joi.object({ }), apiKey: Joi.string().required(), indexName: Joi.string().required(), - searchParameters: Joi.object() + searchParameters: Joi.object({ + facetFilters: FacetFiltersSchema.optional(), + }) .default(DEFAULT_CONFIG.searchParameters) .unknown(), searchPagePath: Joi.alternatives() @@ -53,15 +60,85 @@ export const Schema = Joi.object({ }).required(), to: Joi.string().required(), }).optional(), + // Ask AI configuration (DocSearch v4 only) + askAi: Joi.alternatives() + .try( + // Simple string format (assistantId only) + Joi.string(), + // Full configuration object + Joi.object({ + indexName: Joi.string().required(), + apiKey: Joi.string().required(), + appId: Joi.string().required(), + assistantId: Joi.string().required(), + searchParameters: Joi.object({ + facetFilters: FacetFiltersSchema.optional(), + }).optional(), + }), + ) + .custom( + ( + askAiInput: string | ThemeConfigAlgolia['askAi'] | undefined, + helpers, + ) => { + if (!askAiInput) { + return askAiInput; + } + const algolia: ThemeConfigAlgolia = helpers.state.ancestors[0]; + const algoliaFacetFilters = algolia.searchParameters?.facetFilters; + if (typeof askAiInput === 'string') { + return { + assistantId: askAiInput, + indexName: algolia.indexName, + apiKey: algolia.apiKey, + appId: algolia.appId, + ...(algoliaFacetFilters + ? { + searchParameters: { + facetFilters: algoliaFacetFilters, + }, + } + : {}), + } satisfies ThemeConfigAlgolia['askAi']; + } + + if ( + askAiInput.searchParameters?.facetFilters === undefined && + algoliaFacetFilters + ) { + askAiInput.searchParameters = askAiInput.searchParameters ?? {}; + askAiInput.searchParameters.facetFilters = algoliaFacetFilters; + } + return askAiInput; + }, + ) + .optional() + .messages({ + 'alternatives.types': + 'askAi must be either a string (assistantId) or an object with indexName, apiKey, appId, and assistantId', + }), }) .label('themeConfig.algolia') .required() - .unknown(), // DocSearch 3 is still alpha: don't validate the rest for now + .unknown(), }); +function ensureAskAISupported(themeConfig: ThemeConfig) { + // enforce DocsSearch v4 requirement when AskAI is configured + if (themeConfig.algolia.askAi && !docsearchVersion.startsWith('4.')) { + throw new Error( + 'The askAi feature is only supported in DocSearch v4. ' + + 'Please upgrade to DocSearch v4 by installing "@docsearch/react": "^4.0.0" ' + + 'or remove the askAi configuration from your theme config.', + ); + } +} + export function validateThemeConfig({ validate, - themeConfig, + themeConfig: themeConfigInput, }: ThemeConfigValidationContext): ThemeConfig { - return validate(Schema, themeConfig); + const themeConfig = validate(Schema, themeConfigInput); + ensureAskAISupported(themeConfig); + return themeConfig; } diff --git a/packages/docusaurus-theme-translations/locales/ar/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/ar/theme-search-algolia.json index 69ce6e9ce6..43bd6253cd 100644 --- a/packages/docusaurus-theme-translations/locales/ar/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/ar/theme-search-algolia.json @@ -1,30 +1,55 @@ { "theme.SearchBar.label": "بحث", "theme.SearchBar.seeAll": "مشاهدة جميع {count} نتائج", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "You might want to check your network connection.", "theme.SearchModal.errorScreen.titleText": "Unable to fetch results", + "theme.SearchModal.footer.backToSearchText": "Back to search", "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.searchByText": "Powered by", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter key", "theme.SearchModal.footer.selectText": "to select", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "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.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Cancel", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Clear the query", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorite", "theme.SearchModal.startScreen.noRecentSearchesText": "No recent searches", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Recent", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Save this search", - "theme.SearchPage.algoliaLabel": "البحث بواسطه Algolia", + "theme.SearchPage.algoliaLabel": "مدعوم من Algolia", "theme.SearchPage.documentsFound.plurals": "تم العثور على مستند واحد|تم العثور على {count} مستندات", "theme.SearchPage.emptyResultsTitle": "ابحث في الوثائق", "theme.SearchPage.existingResultsTitle": "نتائج البحث عن \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/base/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/base/theme-search-algolia.json index dc394f4d88..afa916b463 100644 --- a/packages/docusaurus-theme-translations/locales/base/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/base/theme-search-algolia.json @@ -2,54 +2,104 @@ "theme.SearchBar.label": "Search", "theme.SearchBar.label___DESCRIPTION": "The ARIA label and placeholder for search button", "theme.SearchBar.seeAll": "See all {count} results", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.afterToolCallText___DESCRIPTION": "The text after tool call", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonCopiedText___DESCRIPTION": "The text for copy button when copied", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonText___DESCRIPTION": "The text for copy button", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle___DESCRIPTION": "The title for copy button", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.disclaimerText___DESCRIPTION": "The disclaimer text for AI answers", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.dislikeButtonTitle___DESCRIPTION": "The title for dislike button", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.duringToolCallText___DESCRIPTION": "The text during tool call", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.likeButtonTitle___DESCRIPTION": "The title for like button", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.preToolCallText___DESCRIPTION": "The text before tool call", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.relatedSourcesText___DESCRIPTION": "The text for related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thanksForFeedbackText___DESCRIPTION": "The text for thanks for feedback", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", + "theme.SearchModal.askAiScreen.thinkingText___DESCRIPTION": "The text when AI is thinking", "theme.SearchModal.errorScreen.helpText": "You might want to check your network connection.", - "theme.SearchModal.errorScreen.helpText___DESCRIPTION": "The help text for error screen of search modal", + "theme.SearchModal.errorScreen.helpText___DESCRIPTION": "The help text for error screen", "theme.SearchModal.errorScreen.titleText": "Unable to fetch results", - "theme.SearchModal.errorScreen.titleText___DESCRIPTION": "The title for error screen of search modal", + "theme.SearchModal.errorScreen.titleText___DESCRIPTION": "The title for error screen", + "theme.SearchModal.footer.backToSearchText": "Back to search", + "theme.SearchModal.footer.backToSearchText___DESCRIPTION": "The back to search text for footer", "theme.SearchModal.footer.closeKeyAriaLabel": "Escape key", - "theme.SearchModal.footer.closeKeyAriaLabel___DESCRIPTION": "The ARIA label for the Escape key button that close the modal", - "theme.SearchModal.footer.closeText": "to close", - "theme.SearchModal.footer.closeText___DESCRIPTION": "The explanatory text of the action for Escape key", + "theme.SearchModal.footer.closeKeyAriaLabel___DESCRIPTION": "The ARIA label for close key in footer", + "theme.SearchModal.footer.closeText": "Close", + "theme.SearchModal.footer.closeText___DESCRIPTION": "The close text for footer", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Arrow down", - "theme.SearchModal.footer.navigateDownKeyAriaLabel___DESCRIPTION": "The ARIA label for the Arrow down key button that makes the navigation", - "theme.SearchModal.footer.navigateText": "to navigate", - "theme.SearchModal.footer.navigateText___DESCRIPTION": "The explanatory text of the action for the Arrow up and Arrow down key", + "theme.SearchModal.footer.navigateDownKeyAriaLabel___DESCRIPTION": "The ARIA label for navigate down key in footer", + "theme.SearchModal.footer.navigateText": "Navigate", + "theme.SearchModal.footer.navigateText___DESCRIPTION": "The navigate text for footer", "theme.SearchModal.footer.navigateUpKeyAriaLabel": "Arrow up", - "theme.SearchModal.footer.navigateUpKeyAriaLabel___DESCRIPTION": "The ARIA label for the Arrow up key button that makes the navigation", - "theme.SearchModal.footer.searchByText": "Search by", - "theme.SearchModal.footer.searchByText___DESCRIPTION": "The text explain that the search is making by Algolia", + "theme.SearchModal.footer.navigateUpKeyAriaLabel___DESCRIPTION": "The ARIA label for navigate up key in footer", + "theme.SearchModal.footer.searchByText": "Powered by", + "theme.SearchModal.footer.searchByText___DESCRIPTION": "The 'Powered by' text for footer", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter key", - "theme.SearchModal.footer.selectKeyAriaLabel___DESCRIPTION": "The ARIA label for the Enter key button that makes the selection", - "theme.SearchModal.footer.selectText": "to select", - "theme.SearchModal.footer.selectText___DESCRIPTION": "The explanatory text of the action for the enter key", - "theme.SearchModal.noResultsScreen.noResultsText": "No results for", - "theme.SearchModal.noResultsScreen.noResultsText___DESCRIPTION": "The text explains that there are no results for the following search", + "theme.SearchModal.footer.selectKeyAriaLabel___DESCRIPTION": "The ARIA label for select key in footer", + "theme.SearchModal.footer.selectText": "Select", + "theme.SearchModal.footer.selectText___DESCRIPTION": "The select text for footer", + "theme.SearchModal.footer.submitQuestionText": "Submit question", + "theme.SearchModal.footer.submitQuestionText___DESCRIPTION": "The submit question text for footer", + "theme.SearchModal.noResultsScreen.noResultsText": "No results found for", + "theme.SearchModal.noResultsScreen.noResultsText___DESCRIPTION": "The text when there are no results", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Let us know.", - "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText___DESCRIPTION": "The text for the link to report missing results", + "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText___DESCRIPTION": "The link text for reporting missing results", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Believe this query should return results?", - "theme.SearchModal.noResultsScreen.reportMissingResultsText___DESCRIPTION": "The text for the question where the user thinks there are missing results", + "theme.SearchModal.noResultsScreen.reportMissingResultsText___DESCRIPTION": "The text for reporting missing results", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Try searching for", - "theme.SearchModal.noResultsScreen.suggestedQueryText___DESCRIPTION": "The text for the suggested query when no results are found for the following search", + "theme.SearchModal.noResultsScreen.suggestedQueryText___DESCRIPTION": "The text for suggested query", "theme.SearchModal.placeholder": "Search docs", "theme.SearchModal.placeholder___DESCRIPTION": "The placeholder of the input of the DocSearch pop-up modal", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.resultsScreen.askAiPlaceholder___DESCRIPTION": "The placeholder text for Ask AI input", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel___DESCRIPTION": "The ARIA label for back to keyword search button", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText___DESCRIPTION": "The text for back to keyword search button", "theme.SearchModal.searchBox.cancelButtonText": "Cancel", "theme.SearchModal.searchBox.cancelButtonText___DESCRIPTION": "The label and ARIA label for search box cancel button", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHint___DESCRIPTION": "The hint for the search box enter key text", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.enterKeyHintAskAi___DESCRIPTION": "The hint for the Ask AI search box enter key text", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderText___DESCRIPTION": "The placeholder text for the main search input field", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAi___DESCRIPTION": "The placeholder text when in AI question mode", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming___DESCRIPTION": "The placeholder text for search box when AI is streaming an answer", "theme.SearchModal.searchBox.resetButtonTitle": "Clear the query", "theme.SearchModal.searchBox.resetButtonTitle___DESCRIPTION": "The label and ARIA label for search box reset button", + "theme.SearchModal.searchBox.searchInputLabel": "Search", + "theme.SearchModal.searchBox.searchInputLabel___DESCRIPTION": "The ARIA label for search input", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorite", "theme.SearchModal.startScreen.favoriteSearchesTitle___DESCRIPTION": "The title for favorite searches", "theme.SearchModal.startScreen.noRecentSearchesText": "No recent searches", - "theme.SearchModal.startScreen.noRecentSearchesText___DESCRIPTION": "The text when no recent searches", + "theme.SearchModal.startScreen.noRecentSearchesText___DESCRIPTION": "The text when there are no recent searches", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", + "theme.SearchModal.startScreen.recentConversationsTitle___DESCRIPTION": "The title for recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Recent", "theme.SearchModal.startScreen.recentSearchesTitle___DESCRIPTION": "The title for recent searches", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", - "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle___DESCRIPTION": "The label for remove favorite search button", + "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle___DESCRIPTION": "The title for remove favorite search button", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle___DESCRIPTION": "The title for remove recent conversation button", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", - "theme.SearchModal.startScreen.removeRecentSearchButtonTitle___DESCRIPTION": "The label for remove recent search button", + "theme.SearchModal.startScreen.removeRecentSearchButtonTitle___DESCRIPTION": "The title for remove recent search button", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Save this search", - "theme.SearchModal.startScreen.saveRecentSearchButtonTitle___DESCRIPTION": "The label for save recent search button", - "theme.SearchPage.algoliaLabel": "Search by Algolia", - "theme.SearchPage.algoliaLabel___DESCRIPTION": "The ARIA label for Algolia mention", + "theme.SearchModal.startScreen.saveRecentSearchButtonTitle___DESCRIPTION": "The title for save recent search button", + "theme.SearchPage.algoliaLabel": "Powered by Algolia", + "theme.SearchPage.algoliaLabel___DESCRIPTION": "The description label for Algolia mention", "theme.SearchPage.documentsFound.plurals": "One document found|{count} documents found", "theme.SearchPage.documentsFound.plurals___DESCRIPTION": "Pluralized label for \"{count} documents found\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)", "theme.SearchPage.emptyResultsTitle": "Search the documentation", diff --git a/packages/docusaurus-theme-translations/locales/bg/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/bg/theme-search-algolia.json index 100008c134..7442a4697c 100644 --- a/packages/docusaurus-theme-translations/locales/bg/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/bg/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Търсене", "theme.SearchBar.seeAll": "Вижте всички {count} резултата", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Може да проверите вашата мрежова връзка.", "theme.SearchModal.errorScreen.titleText": "Не може да се извлекат резултати", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Клавиш Escape", "theme.SearchModal.footer.closeText": "за затваряне", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Стрелка надолу", @@ -11,25 +24,37 @@ "theme.SearchModal.footer.searchByText": "Търсене от", "theme.SearchModal.footer.selectKeyAriaLabel": "Клавиш Enter ", "theme.SearchModal.footer.selectText": "за избиране", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Няма резултати за", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Информирай ни.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Вярвате, че тази заявка трябва да върне резултати?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Опитайте да потърсите", "theme.SearchModal.placeholder": "Търсене в документацията", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Отказ", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Изчистване на заявката", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Любими", "theme.SearchModal.startScreen.noRecentSearchesText": "Няма скорошни търсения", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Скорошни", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Премахване на това търсене от любимите", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Премахване това търсене от историята", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Запазване това търсене", - "theme.SearchPage.algoliaLabel": "Търсене от Algolia", + "theme.SearchPage.algoliaLabel": "Задвижвано от Algolia", "theme.SearchPage.documentsFound.plurals": "Намерен е един документ|{count} намерени документи", "theme.SearchPage.emptyResultsTitle": "Потърсете в документацията", "theme.SearchPage.existingResultsTitle": "Резултати от търсенето за \"{query}\"", "theme.SearchPage.fetchingNewResults": "звличане на нови резултати...", "theme.SearchPage.inputLabel": "Търсене", - "theme.SearchPage.inputPlaceholder": "Въведете вашето търсене тук", - "theme.SearchPage.noResultsText": "Не бяха намерени резултати" + "theme.SearchPage.inputPlaceholder": "Въведете търсенето си тук", + "theme.SearchPage.noResultsText": "Няма намерени резултати" } diff --git a/packages/docusaurus-theme-translations/locales/bn/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/bn/theme-search-algolia.json index b6d157a5a5..0987b48e9d 100644 --- a/packages/docusaurus-theme-translations/locales/bn/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/bn/theme-search-algolia.json @@ -1,35 +1,60 @@ { - "theme.SearchBar.label": "সার্চ", - "theme.SearchBar.seeAll": "See all {count} results", - "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.SearchPage.algoliaLabel": "আলগোলিয়া দ্বারা অনুসন্ধান করুন", - "theme.SearchPage.documentsFound.plurals": "একটি ডকুমেন্ট পাওয়া গেছে|{count} ডকুমেন্টস পাওয়া গেছে", - "theme.SearchPage.emptyResultsTitle": "ডকুমেন্টেশন অনুসন্ধান করুন", + "theme.SearchBar.label": "অনুসন্ধান", + "theme.SearchBar.seeAll": "সমস্ত {count}টি ফলাফল দেখুন", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", + "theme.SearchModal.errorScreen.helpText": "আপনি আপনার নেটওয়ার্ক সংযোগ পরীক্ষা করতে চাইতে পারেন।", + "theme.SearchModal.errorScreen.titleText": "ফলাফল আনতে অক্ষম", + "theme.SearchModal.footer.backToSearchText": "Back to search", + "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.footer.submitQuestionText": "Submit question", + "theme.SearchModal.noResultsScreen.noResultsText": "কোনো ফলাফল পাওয়া যায়নি", + "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "আমাদের জানান।", + "theme.SearchModal.noResultsScreen.reportMissingResultsText": "বিশ্বাস করেন এই অনুসন্ধানে ফলাফল থাকা উচিত?", + "theme.SearchModal.noResultsScreen.suggestedQueryText": "অনুসন্ধান করার চেষ্টা করুন", + "theme.SearchModal.placeholder": "ডক্স অনুসন্ধান করুন", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", + "theme.SearchModal.searchBox.cancelButtonText": "বাতিল", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", + "theme.SearchModal.searchBox.resetButtonTitle": "অনুসন্ধান সাফ করুন", + "theme.SearchModal.searchBox.searchInputLabel": "Search", + "theme.SearchModal.startScreen.favoriteSearchesTitle": "প্রিয়", + "theme.SearchModal.startScreen.noRecentSearchesText": "কোনো সাম্প্রতিক অনুসন্ধান নেই", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", + "theme.SearchModal.startScreen.recentSearchesTitle": "সাম্প্রতিক", + "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "প্রিয় থেকে এই অনুসন্ধান সরান", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", + "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "ইতিহাস থেকে এই অনুসন্ধান সরান", + "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "এই অনুসন্ধান সংরক্ষণ করুন", + "theme.SearchPage.algoliaLabel": "Algolia দ্বারা অনুসন্ধান", + "theme.SearchPage.documentsFound.plurals": "{count}টি ডকুমেন্ট পাওয়া গেছে", + "theme.SearchPage.emptyResultsTitle": "ডকুমেন্টেশনে অনুসন্ধান করুন", "theme.SearchPage.existingResultsTitle": "\"{query}\" এর জন্য অনুসন্ধান ফলাফল", "theme.SearchPage.fetchingNewResults": "নতুন ফলাফল আনা হচ্ছে...", - "theme.SearchPage.inputLabel": "সার্চ", - "theme.SearchPage.inputPlaceholder": "আপনার অনুসন্ধান এখানে টাইপ করুন", - "theme.SearchPage.noResultsText": "কোন ফলাফল পাওয়া যায়নি" + "theme.SearchPage.inputLabel": "অনুসন্ধান", + "theme.SearchPage.inputPlaceholder": "এখানে আপনার অনুসন্ধান লিখুন", + "theme.SearchPage.noResultsText": "কোনো ফলাফল পাওয়া যায়নি" } diff --git a/packages/docusaurus-theme-translations/locales/cs/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/cs/theme-search-algolia.json index 8c8d092d01..ebcd44bf65 100644 --- a/packages/docusaurus-theme-translations/locales/cs/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/cs/theme-search-algolia.json @@ -1,35 +1,60 @@ { - "theme.SearchBar.label": "Hledat", - "theme.SearchBar.seeAll": "See all {count} results", - "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.SearchPage.algoliaLabel": "Vyhledávání od Algolia", - "theme.SearchPage.documentsFound.plurals": "Jeden dokument nalezen|{count} dokumenty nalezeny|{count} dokumentů nalezeno", + "theme.SearchBar.label": "Vyhledávání", + "theme.SearchBar.seeAll": "Zobrazit všech {count} výsledků", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", + "theme.SearchModal.errorScreen.helpText": "Možná byste měli zkontrolovat připojení k síti.", + "theme.SearchModal.errorScreen.titleText": "Nelze načíst výsledky", + "theme.SearchModal.footer.backToSearchText": "Back to search", + "theme.SearchModal.footer.closeKeyAriaLabel": "Klávesa Escape", + "theme.SearchModal.footer.closeText": "zavřít", + "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Šipka dolů", + "theme.SearchModal.footer.navigateText": "navigovat", + "theme.SearchModal.footer.navigateUpKeyAriaLabel": "Šipka nahoru", + "theme.SearchModal.footer.searchByText": "Vyhledávání pomocí", + "theme.SearchModal.footer.selectKeyAriaLabel": "Klávesa Enter", + "theme.SearchModal.footer.selectText": "vybrat", + "theme.SearchModal.footer.submitQuestionText": "Submit question", + "theme.SearchModal.noResultsScreen.noResultsText": "Žádné výsledky pro", + "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Dejte nám vědět.", + "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Věříte, že tento dotaz by měl vrátit výsledky?", + "theme.SearchModal.noResultsScreen.suggestedQueryText": "Zkuste vyhledat", + "theme.SearchModal.placeholder": "Prohledat dokumentaci", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", + "theme.SearchModal.searchBox.cancelButtonText": "Zrušit", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", + "theme.SearchModal.searchBox.resetButtonTitle": "Vymazat dotaz", + "theme.SearchModal.searchBox.searchInputLabel": "Search", + "theme.SearchModal.startScreen.favoriteSearchesTitle": "Oblíbené", + "theme.SearchModal.startScreen.noRecentSearchesText": "Žádná nedávná vyhledávání", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", + "theme.SearchModal.startScreen.recentSearchesTitle": "Nedávné", + "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Odebrat toto vyhledávání z oblíbených", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", + "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Odebrat toto vyhledávání z historie", + "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Uložit toto vyhledávání", + "theme.SearchPage.algoliaLabel": "Vyhledávání pomocí Algolia", + "theme.SearchPage.documentsFound.plurals": "Nalezen {count} dokument", "theme.SearchPage.emptyResultsTitle": "Prohledat dokumentaci", "theme.SearchPage.existingResultsTitle": "Výsledky vyhledávání pro \"{query}\"", - "theme.SearchPage.fetchingNewResults": "Stahuji nové výsledky...", - "theme.SearchPage.inputLabel": "Hledat", - "theme.SearchPage.inputPlaceholder": "Zde napište hledaný text", - "theme.SearchPage.noResultsText": "Nic nebylo nalezeno" + "theme.SearchPage.fetchingNewResults": "Načítání nových výsledků...", + "theme.SearchPage.inputLabel": "Vyhledávání", + "theme.SearchPage.inputPlaceholder": "Zadejte hledaný text", + "theme.SearchPage.noResultsText": "Žádné výsledky nenalezeny" } diff --git a/packages/docusaurus-theme-translations/locales/da/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/da/theme-search-algolia.json index be4f094384..b04cf00c56 100644 --- a/packages/docusaurus-theme-translations/locales/da/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/da/theme-search-algolia.json @@ -1,30 +1,55 @@ { "theme.SearchBar.label": "Søg", "theme.SearchBar.seeAll": "See all {count} results", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "You might want to check your network connection.", "theme.SearchModal.errorScreen.titleText": "Unable to fetch results", + "theme.SearchModal.footer.backToSearchText": "Back to search", "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.searchByText": "Powered by", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter key", "theme.SearchModal.footer.selectText": "to select", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "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.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Cancel", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Clear the query", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorite", "theme.SearchModal.startScreen.noRecentSearchesText": "No recent searches", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Recent", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Save this search", - "theme.SearchPage.algoliaLabel": "Søg med Algolia", + "theme.SearchPage.algoliaLabel": "Drevet af Algolia", "theme.SearchPage.documentsFound.plurals": "Et dokument fundet|{count} dokumenter fundet", "theme.SearchPage.emptyResultsTitle": "Søg i dokumentationen", "theme.SearchPage.existingResultsTitle": "Søgeresultater for \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/de/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/de/theme-search-algolia.json index 5aa48122ad..b9e69701c5 100644 --- a/packages/docusaurus-theme-translations/locales/de/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/de/theme-search-algolia.json @@ -1,30 +1,55 @@ { "theme.SearchBar.label": "Suche", "theme.SearchBar.seeAll": "Alle {count} Ergebnisse anzeigen", + "theme.SearchModal.askAiScreen.afterToolCallText": "Gesucht nach ", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Kopiert!", + "theme.SearchModal.askAiScreen.copyButtonText": "Kopieren", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Kopieren", + "theme.SearchModal.askAiScreen.disclaimerText": "Antworten werden von KI generiert und können Fehler enthalten. Bitte überprüfen Sie die Antworten.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Gefällt mir nicht", + "theme.SearchModal.askAiScreen.duringToolCallText": "Suche nach ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Gefällt mir", + "theme.SearchModal.askAiScreen.preToolCallText": "Suche...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Verwandte Quellen", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Danke für Ihr Feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Denkt nach...", "theme.SearchModal.errorScreen.helpText": "You might want to check your network connection.", "theme.SearchModal.errorScreen.titleText": "Unable to fetch results", + "theme.SearchModal.footer.backToSearchText": "Zurück zur Suche", "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.searchByText": "Powered by", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter key", "theme.SearchModal.footer.selectText": "to select", + "theme.SearchModal.footer.submitQuestionText": "Frage absenden", "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.resultsScreen.askAiPlaceholder": "KI fragen: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Zurück zur Stichwortsuche", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Zurück zur Stichwortsuche", "theme.SearchModal.searchBox.cancelButtonText": "Cancel", + "theme.SearchModal.searchBox.enterKeyHint": "suchen", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "eingeben", + "theme.SearchModal.searchBox.placeholderText": "Dokumentation durchsuchen", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Weitere Frage stellen...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Antwortet...", "theme.SearchModal.searchBox.resetButtonTitle": "Clear the query", + "theme.SearchModal.searchBox.searchInputLabel": "Suchen", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorite", "theme.SearchModal.startScreen.noRecentSearchesText": "No recent searches", + "theme.SearchModal.startScreen.recentConversationsTitle": "Letzte Gespräche", "theme.SearchModal.startScreen.recentSearchesTitle": "Recent", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Dieses Gespräch aus dem Verlauf entfernen", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Save this search", - "theme.SearchPage.algoliaLabel": "Suche von Algolia", + "theme.SearchPage.algoliaLabel": "Unterstützt von Algolia", "theme.SearchPage.documentsFound.plurals": "Ein Dokument gefunden|{count} Dokumente gefunden", "theme.SearchPage.emptyResultsTitle": "Suche in der Dokumentation", "theme.SearchPage.existingResultsTitle": "Suchergebnisse für \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/es/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/es/theme-search-algolia.json index 987ba4194c..159dd5d749 100644 --- a/packages/docusaurus-theme-translations/locales/es/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/es/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Buscar", "theme.SearchBar.seeAll": "Ver todos los {count} resultados", + "theme.SearchModal.askAiScreen.afterToolCallText": "Se buscó ", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "¡Copiado!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copiar", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copiar", + "theme.SearchModal.askAiScreen.disclaimerText": "Las respuestas son generadas por IA y pueden contener errores. Verifique las respuestas.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "No me gusta", + "theme.SearchModal.askAiScreen.duringToolCallText": "Buscando ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Me gusta", + "theme.SearchModal.askAiScreen.preToolCallText": "Buscando...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Fuentes relacionadas", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "¡Gracias por tu opinión!", + "theme.SearchModal.askAiScreen.thinkingText": "Pensando...", "theme.SearchModal.errorScreen.helpText": "Quizás quieras comprobar tu conexión de red.", "theme.SearchModal.errorScreen.titleText": "No se pueden obtener resultados", + "theme.SearchModal.footer.backToSearchText": "Volver a la búsqueda", "theme.SearchModal.footer.closeKeyAriaLabel": "tecla Escape", "theme.SearchModal.footer.closeText": "cerrar", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Flecha abajo", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Buscar por", "theme.SearchModal.footer.selectKeyAriaLabel": "tecla Enter", "theme.SearchModal.footer.selectText": "seleccionar", + "theme.SearchModal.footer.submitQuestionText": "Enviar pregunta", "theme.SearchModal.noResultsScreen.noResultsText": "Sin resultados para", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Háganos saber.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Crees que esta consulta debería devolver resultados?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Intenta buscando por", "theme.SearchModal.placeholder": "Buscar documentos", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Preguntar a la IA: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Volver a búsqueda por palabras clave", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Volver a búsqueda por palabras clave", "theme.SearchModal.searchBox.cancelButtonText": "Cancelar", + "theme.SearchModal.searchBox.enterKeyHint": "buscar", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enviar", + "theme.SearchModal.searchBox.placeholderText": "Buscar documentos", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Hacer otra pregunta...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Respondiendo...", "theme.SearchModal.searchBox.resetButtonTitle": "Limpiar la búsqueda", + "theme.SearchModal.searchBox.searchInputLabel": "Buscar", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorito", "theme.SearchModal.startScreen.noRecentSearchesText": "Sin búsquedas recientes", + "theme.SearchModal.startScreen.recentConversationsTitle": "Conversaciones recientes", "theme.SearchModal.startScreen.recentSearchesTitle": "Reciente", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Eliminar esta búsqueda de favoritos", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Eliminar esta conversación del historial", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Eliminar esta búsqueda del historial", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Guardar esta búsqueda", - "theme.SearchPage.algoliaLabel": "Búsqueda por Algolia", + "theme.SearchPage.algoliaLabel": "Con tecnología de Algolia", "theme.SearchPage.documentsFound.plurals": "Un documento encontrado|{count} documentos encontrados", "theme.SearchPage.emptyResultsTitle": "Búsqueda en la documentación", "theme.SearchPage.existingResultsTitle": "Resultados de búsqueda para \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/et/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/et/theme-search-algolia.json index 2d63010512..87f07ec7e2 100644 --- a/packages/docusaurus-theme-translations/locales/et/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/et/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Otsi", "theme.SearchBar.seeAll": "Vaata kõiki {count} tulemust", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Kontrolli interneti ühendust.", "theme.SearchModal.errorScreen.titleText": "Tulemuste pärimine ebaõnnestus", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Paoklahvi nuppu", "theme.SearchModal.footer.closeText": "sulgemiseks", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Alla noolt", @@ -11,25 +24,37 @@ "theme.SearchModal.footer.searchByText": "Otsi", "theme.SearchModal.footer.selectKeyAriaLabel": "Sisestusklahvi nuppu", "theme.SearchModal.footer.selectText": "valimiseks", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Tulemused puuduvad päringule", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Anna meile teada.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Usud, et see päring peaks tulemuse andma?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Proovi otsida", "theme.SearchModal.placeholder": "Otsi dokumente", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Tühista", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Puhasta päring", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Lemmik", "theme.SearchModal.startScreen.noRecentSearchesText": "Hiljutised otsingud puuduvad", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Hiljutised", - "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Kustuta see päring lemmikute seast", - "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Kustuta see päring ajaloost", - "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Salvesta see päring", - "theme.SearchPage.algoliaLabel": "Algolia otsing", - "theme.SearchPage.documentsFound.plurals": "Üks dokument leitud|{count} dokumenti leitud", - "theme.SearchPage.emptyResultsTitle": "Otsi dokumentatsioonist", - "theme.SearchPage.existingResultsTitle": "Otsi tulemust päringule \"{query}\"", - "theme.SearchPage.fetchingNewResults": "Pärib uusi tulemusi...", - "theme.SearchPage.inputLabel": "Otsi", - "theme.SearchPage.inputPlaceholder": "Kirjuta oma päring siia", + "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Eemalda see otsing lemmikutest", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", + "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Eemalda see otsing ajaloost", + "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Salvesta see otsing", + "theme.SearchPage.algoliaLabel": "Otsingu võimaldab Algolia", + "theme.SearchPage.documentsFound.plurals": "Leitud {count} dokument", + "theme.SearchPage.emptyResultsTitle": "Otsi dokumentatsioonis", + "theme.SearchPage.existingResultsTitle": "Otsingutulemused päringule \"{query}\"", + "theme.SearchPage.fetchingNewResults": "Uute tulemuste laadimine...", + "theme.SearchPage.inputLabel": "Otsing", + "theme.SearchPage.inputPlaceholder": "Sisesta oma otsing siia", "theme.SearchPage.noResultsText": "Tulemusi ei leitud" } diff --git a/packages/docusaurus-theme-translations/locales/fa/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/fa/theme-search-algolia.json index e9108bc9da..4b237da096 100644 --- a/packages/docusaurus-theme-translations/locales/fa/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/fa/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "جستجو", "theme.SearchBar.seeAll": "نمایش {count} نتیجه", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "لطفا اتصال شبکه خود را بررسی کنید.", "theme.SearchModal.errorScreen.titleText": "دریافت نتایج ممکن نیست", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "کلید Escape", "theme.SearchModal.footer.closeText": "بستن", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "کلید پایین", @@ -11,25 +24,37 @@ "theme.SearchModal.footer.searchByText": "جستجو برای", "theme.SearchModal.footer.selectKeyAriaLabel": "کلید اینتر", "theme.SearchModal.footer.selectText": "انتخاب", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "هیچ نتیجه ای برای", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "با ما در میان بگذارید.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "آیا اطمینان دارید این جستجو باید نتیجه ای داشته باشد؟", "theme.SearchModal.noResultsScreen.suggestedQueryText": "جستجو پیشنهادی برای", "theme.SearchModal.placeholder": "جستجوی مستندات", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "کنسل", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "پاک کردن جستجو", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "برگزیده", "theme.SearchModal.startScreen.noRecentSearchesText": "جستجوی اخیر مشاهده نشد", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "اخیرا", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "این جستجو از برگزیده ها پاک شود", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "این جستجو از تاریخچه پاک شود", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "ذخیره این جستجو", - "theme.SearchPage.algoliaLabel": "جستجو با Algolia", + "theme.SearchPage.algoliaLabel": "قدرت گرفته از Algolia", "theme.SearchPage.documentsFound.plurals": "یک مورد پیدا شد|{count} مورد پیدا شد", "theme.SearchPage.emptyResultsTitle": "جستجو در متن", "theme.SearchPage.existingResultsTitle": "جستجو برای عبارت \"{query}\"", "theme.SearchPage.fetchingNewResults": "در حال دریافت نتایج...", "theme.SearchPage.inputLabel": "جستجو", - "theme.SearchPage.inputPlaceholder": "عبارت مورد نظر را اینجا بنویسید", - "theme.SearchPage.noResultsText": "هیچ نتیجه ای پیدا نشد" + "theme.SearchPage.inputPlaceholder": "جستجوی خود را اینجا تایپ کنید", + "theme.SearchPage.noResultsText": "هیچ نتیجه‌ای پیدا نشد" } diff --git a/packages/docusaurus-theme-translations/locales/fil/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/fil/theme-search-algolia.json index d17d797ded..ec81fd9efe 100644 --- a/packages/docusaurus-theme-translations/locales/fil/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/fil/theme-search-algolia.json @@ -1,35 +1,60 @@ { "theme.SearchBar.label": "Maghanap", "theme.SearchBar.seeAll": "See all {count} results", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "You might want to check your network connection.", "theme.SearchModal.errorScreen.titleText": "Unable to fetch results", + "theme.SearchModal.footer.backToSearchText": "Back to search", "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.searchByText": "Powered by", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter key", "theme.SearchModal.footer.selectText": "to select", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "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.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Cancel", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Clear the query", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorite", "theme.SearchModal.startScreen.noRecentSearchesText": "No recent searches", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Recent", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Save this search", - "theme.SearchPage.algoliaLabel": "Paghahanap hatid ng Algolia", + "theme.SearchPage.algoliaLabel": "Pinapagana ng Algolia", "theme.SearchPage.documentsFound.plurals": "Isang dokumento ang nahanap|{count} na mga dokumento ang nahanap", "theme.SearchPage.emptyResultsTitle": "Maghanap sa dokumentasyón", "theme.SearchPage.existingResultsTitle": "Resulta ng paghahanap para sa \"{query}\"", "theme.SearchPage.fetchingNewResults": "Kumukuha ng mga bagong resulta...", "theme.SearchPage.inputLabel": "Maghanap", - "theme.SearchPage.inputPlaceholder": "I-type and inyong hinahanap dito", - "theme.SearchPage.noResultsText": "Walang resultang nahanap" + "theme.SearchPage.inputPlaceholder": "I-type ang inyong paghahanap dito", + "theme.SearchPage.noResultsText": "Walang nahanap na resulta" } diff --git a/packages/docusaurus-theme-translations/locales/fr/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/fr/theme-search-algolia.json index be970d1af6..2eda7f3db5 100644 --- a/packages/docusaurus-theme-translations/locales/fr/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/fr/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Chercher", "theme.SearchBar.seeAll": "Voir les {count} résultats", + "theme.SearchModal.askAiScreen.afterToolCallText": "Recherche effectuée pour ", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copié !", + "theme.SearchModal.askAiScreen.copyButtonText": "Copier", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copier", + "theme.SearchModal.askAiScreen.disclaimerText": "Les réponses sont générées par l'IA et peuvent contenir des erreurs. Veuillez vérifier les réponses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Je n'aime pas", + "theme.SearchModal.askAiScreen.duringToolCallText": "Recherche de ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "J'aime", + "theme.SearchModal.askAiScreen.preToolCallText": "Recherche en cours...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Sources connexes", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Merci pour votre retour !", + "theme.SearchModal.askAiScreen.thinkingText": "Réflexion en cours...", "theme.SearchModal.errorScreen.helpText": "Vous pouvez vérifier votre connexion réseau.", "theme.SearchModal.errorScreen.titleText": "Impossible de récupérer les résultats", + "theme.SearchModal.footer.backToSearchText": "Retour à la recherche", "theme.SearchModal.footer.closeKeyAriaLabel": "Touche Echap", "theme.SearchModal.footer.closeText": "fermer", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Flèche vers le bas", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Recherche via", "theme.SearchModal.footer.selectKeyAriaLabel": "Touche Entrée", "theme.SearchModal.footer.selectText": "sélectionner", + "theme.SearchModal.footer.submitQuestionText": "Soumettre la question", "theme.SearchModal.noResultsScreen.noResultsText": "Aucun résultat pour", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Faites-le nous savoir.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Vous pensez que cette requête doit donner des résultats ?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Essayez de chercher", "theme.SearchModal.placeholder": "Rechercher des docs", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Demander à l'IA : ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Retour à la recherche par mots-clés", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Retour à la recherche par mots-clés", "theme.SearchModal.searchBox.cancelButtonText": "Annuler", + "theme.SearchModal.searchBox.enterKeyHint": "rechercher", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "entrée", + "theme.SearchModal.searchBox.placeholderText": "Rechercher des docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Poser une autre question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "En train de répondre...", "theme.SearchModal.searchBox.resetButtonTitle": "Effacer la requête", + "theme.SearchModal.searchBox.searchInputLabel": "Rechercher", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favoris", "theme.SearchModal.startScreen.noRecentSearchesText": "Aucune recherche récente", + "theme.SearchModal.startScreen.recentConversationsTitle": "Conversations récentes", "theme.SearchModal.startScreen.recentSearchesTitle": "Récemment", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Supprimer cette recherche des favoris", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Supprimer cette conversation de l'historique", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Supprimer cette recherche de l'historique", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Sauvegarder cette recherche", - "theme.SearchPage.algoliaLabel": "Recherche par Algolia", + "theme.SearchPage.algoliaLabel": "Fourni par Algolia", "theme.SearchPage.documentsFound.plurals": "Un document trouvé|{count} documents trouvés", "theme.SearchPage.emptyResultsTitle": "Rechercher dans la documentation", "theme.SearchPage.existingResultsTitle": "Résultats de recherche pour « {query} »", diff --git a/packages/docusaurus-theme-translations/locales/he/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/he/theme-search-algolia.json index 75f2ca642c..43d6a07b78 100644 --- a/packages/docusaurus-theme-translations/locales/he/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/he/theme-search-algolia.json @@ -1,35 +1,60 @@ { "theme.SearchBar.label": "חיפוש", "theme.SearchBar.seeAll": "See all {count} results", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "You might want to check your network connection.", "theme.SearchModal.errorScreen.titleText": "Unable to fetch results", + "theme.SearchModal.footer.backToSearchText": "Back to search", "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.searchByText": "Powered by", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter key", "theme.SearchModal.footer.selectText": "to select", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "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.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Cancel", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Clear the query", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorite", "theme.SearchModal.startScreen.noRecentSearchesText": "No recent searches", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Recent", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Save this search", - "theme.SearchPage.algoliaLabel": "חיפוש by Algolia", + "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.inputPlaceholder": "הקלד את החיפוש שלך כאן", "theme.SearchPage.noResultsText": "לא נמצאו תוצאות" } diff --git a/packages/docusaurus-theme-translations/locales/hi/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/hi/theme-search-algolia.json index f718a2fac5..46f24d198e 100644 --- a/packages/docusaurus-theme-translations/locales/hi/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/hi/theme-search-algolia.json @@ -1,35 +1,60 @@ { "theme.SearchBar.label": "खोज करें", "theme.SearchBar.seeAll": "See all {count} results", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "You might want to check your network connection.", "theme.SearchModal.errorScreen.titleText": "Unable to fetch results", + "theme.SearchModal.footer.backToSearchText": "Back to search", "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.searchByText": "Powered by", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter key", "theme.SearchModal.footer.selectText": "to select", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "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.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Cancel", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Clear the query", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorite", "theme.SearchModal.startScreen.noRecentSearchesText": "No recent searches", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Recent", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Save this search", - "theme.SearchPage.algoliaLabel": "अल्गोलिया द्वारा खोजें", + "theme.SearchPage.algoliaLabel": "Algolia द्वारा संचालित", "theme.SearchPage.documentsFound.plurals": "एक डॉक्यूमेंट मिला|{count} डॉक्यूमेंट मिलें", "theme.SearchPage.emptyResultsTitle": "डॉक्यूमेंटेशन में खोजें", "theme.SearchPage.existingResultsTitle": "\"{query}\" के लिए खोज परिणाम", - "theme.SearchPage.fetchingNewResults": "नए परिणाम प्राप्त कियें जा रहे हैं...", - "theme.SearchPage.inputLabel": "खोज करें", - "theme.SearchPage.inputPlaceholder": "अपनी खोज यहाँ टाइप करें", - "theme.SearchPage.noResultsText": "कोई परिणाम नहीं मिलें" + "theme.SearchPage.fetchingNewResults": "नए परिणाम प्राप्त कर रहे हैं...", + "theme.SearchPage.inputLabel": "खोजें", + "theme.SearchPage.inputPlaceholder": "यहाँ अपनी खोज टाइप करें", + "theme.SearchPage.noResultsText": "कोई परिणाम नहीं मिला" } diff --git a/packages/docusaurus-theme-translations/locales/hu/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/hu/theme-search-algolia.json index 0bf7ebca24..ef048a6bb1 100644 --- a/packages/docusaurus-theme-translations/locales/hu/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/hu/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Keresés", "theme.SearchBar.seeAll": "Összes eredmény megtekintése ({count})", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Ellenőrizze a hálózati kapcsolatot.", "theme.SearchModal.errorScreen.titleText": "Nem sikerült az eredményeket lekérni", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Escape billentyű", "theme.SearchModal.footer.closeText": "bezárás", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Lefelé nyíl", @@ -11,26 +24,37 @@ "theme.SearchModal.footer.searchByText": "Motor:", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter billentyű", "theme.SearchModal.footer.selectText": "kiválasztás", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Nincs eredmény", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Adja meg nekünk.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Úgy gondolja, hogy ez a keresés eredményt kellene adnia?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Próbálja meg keresni", "theme.SearchModal.placeholder": "Dokumentumok keresése", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Mégse", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Keresési kérés törlése", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Kedvencek", "theme.SearchModal.startScreen.noRecentSearchesText": "Nincsenek legutóbbi keresések", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Legutóbbi", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Törölje ezt a keresést a kedvencekből", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Törölje ezt a keresést az előzményekből", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Mentsük el ezt a keresést", - "theme.SearchPage.algoliaLabel": "Keresés az Algolia segítségével", + "theme.SearchPage.algoliaLabel": "Az Algolia támogatásával", "theme.SearchPage.documentsFound.plurals": "Egy dokumentum|{count} dokumentumok", "theme.SearchPage.emptyResultsTitle": "Keresés a webhelyen", "theme.SearchPage.existingResultsTitle": "\"{query}\" keresési eredményei", "theme.SearchPage.fetchingNewResults": "Új keresési eredmények betöltése...", "theme.SearchPage.inputLabel": "Keresés", - "theme.SearchPage.inputPlaceholder": "Adja meg a keresendő kifejezést", - "theme.SearchPage.noResultsText": "Nincs találat a keresésre", - "theme.SearchPage.saveRecentSearchButtonTitle": "Mentse ezt a keresést" + "theme.SearchPage.inputPlaceholder": "Írja be a keresését ide", + "theme.SearchPage.noResultsText": "Nem található eredmény" } diff --git a/packages/docusaurus-theme-translations/locales/id/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/id/theme-search-algolia.json index b294959d00..cbd7c6955c 100644 --- a/packages/docusaurus-theme-translations/locales/id/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/id/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Cari", "theme.SearchBar.seeAll": "Lihat semua {count} hasilnya", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Barangkali anda perlu memerika koneksi jaringan anda.", "theme.SearchModal.errorScreen.titleText": "Gagal mendapatkan hasilnya", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Tombol Escape", "theme.SearchModal.footer.closeText": "menutup", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Panah ke bawah", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Cari dengan teks", "theme.SearchModal.footer.selectKeyAriaLabel": "Tombol Enter", "theme.SearchModal.footer.selectText": "memilih", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Tak ada hasil untuk", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Beri tahu kami.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Yakin pencarian ini seharusnya memberikan hasil?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Coba lakukan pencarian untuk", "theme.SearchModal.placeholder": "Cari dokumentasi", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Batalkan", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Hapus teks pencarian", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorit", "theme.SearchModal.startScreen.noRecentSearchesText": "Tak ada riwayat pencarian", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Terbaru", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Hapus pencarian ini dari favorit", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Hapus pencarian ini dari riwayat", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Simpan pencarian ini", - "theme.SearchPage.algoliaLabel": "Pencarian oleh Algolia", + "theme.SearchPage.algoliaLabel": "Didukung oleh Algolia", "theme.SearchPage.documentsFound.plurals": "Satu dokumen ditemukan|{count} dokumen ditemukan", "theme.SearchPage.emptyResultsTitle": "Cari dokumentasi", "theme.SearchPage.existingResultsTitle": "Hasil pencarian untuk \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/is/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/is/theme-search-algolia.json index 547c0c0807..3b492a99a9 100644 --- a/packages/docusaurus-theme-translations/locales/is/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/is/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Leita", "theme.SearchBar.seeAll": "Sjá allar {count} niðurstöður", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Þú gætir viljað athuga nettenginguna.", "theme.SearchModal.errorScreen.titleText": "Tókst ekki að sækja niðurstöður", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Escape hnappur", "theme.SearchModal.footer.closeText": "til að loka", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Ör niður", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Leit með", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter hnappur", "theme.SearchModal.footer.selectText": "að velja", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Engin niðurstaða fyrir", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Láttu okkur vita.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Tel að þessi fyrirspurn eigi að skila niðurstöðum?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Prófaðu að leita að", "theme.SearchModal.placeholder": "Leita í skjölum", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Hætta", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Hreinsa fyrirspurn", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Uppáhalds", "theme.SearchModal.startScreen.noRecentSearchesText": "Engar nýlegar leitir", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Nýlegar", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Fjarlægja þessa leit úr uppáhalds", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Fjarlægja þessa leit úr sögu", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Vista þessa leit", - "theme.SearchPage.algoliaLabel": "Leit með Algolia", + "theme.SearchPage.algoliaLabel": "Keyrt af Algolia", "theme.SearchPage.documentsFound.plurals": "Eitt skjal fannst|{count} skjöl fundust", "theme.SearchPage.emptyResultsTitle": "Leita í skjölun", "theme.SearchPage.existingResultsTitle": "Niðurstöður fyrir \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/it/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/it/theme-search-algolia.json index 0160450688..f78ea26ab3 100644 --- a/packages/docusaurus-theme-translations/locales/it/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/it/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Cerca", "theme.SearchBar.seeAll": "Vedi tutti {count} risultati", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Potresti voler controllare la tua connessione di rete.", "theme.SearchModal.errorScreen.titleText": "Impossibile recuperare i risultati", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Tasto di fuga", "theme.SearchModal.footer.closeText": "chiudere", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Freccia giù", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Cercato da", "theme.SearchModal.footer.selectKeyAriaLabel": "Tasto Invio", "theme.SearchModal.footer.selectText": "selezionare", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Nessun risultato per", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Facci sapere.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Credi che questa query dovrebbe restituire risultati?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Prova a cercare", "theme.SearchModal.placeholder": "Cerca documenti", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Annulla", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Cancella la query", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Preferita", "theme.SearchModal.startScreen.noRecentSearchesText": "Nessuna ricerca recente", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Recente", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Rimuovi questa ricerca dai preferiti", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Rimuovi questa ricerca dalla cronologia", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Salva questa ricerca", - "theme.SearchPage.algoliaLabel": "Ricerca tramite Algolia", + "theme.SearchPage.algoliaLabel": "Fornito da Algolia", "theme.SearchPage.documentsFound.plurals": "Un documento trovato|{count} documenti trovati", "theme.SearchPage.emptyResultsTitle": "Cerca nella documentazione", "theme.SearchPage.existingResultsTitle": "Risultati di ricerca per \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/ja/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/ja/theme-search-algolia.json index fa0ffbacdc..8d41242252 100644 --- a/packages/docusaurus-theme-translations/locales/ja/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/ja/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "検索", "theme.SearchBar.seeAll": "検索結果{count}件をすべて見る", + "theme.SearchModal.askAiScreen.afterToolCallText": "検索完了:", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "コピーしました!", + "theme.SearchModal.askAiScreen.copyButtonText": "コピー", + "theme.SearchModal.askAiScreen.copyButtonTitle": "コピー", + "theme.SearchModal.askAiScreen.disclaimerText": "回答はAIによって生成されており、誤りがある可能性があります。必ず内容を確認してください。", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "よくない", + "theme.SearchModal.askAiScreen.duringToolCallText": "検索中:", + "theme.SearchModal.askAiScreen.likeButtonTitle": "いいね", + "theme.SearchModal.askAiScreen.preToolCallText": "検索中...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "関連ソース", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "フィードバックありがとうございます!", + "theme.SearchModal.askAiScreen.thinkingText": "考え中...", "theme.SearchModal.errorScreen.helpText": "ネットワーク接続を確認してください", "theme.SearchModal.errorScreen.titleText": "検索結果の取得に失敗しました", + "theme.SearchModal.footer.backToSearchText": "検索に戻る", "theme.SearchModal.footer.closeKeyAriaLabel": "エスケープキー", "theme.SearchModal.footer.closeText": "閉じる", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "下矢印キー", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "検索", "theme.SearchModal.footer.selectKeyAriaLabel": "エンターキー", "theme.SearchModal.footer.selectText": "選ぶ", + "theme.SearchModal.footer.submitQuestionText": "質問を送信", "theme.SearchModal.noResultsScreen.noResultsText": "見つかりませんでした", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "報告する", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "よりよい検索結果がありますか?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "次の検索を試す:", "theme.SearchModal.placeholder": "ドキュメントを検索", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "AIに質問:", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "キーワード検索に戻る", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "キーワード検索に戻る", "theme.SearchModal.searchBox.cancelButtonText": "キャンセル", + "theme.SearchModal.searchBox.enterKeyHint": "検索", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "確定", + "theme.SearchModal.searchBox.placeholderText": "ドキュメントを検索", + "theme.SearchModal.searchBox.placeholderTextAskAi": "別の質問をする...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "回答中...", "theme.SearchModal.searchBox.resetButtonTitle": "クリア", + "theme.SearchModal.searchBox.searchInputLabel": "検索", "theme.SearchModal.startScreen.favoriteSearchesTitle": "お気に入り", "theme.SearchModal.startScreen.noRecentSearchesText": "最近の検索履歴はありません", + "theme.SearchModal.startScreen.recentConversationsTitle": "最近の会話", "theme.SearchModal.startScreen.recentSearchesTitle": "最近の検索", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "この検索をお気に入りから削除", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "この会話を履歴から削除", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "この検索を履歴から削除", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "この検索をお気に入りに追加", - "theme.SearchPage.algoliaLabel": "Algoliaで検索", + "theme.SearchPage.algoliaLabel": "Algolia提供", "theme.SearchPage.documentsFound.plurals": "{count}件のドキュメントが見つかりました", "theme.SearchPage.emptyResultsTitle": "ドキュメントを検索", "theme.SearchPage.existingResultsTitle": "『{query}』の検索結果", diff --git a/packages/docusaurus-theme-translations/locales/ko/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/ko/theme-search-algolia.json index d1941ec178..15111a335c 100644 --- a/packages/docusaurus-theme-translations/locales/ko/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/ko/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "검색", "theme.SearchBar.seeAll": "{count}개의 결과 확인하기", + "theme.SearchModal.askAiScreen.afterToolCallText": "검색 완료: ", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "복사됨!", + "theme.SearchModal.askAiScreen.copyButtonText": "복사", + "theme.SearchModal.askAiScreen.copyButtonTitle": "복사", + "theme.SearchModal.askAiScreen.disclaimerText": "답변은 AI가 생성하며 오류가 있을 수 있습니다. 응답을 확인해주세요.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "싫어요", + "theme.SearchModal.askAiScreen.duringToolCallText": "검색 중: ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "좋아요", + "theme.SearchModal.askAiScreen.preToolCallText": "검색 중...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "관련 출처", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "피드백 감사합니다!", + "theme.SearchModal.askAiScreen.thinkingText": "생각 중...", "theme.SearchModal.errorScreen.helpText": "인터넷 연결을 다시 확인하시기 바랍니다.", "theme.SearchModal.errorScreen.titleText": "결과를 불러올 수 없음", + "theme.SearchModal.footer.backToSearchText": "검색으로 돌아가기", "theme.SearchModal.footer.closeKeyAriaLabel": "Esc 키", "theme.SearchModal.footer.closeText": "로 종료", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "화살표 아래 키", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "검색 제공", "theme.SearchModal.footer.selectKeyAriaLabel": "엔터 키", "theme.SearchModal.footer.selectText": "로 선택", + "theme.SearchModal.footer.submitQuestionText": "질문 제출", "theme.SearchModal.noResultsScreen.noResultsText": "검색 결과 없음", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "알려주시기 바랍니다.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "검색 결과가 없는 것이 오류라고 생각되십니까?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "다른 추천 검색어", "theme.SearchModal.placeholder": "문서 검색", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "AI에게 질문: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "키워드 검색으로 돌아가기", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "키워드 검색으로 돌아가기", "theme.SearchModal.searchBox.cancelButtonText": "취소", + "theme.SearchModal.searchBox.enterKeyHint": "검색", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "입력", + "theme.SearchModal.searchBox.placeholderText": "문서 검색", + "theme.SearchModal.searchBox.placeholderTextAskAi": "다른 질문하기...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "답변 중...", "theme.SearchModal.searchBox.resetButtonTitle": "검색어 초기화", + "theme.SearchModal.searchBox.searchInputLabel": "검색", "theme.SearchModal.startScreen.favoriteSearchesTitle": "즐겨찾기", "theme.SearchModal.startScreen.noRecentSearchesText": "최근 검색어 없음", + "theme.SearchModal.startScreen.recentConversationsTitle": "최근 대화", "theme.SearchModal.startScreen.recentSearchesTitle": "최근", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "이 검색어를 즐겨찾기에서 삭제", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "이 대화를 기록에서 삭제", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "이 검색어를 최근 검색어에서 삭제", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "이 검색어를 저장", - "theme.SearchPage.algoliaLabel": "Algolia로 검색", + "theme.SearchPage.algoliaLabel": "Algolia 제공", "theme.SearchPage.documentsFound.plurals": "{count}개의 문서를 찾았습니다.", "theme.SearchPage.emptyResultsTitle": "문서를 검색합니다.", "theme.SearchPage.existingResultsTitle": "\"{query}\" 검색 결과", diff --git a/packages/docusaurus-theme-translations/locales/nb/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/nb/theme-search-algolia.json index 1871413677..95048f778b 100644 --- a/packages/docusaurus-theme-translations/locales/nb/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/nb/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Søk", "theme.SearchBar.seeAll": "Se alle {count} resultat", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Det kan være lurt å sjekke nettverkstilkoblingen.", "theme.SearchModal.errorScreen.titleText": "Kan ikke hente resultater", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Escape-tasten", "theme.SearchModal.footer.closeText": "Lukk", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Pil ned", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Søk på", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter-tasten", "theme.SearchModal.footer.selectText": "for å velge", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Ingen resultat", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Gi oss beskjed.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Tenker du at denne spørringen bør gi resultater?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Prøv å søke etter", "theme.SearchModal.placeholder": "Søk i dokumenter", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Avbryt", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Fjern søket", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favoritt", "theme.SearchModal.startScreen.noRecentSearchesText": "Ingen nylige søk", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Nylig", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Fjern dette søket fra favoritter", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Fjern dette søket fra loggen", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Lagre dette søket", - "theme.SearchPage.algoliaLabel": "Søk med Algolia", + "theme.SearchPage.algoliaLabel": "Drevet av Algolia", "theme.SearchPage.documentsFound.plurals": "Ett dokument funnet|{count} dokumenter funnet", "theme.SearchPage.emptyResultsTitle": "Søk i dokumentasjonen", "theme.SearchPage.existingResultsTitle": "Søkeresultater for \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/nl/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/nl/theme-search-algolia.json index 8b99bcd7a7..910e036249 100644 --- a/packages/docusaurus-theme-translations/locales/nl/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/nl/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Zoeken", "theme.SearchBar.seeAll": "Laat alle {count} resultaten zien", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Misschien wilt u uw netwerkverbinding controleren.", "theme.SearchModal.errorScreen.titleText": "Niet in staat resultaten op te halen", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Escape-toets", "theme.SearchModal.footer.closeText": "om te sluiten", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Pijltoets naar beneden", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Zoek op", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter-toets", "theme.SearchModal.footer.selectText": "om te selecteren", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Geen resultaten voor", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Laat het ons weten.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Zou deze zoekopdracht resultaten moeten opleveren?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Probeer om te zoeken op", "theme.SearchModal.placeholder": "Doorzoek de documentatie", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Annuleren", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Maak de zoekopdracht leeg", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favoriet", "theme.SearchModal.startScreen.noRecentSearchesText": "Geen recente zoekopdrachten", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Recente zoekopdrachten", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Verwijder deze zoekopdracht uit mijn favorieten", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Verwijder deze zoekopdracht uit mijn geschiedenis", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Sla deze zoekopdracht op", - "theme.SearchPage.algoliaLabel": "Zoeken door Algolia", + "theme.SearchPage.algoliaLabel": "Aangedreven door Algolia", "theme.SearchPage.documentsFound.plurals": "Een document gevonden|{count} documenten gevonden", "theme.SearchPage.emptyResultsTitle": "Doorzoek de documentatie", "theme.SearchPage.existingResultsTitle": "Zoekresultaten voor \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/pl/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/pl/theme-search-algolia.json index bc4ab9d5f6..b689bd2133 100644 --- a/packages/docusaurus-theme-translations/locales/pl/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/pl/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Szukaj", "theme.SearchBar.seeAll": "Wyświetl wszystkie {count} wyników", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Sprawdź swoje połączenie sieciowe.", "theme.SearchModal.errorScreen.titleText": "Nie można pobrać wyników", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Klawisz Escape", "theme.SearchModal.footer.closeText": "aby zamknąć", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Strzałka w dół", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Szukaj według", "theme.SearchModal.footer.selectKeyAriaLabel": "Klawisz Enter", "theme.SearchModal.footer.selectText": "aby wybrać", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Brak wyników dla", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Daj nam znać.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Wydaje Ci się, że to zapytanie powinno zwrócić wyniki?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Spróbuj poszukać", "theme.SearchModal.placeholder": "Wyszukaj dokumenty", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Anuluj", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Wyczyść zapytanie", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Ulubione", "theme.SearchModal.startScreen.noRecentSearchesText": "Brak ostatnich wyszukiwań", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Ostatnie wyszukiwania", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Usuń to wyszukiwanie z ulubionych", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Usuń to wyszukiwanie z historii", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Zapisz to wyszukiwanie", - "theme.SearchPage.algoliaLabel": "Dostawca rozwiązania Algolia", + "theme.SearchPage.algoliaLabel": "Napędzane przez Algolia", "theme.SearchPage.documentsFound.plurals": "Jeden dokument znaleziony|{count} dokumenty znalezione|{count} dokumentów znalezionych", "theme.SearchPage.emptyResultsTitle": "Wyszukaj w dokumentacji", "theme.SearchPage.existingResultsTitle": "Wyniki wyszukiwania dla \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/pt-BR/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/pt-BR/theme-search-algolia.json index 83938b9c90..77c15c42c5 100644 --- a/packages/docusaurus-theme-translations/locales/pt-BR/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/pt-BR/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Buscar", "theme.SearchBar.seeAll": "Ver todos os {count} resultados", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Talvez você deva verificar sua conexão de rede.", "theme.SearchModal.errorScreen.titleText": "Não foi possível obter resultados", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Tecla Esc", "theme.SearchModal.footer.closeText": "fechar", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Seta para baixo", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Esta busca utiliza", "theme.SearchModal.footer.selectKeyAriaLabel": "Tecla Enter", "theme.SearchModal.footer.selectText": "selecionar", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Nenhum resultado para", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Nos avise.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Você acha que esta busca deveria retornar resultados?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Tente buscar por", "theme.SearchModal.placeholder": "Buscar documentos", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Cancelar", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Limpar a busca", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorito", "theme.SearchModal.startScreen.noRecentSearchesText": "Nenhuma busca recente", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Recente", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Remover esta busca dos favoritos", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Remover esta busca do histórico", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Salvar esta busca", - "theme.SearchPage.algoliaLabel": "Busca feita por Algolia", + "theme.SearchPage.algoliaLabel": "Desenvolvido por Algolia", "theme.SearchPage.documentsFound.plurals": "Um documento encontrado|{count} documentos encontrados", "theme.SearchPage.emptyResultsTitle": "Busca da documentação", "theme.SearchPage.existingResultsTitle": "Resultado da busca por \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/pt-PT/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/pt-PT/theme-search-algolia.json index 1d1ab1ef63..2a47d02c79 100644 --- a/packages/docusaurus-theme-translations/locales/pt-PT/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/pt-PT/theme-search-algolia.json @@ -1,30 +1,55 @@ { "theme.SearchBar.label": "Pesquisar", "theme.SearchBar.seeAll": "See all {count} results", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "You might want to check your network connection.", "theme.SearchModal.errorScreen.titleText": "Unable to fetch results", + "theme.SearchModal.footer.backToSearchText": "Back to search", "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.searchByText": "Powered by", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter key", "theme.SearchModal.footer.selectText": "to select", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "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.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Cancel", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Clear the query", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorite", "theme.SearchModal.startScreen.noRecentSearchesText": "No recent searches", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Recent", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Save this search", - "theme.SearchPage.algoliaLabel": "Pesquisa por Algolia", + "theme.SearchPage.algoliaLabel": "Desenvolvido por Algolia", "theme.SearchPage.documentsFound.plurals": "Um documento encontrado|{count} documentos encontrados", "theme.SearchPage.emptyResultsTitle": "Pesquisar pela documentação", "theme.SearchPage.existingResultsTitle": "Resultados da pesquisa por \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/ru/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/ru/theme-search-algolia.json index 39005aee5c..1df1f89722 100644 --- a/packages/docusaurus-theme-translations/locales/ru/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/ru/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Поиск", "theme.SearchBar.seeAll": "Посмотреть все результаты ({count})", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Проверьте подключение к интернету.", "theme.SearchModal.errorScreen.titleText": "Невозможно загрузить результаты поиска", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Клавиша Escape", "theme.SearchModal.footer.closeText": "закрыть", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Клавиша стрелка вниз", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Поиск от", "theme.SearchModal.footer.selectKeyAriaLabel": "Клавиша Enter", "theme.SearchModal.footer.selectText": "выбрать", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Нет результатов по запросу", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Сообщите нам.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Нет подходящего результата поиска?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Попробуйте", "theme.SearchModal.placeholder": "Поиск", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Отменить", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Очистить", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Избранное", "theme.SearchModal.startScreen.noRecentSearchesText": "Нет истории поиска", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Недавнее", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Удалить запись из избранное", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Удалить запись из историю", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Сохранить поисковый запрос", - "theme.SearchPage.algoliaLabel": "Поиск от Algolia", + "theme.SearchPage.algoliaLabel": "При поддержке Algolia", "theme.SearchPage.documentsFound.plurals": "{count} документ|{count} документа|{count} документов", "theme.SearchPage.emptyResultsTitle": "Поиск по сайту", "theme.SearchPage.existingResultsTitle": "Результаты поиска по запросу \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/sl/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/sl/theme-search-algolia.json index e2c1e41bc3..d9d61b94d5 100644 --- a/packages/docusaurus-theme-translations/locales/sl/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/sl/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Išči", "theme.SearchBar.seeAll": "Poglej vse rezultate ({count})", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Preverite vašo spletno povezavo.", "theme.SearchModal.errorScreen.titleText": "Rezultatov ni bilo možno naložiti", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Tipka Escape", "theme.SearchModal.footer.closeText": "zapri", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Tipka puščica navzdol", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Iskanje", "theme.SearchModal.footer.selectKeyAriaLabel": "tipka Enter", "theme.SearchModal.footer.selectText": "izberi", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Ni rezultatov za", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Obvestite nas.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Mislite, da bi morali obstajati rezultati?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Poskusite poiskati", "theme.SearchModal.placeholder": "Išči po dokumentaciji", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Prekliči", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Izprazni iskalni niz", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Priljubljena iskanja", "theme.SearchModal.startScreen.noRecentSearchesText": "Ni iskanj pred kratkim", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Pred kratkim", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Umakni iskanje iz priljubljenih", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Umakni iskanje iz zgodovine", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Shrani to iskanje", - "theme.SearchPage.algoliaLabel": "Iskanje Algolia", + "theme.SearchPage.algoliaLabel": "Poganja Algolia", "theme.SearchPage.documentsFound.plurals": "Dokument najden|Dokumenta najdena|{count} dokumenti najdeni|{count} dokumentov najdenih", "theme.SearchPage.emptyResultsTitle": "Išči po dokumentaciji", "theme.SearchPage.existingResultsTitle": "Rezultati iskanja za \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/sr/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/sr/theme-search-algolia.json index 4c6e05d55e..337015a14e 100644 --- a/packages/docusaurus-theme-translations/locales/sr/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/sr/theme-search-algolia.json @@ -1,30 +1,55 @@ { "theme.SearchBar.label": "Тражи", "theme.SearchBar.seeAll": "See all {count} results", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "You might want to check your network connection.", "theme.SearchModal.errorScreen.titleText": "Unable to fetch results", + "theme.SearchModal.footer.backToSearchText": "Back to search", "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.searchByText": "Powered by", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter key", "theme.SearchModal.footer.selectText": "to select", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "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.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Cancel", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Clear the query", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favorite", "theme.SearchModal.startScreen.noRecentSearchesText": "No recent searches", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Recent", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Remove this search from favorites", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Remove this search from history", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Save this search", - "theme.SearchPage.algoliaLabel": "Претрага из Algolia", + "theme.SearchPage.algoliaLabel": "Покреће Algolia", "theme.SearchPage.documentsFound.plurals": "Један пронађен документ|{count} пронађених докумената", "theme.SearchPage.emptyResultsTitle": "Тражи документацију", "theme.SearchPage.existingResultsTitle": "Резултати за \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/sv/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/sv/theme-search-algolia.json index c5477d8b59..c83d2e778b 100644 --- a/packages/docusaurus-theme-translations/locales/sv/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/sv/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Sök", "theme.SearchBar.seeAll": "Se alla {count} resultat", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Du kanske vill kontrollera din nätverksanslutning.", "theme.SearchModal.errorScreen.titleText": "Kunde inte hämta resultat", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Escape-tangenten", "theme.SearchModal.footer.closeText": "för att stänga", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Pil ned", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Sökning från", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter-tangenten", "theme.SearchModal.footer.selectText": "för att välja", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Inga resultat för", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Återkoppla.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Tycker du att sökningen borde returnera resultat?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Försöka söka efter", "theme.SearchModal.placeholder": "Sök i dokumentationen", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Avbryt", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Rensa sökningen", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favoriter", "theme.SearchModal.startScreen.noRecentSearchesText": "Inga senaste sökningar", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Senaste sökningar", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Ta bort från favoriter", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Ta bort från historiken", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Lägg till som favorit", - "theme.SearchPage.algoliaLabel": "Sökning från Algolia", + "theme.SearchPage.algoliaLabel": "Drivs av Algolia", "theme.SearchPage.documentsFound.plurals": "Ett dokument hittades|{count} dokument hittades", "theme.SearchPage.emptyResultsTitle": "Sök genom dokumentationen", "theme.SearchPage.existingResultsTitle": "Sökresultat för \"{query}\"", diff --git a/packages/docusaurus-theme-translations/locales/tk/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/tk/theme-search-algolia.json index 39627ef516..c3621dcaff 100644 --- a/packages/docusaurus-theme-translations/locales/tk/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/tk/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Gözleg", "theme.SearchBar.seeAll": "Ähli netijeleri gör ({count})", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Internet birikmäňizi barlaň.", "theme.SearchModal.errorScreen.titleText": "Gözleg netijelerini ýüklemek mümkin däl", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Escape düwmesi", "theme.SearchModal.footer.closeText": "ýapmak", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Aşak ok düwmesi", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Gözleg", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter düwmesi", "theme.SearchModal.footer.selectText": "saýlamak", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Sorag boýunça netijeler ýok", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Bize habar beriň.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Gözleg netijesi ýokmy?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Synanyşyň", "theme.SearchModal.placeholder": "Gözleg", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Ýatyrmak", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Arassalamak", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Halaýanlar", "theme.SearchModal.startScreen.noRecentSearchesText": "Gözleg taryhy ýok", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Soňky", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Halaýan ýazgyny aýyrmak", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Taryh ýazgysyny aýyrmak", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Gözleg soragyny ýatda saklaň", - "theme.SearchPage.algoliaLabel": "Algolia tarapyndan gözleg", + "theme.SearchPage.algoliaLabel": "Algolia tarapyndan goldanylýar", "theme.SearchPage.documentsFound.plurals": "{count} dokument|{count} dokumentler", "theme.SearchPage.emptyResultsTitle": "Sahypada gözleg", "theme.SearchPage.existingResultsTitle": "\"{query}\" boýunça gözleg netijeleri", diff --git a/packages/docusaurus-theme-translations/locales/tr/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/tr/theme-search-algolia.json index 04b00b9690..c1635ea334 100644 --- a/packages/docusaurus-theme-translations/locales/tr/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/tr/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Ara", "theme.SearchBar.seeAll": "{count} sonucun tümünü görün", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Ağ bağlantınızı kontrol etmek isteyebilirsiniz.", "theme.SearchModal.errorScreen.titleText": "Sonuçlar alınamadı", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "ESC Tuşu", "theme.SearchModal.footer.closeText": "Kapat", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Aşağı ok", @@ -11,20 +24,32 @@ "theme.SearchModal.footer.searchByText": "Şuna göre ara:", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter tuşu", "theme.SearchModal.footer.selectText": "Seç", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "için sonuç yok", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Bilmemize izin ver.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Bu sorgunun sonuç döndürmesi gerektiğine inanıyor musunuz?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Aramayı deneyin", "theme.SearchModal.placeholder": "Dokümanlarda ara", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "İptal", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Sorguyu temizle", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Favori", "theme.SearchModal.startScreen.noRecentSearchesText": "Son arama yok", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Son", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Bu aramayı favorilerden kaldır", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Bu aramayı geçmişten kaldır", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Bu aramayı kaydet", - "theme.SearchPage.algoliaLabel": "Algolia ile Ara", + "theme.SearchPage.algoliaLabel": "Algolia tarafından desteklenmektedir", "theme.SearchPage.documentsFound.plurals": "Bir döküman bulundu|{count} döküman bulundu", "theme.SearchPage.emptyResultsTitle": "Dokümanlarda ara", "theme.SearchPage.existingResultsTitle": "Arama sonuçları", diff --git a/packages/docusaurus-theme-translations/locales/uk/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/uk/theme-search-algolia.json index 263ee92511..d26538bc52 100644 --- a/packages/docusaurus-theme-translations/locales/uk/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/uk/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Пошук", "theme.SearchBar.seeAll": "Переглянути всі результати ({count})", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "Перевірте підключення до мережі.", "theme.SearchModal.errorScreen.titleText": "Не вдалося отримати результати", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Клавіша Escape", "theme.SearchModal.footer.closeText": "закрити", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Стрілка вниз", @@ -11,25 +24,37 @@ "theme.SearchModal.footer.searchByText": "Пошук за допомогою", "theme.SearchModal.footer.selectKeyAriaLabel": "Клавіша Enter", "theme.SearchModal.footer.selectText": "обрати", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "Немає результатів для", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "Дайте нам знати.", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "Чи вважаєте ви, що цей запит має повернути результати?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "Спробуйте пошукати", "theme.SearchModal.placeholder": "Пошук документів", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Скасувати", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Очистити запит", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "Обране", "theme.SearchModal.startScreen.noRecentSearchesText": "Немає останніх пошуків", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "Останні", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "Видалити цей пошук з обраного", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "Видалити цей пошук з історії", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "Зберегти цей пошук", - "theme.SearchPage.algoliaLabel": "Пошук за допомогою Algolia", + "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": "За запитом нічого не знайдено" + "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 664f86539c..18191ca11a 100644 --- a/packages/docusaurus-theme-translations/locales/vi/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/vi/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "Tìm kiếm", "theme.SearchBar.seeAll": "Xem tất cả {count} kết quả", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "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.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Phím thoát", "theme.SearchModal.footer.closeText": "để đóng", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "Mũi tên xuống", @@ -11,25 +24,37 @@ "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.footer.submitQuestionText": "Submit question", "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.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "Hủy bỏ", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "Xóa truy vấn", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "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.recentConversationsTitle": "Recent conversations", "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.removeRecentConversationButtonTitle": "Remove this conversation from history", "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.algoliaLabel": "Được cung cấp bởi Algolia", "theme.SearchPage.documentsFound.plurals": "Tìm thấy {count} kết quả", "theme.SearchPage.emptyResultsTitle": "Tìm kiếm", "theme.SearchPage.existingResultsTitle": "Kết quả tìm kiếm cho \"{query}\"", "theme.SearchPage.fetchingNewResults": "Đang tải thêm kết quả...", "theme.SearchPage.inputLabel": "Tìm kiếm", - "theme.SearchPage.inputPlaceholder": "Nhập từ khóa cần tìm vào đây", - "theme.SearchPage.noResultsText": "Không tìm thấy kết quả nào" + "theme.SearchPage.inputPlaceholder": "Nhập tìm kiếm của bạn ở đây", + "theme.SearchPage.noResultsText": "Không tìm thấy kết quả" } diff --git a/packages/docusaurus-theme-translations/locales/zh-Hans/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/zh-Hans/theme-search-algolia.json index fb86932938..7f6ac62a23 100644 --- a/packages/docusaurus-theme-translations/locales/zh-Hans/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/zh-Hans/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "搜索", "theme.SearchBar.seeAll": "查看全部 {count} 个结果", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "你可能需要检查网络连接。", "theme.SearchModal.errorScreen.titleText": "无法获取结果", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Esc 键", "theme.SearchModal.footer.closeText": "关闭", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "向下键", @@ -11,25 +24,37 @@ "theme.SearchModal.footer.searchByText": "搜索提供", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter 键", "theme.SearchModal.footer.selectText": "选中", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "没有结果:", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "请告知我们。", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "认为这个查询应该有结果?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "试试搜索", "theme.SearchModal.placeholder": "搜索文档", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "取消", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "清除查询", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "收藏", "theme.SearchModal.startScreen.noRecentSearchesText": "没有最近搜索", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "最近搜索", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "从收藏列表中删除这个搜索", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "从历史记录中删除这个搜索", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "保存这个搜索", - "theme.SearchPage.algoliaLabel": "通过 Algolia 搜索", + "theme.SearchPage.algoliaLabel": "由 Algolia 提供", "theme.SearchPage.documentsFound.plurals": "找到 {count} 份文件", "theme.SearchPage.emptyResultsTitle": "在文档中搜索", "theme.SearchPage.existingResultsTitle": "「{query}」的搜索结果", "theme.SearchPage.fetchingNewResults": "正在获取新的搜索结果...", "theme.SearchPage.inputLabel": "搜索", - "theme.SearchPage.inputPlaceholder": "在此输入搜索字词", - "theme.SearchPage.noResultsText": "未找到任何结果" + "theme.SearchPage.inputPlaceholder": "在此输入搜索词", + "theme.SearchPage.noResultsText": "未找到结果" } diff --git a/packages/docusaurus-theme-translations/locales/zh-Hant/theme-search-algolia.json b/packages/docusaurus-theme-translations/locales/zh-Hant/theme-search-algolia.json index 9e71d66561..4f8bee87df 100644 --- a/packages/docusaurus-theme-translations/locales/zh-Hant/theme-search-algolia.json +++ b/packages/docusaurus-theme-translations/locales/zh-Hant/theme-search-algolia.json @@ -1,8 +1,21 @@ { "theme.SearchBar.label": "搜尋", "theme.SearchBar.seeAll": "查看全部 {count} 個結果", + "theme.SearchModal.askAiScreen.afterToolCallText": "Searched for", + "theme.SearchModal.askAiScreen.copyButtonCopiedText": "Copied!", + "theme.SearchModal.askAiScreen.copyButtonText": "Copy", + "theme.SearchModal.askAiScreen.copyButtonTitle": "Copy", + "theme.SearchModal.askAiScreen.disclaimerText": "Answers are generated with AI which can make mistakes. Verify responses.", + "theme.SearchModal.askAiScreen.dislikeButtonTitle": "Dislike", + "theme.SearchModal.askAiScreen.duringToolCallText": "Searching for ", + "theme.SearchModal.askAiScreen.likeButtonTitle": "Like", + "theme.SearchModal.askAiScreen.preToolCallText": "Searching...", + "theme.SearchModal.askAiScreen.relatedSourcesText": "Related sources", + "theme.SearchModal.askAiScreen.thanksForFeedbackText": "Thanks for your feedback!", + "theme.SearchModal.askAiScreen.thinkingText": "Thinking...", "theme.SearchModal.errorScreen.helpText": "你可能需要檢查網路連線。", "theme.SearchModal.errorScreen.titleText": "無法獲取結果", + "theme.SearchModal.footer.backToSearchText": "Back to search", "theme.SearchModal.footer.closeKeyAriaLabel": "Esc 鍵", "theme.SearchModal.footer.closeText": "關閉", "theme.SearchModal.footer.navigateDownKeyAriaLabel": "向下鍵", @@ -11,25 +24,37 @@ "theme.SearchModal.footer.searchByText": "搜尋提供", "theme.SearchModal.footer.selectKeyAriaLabel": "Enter 鍵", "theme.SearchModal.footer.selectText": "選中", + "theme.SearchModal.footer.submitQuestionText": "Submit question", "theme.SearchModal.noResultsScreen.noResultsText": "沒有結果:", "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": "請告知我們。", "theme.SearchModal.noResultsScreen.reportMissingResultsText": "認為這個查詢應該有結果?", "theme.SearchModal.noResultsScreen.suggestedQueryText": "試試搜尋", "theme.SearchModal.placeholder": "搜尋文檔", + "theme.SearchModal.resultsScreen.askAiPlaceholder": "Ask AI: ", + "theme.SearchModal.searchBox.backToKeywordSearchButtonAriaLabel": "Back to keyword search", + "theme.SearchModal.searchBox.backToKeywordSearchButtonText": "Back to keyword search", "theme.SearchModal.searchBox.cancelButtonText": "取消", + "theme.SearchModal.searchBox.enterKeyHint": "search", + "theme.SearchModal.searchBox.enterKeyHintAskAi": "enter", + "theme.SearchModal.searchBox.placeholderText": "Search docs", + "theme.SearchModal.searchBox.placeholderTextAskAi": "Ask another question...", + "theme.SearchModal.searchBox.placeholderTextAskAiStreaming": "Answering...", "theme.SearchModal.searchBox.resetButtonTitle": "清除查詢", + "theme.SearchModal.searchBox.searchInputLabel": "Search", "theme.SearchModal.startScreen.favoriteSearchesTitle": "收藏", "theme.SearchModal.startScreen.noRecentSearchesText": "沒有最近的搜尋", + "theme.SearchModal.startScreen.recentConversationsTitle": "Recent conversations", "theme.SearchModal.startScreen.recentSearchesTitle": "最近搜尋", "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": "從收藏列表中刪除這個搜尋", + "theme.SearchModal.startScreen.removeRecentConversationButtonTitle": "Remove this conversation from history", "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": "從歷史記錄中刪除這個搜尋", "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": "保存這個搜尋", - "theme.SearchPage.algoliaLabel": "透過 Algolia 搜尋", + "theme.SearchPage.algoliaLabel": "由 Algolia 提供", "theme.SearchPage.documentsFound.plurals": "找到 {count} 份文件", "theme.SearchPage.emptyResultsTitle": "在文件中搜尋", "theme.SearchPage.existingResultsTitle": "「{query}」的搜尋結果", "theme.SearchPage.fetchingNewResults": "正在取得新的搜尋結果...", "theme.SearchPage.inputLabel": "搜尋", - "theme.SearchPage.inputPlaceholder": "在此輸入搜尋字詞", - "theme.SearchPage.noResultsText": "未找到任何結果" + "theme.SearchPage.inputPlaceholder": "在此輸入搜尋詞", + "theme.SearchPage.noResultsText": "未找到結果" } diff --git a/project-words.txt b/project-words.txt index e377036d12..84ab6efecc 100644 --- a/project-words.txt +++ b/project-words.txt @@ -367,3 +367,4 @@ Zhou zoomable zpao ödingers +BYOLLM diff --git a/website/docs/search.mdx b/website/docs/search.mdx index c3264f62ca..eb7a130644 100644 --- a/website/docs/search.mdx +++ b/website/docs/search.mdx @@ -127,6 +127,9 @@ export default { // Optional: whether the insights feature is enabled or not on Docsearch (`false` by default) insights: false, + // Optional: whether you want to use the new Ask AI feature (undefined by default) + askAi: 'YOUR_ALGOLIA_ASK_AI_ASSISTANT_ID', + //... other Algolia params }, // highlight-end @@ -214,6 +217,53 @@ If you only get search results when Contextual Search is disabled, this is very ::: +### Ask AI {#ask-ai} + +Ask AI is a new feature that allows you to ask questions about your documentation. + +Ask AI brings the power of AI to your documentation: + +- **Conversational search:** Users can ask questions in natural language and get context-aware answers. +- **Completely free:** Ask AI is available at no additional cost. You'll pay only for the LLM usage to your provider. +- **BYOLLM (Bring Your Own LLM):** You can use your own language model provider, giving you full control over the AI experience. +- **Direct Algolia index integration:** The provider/models retrieve relevant context directly from your Algolia index, ensuring accurate and up-to-date answers. +- **Recently asked & conversation history:** Easily revisit your recent questions and jump back into previous Ask AI conversations. +- **Seamless integration:** Ask AI is available directly from the search modal. + +To enable it, add an `askAi` field in your `algolia` config: + +```js title="docusaurus.config.js" +export default { + // ... + themeConfig: { + // ... + algolia: { + // highlight-start + askAi: 'YOUR_ALGOLIA_ASK_AI_ASSISTANT_ID', + // highlight-end + + // highlight-start + // OR with custom parameters + askAi: { + assistantId: 'YOUR_ALGOLIA_ASK_AI_ASSISTANT_ID', + indexName: 'YOUR_ALGOLIA_INDEX_NAME', + apiKey: 'YOUR_ALGOLIA_API_KEY', + appId: 'YOUR_ALGOLIA_APP_ID', + }, + // highlight-end + + //... other Algolia params + }, + }, +}; +``` + +:::info + +To use Ask AI, you need to have an Algolia index with the Ask AI assistant enabled. Learn more about [how to setup Ask AI](https://docsearch.algolia.com/docs/v4/askai). + +::: + ### Styling your Algolia search {#styling-your-algolia-search} By default, DocSearch comes with a fine-tuned theme that was designed for accessibility, making sure that colors and contrasts respect standards. diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index 7ed001e3e0..2f96f7ff39 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -655,6 +655,17 @@ export default async function createConfigAsync() { appId: 'X1Z85QJPUV', apiKey: 'bf7211c161e8205da2f933a02534105a', indexName: 'docusaurus-2', + + // TODO temporary, for DocSearch v3/v4 conditional Ask AI integration + // see https://github.com/facebook/docusaurus/pull/11327 + // eslint-disable-next-line @typescript-eslint/no-var-requires,global-require + ...(require('@docsearch/react').version.startsWith('4.') + ? { + // cSpell:ignore IMYF + askAi: 'RgIMYFUmTfrN', + } + : {}), + replaceSearchResultPathname: isDev || isDeployPreview ? { diff --git a/yarn.lock b/yarn.lock index 3d53a19683..b02878f9cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,153 +2,190 @@ # yarn lockfile v1 -"@algolia/autocomplete-core@1.17.9": - version "1.17.9" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.17.9.tgz#83374c47dc72482aa45d6b953e89377047f0dcdc" - integrity sha512-O7BxrpLDPJWWHv/DLA9DRFWs+iY1uOJZkqUwjS5HSZAGcl0hIVCQ97LTLewiZmZ402JYUrun+8NqFP+hCknlbQ== +"@ai-sdk/gateway@1.0.23": + version "1.0.23" + resolved "https://registry.yarnpkg.com/@ai-sdk/gateway/-/gateway-1.0.23.tgz#284a7de5bf7c9e80ac68416f19cf3644d7bb2db6" + integrity sha512-ynV7WxpRK2zWLGkdOtrU2hW22mBVkEYVS3iMg1+ZGmAYSgzCqzC74bfOJZ2GU1UdcrFWUsFI9qAYjsPkd+AebA== dependencies: - "@algolia/autocomplete-plugin-algolia-insights" "1.17.9" - "@algolia/autocomplete-shared" "1.17.9" + "@ai-sdk/provider" "2.0.0" + "@ai-sdk/provider-utils" "3.0.9" -"@algolia/autocomplete-plugin-algolia-insights@1.17.9": - version "1.17.9" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.9.tgz#74c86024d09d09e8bfa3dd90b844b77d9f9947b6" - integrity sha512-u1fEHkCbWF92DBeB/KHeMacsjsoI0wFhjZtlCq2ddZbAehshbZST6Hs0Avkc0s+4UyBGbMDnSuXHLuvRWK5iDQ== +"@ai-sdk/provider-utils@3.0.9": + version "3.0.9" + resolved "https://registry.yarnpkg.com/@ai-sdk/provider-utils/-/provider-utils-3.0.9.tgz#ac35a11eaafb5943a6c1bb024b4d2fdda6a8a0a3" + integrity sha512-Pm571x5efqaI4hf9yW4KsVlDBDme8++UepZRnq+kqVBWWjgvGhQlzU8glaFq0YJEB9kkxZHbRRyVeHoV2sRYaQ== dependencies: - "@algolia/autocomplete-shared" "1.17.9" + "@ai-sdk/provider" "2.0.0" + "@standard-schema/spec" "^1.0.0" + eventsource-parser "^3.0.5" -"@algolia/autocomplete-preset-algolia@1.17.9": - version "1.17.9" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.9.tgz#911f3250544eb8ea4096fcfb268f156b085321b5" - integrity sha512-Na1OuceSJeg8j7ZWn5ssMu/Ax3amtOwk76u4h5J4eK2Nx2KB5qt0Z4cOapCsxot9VcEN11ADV5aUSlQF4RhGjQ== +"@ai-sdk/provider@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@ai-sdk/provider/-/provider-2.0.0.tgz#b853c739d523b33675bc74b6c506b2c690bc602b" + integrity sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA== dependencies: - "@algolia/autocomplete-shared" "1.17.9" + json-schema "^0.4.0" -"@algolia/autocomplete-shared@1.17.9": - version "1.17.9" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.9.tgz#5f38868f7cb1d54b014b17a10fc4f7e79d427fa8" - integrity sha512-iDf05JDQ7I0b7JEA/9IektxN/80a2MZ1ToohfmNS3rfeuQnIKI3IJlIafD0xu4StbtQTghx9T3Maa97ytkXenQ== - -"@algolia/client-abtesting@5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.17.1.tgz#cd591627245e2a4f2a978e51df5507b62d74b664" - integrity sha512-Os/xkQbDp5A5RdGYq1yS3fF69GoBJH5FIfrkVh+fXxCSe714i1Xdl9XoXhS4xG76DGKm6EFMlUqP024qjps8cg== +"@ai-sdk/react@^2.0.30": + version "2.0.45" + resolved "https://registry.yarnpkg.com/@ai-sdk/react/-/react-2.0.45.tgz#ea368c59e0e200e6506c8f82abefaf8cf52833f3" + integrity sha512-jrTeBQpIsueV6EB/L6KNdH/yadK/Ehx1qCus+9RC29kRikVhjgj8xNvHfH3qHCwsfGqLX9ljj69dCRLrmzpvnw== dependencies: - "@algolia/client-common" "5.17.1" - "@algolia/requester-browser-xhr" "5.17.1" - "@algolia/requester-fetch" "5.17.1" - "@algolia/requester-node-http" "5.17.1" + "@ai-sdk/provider-utils" "3.0.9" + ai "5.0.45" + swr "^2.2.5" + throttleit "2.1.0" -"@algolia/client-analytics@5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.17.1.tgz#32d5670b2640a44415dd58fc4b65a032dcfb7c29" - integrity sha512-WKpGC+cUhmdm3wndIlTh8RJXoVabUH+4HrvZHC4hXtvCYojEXYeep8RZstatwSZ7Ocg6Y2u67bLw90NEINuYEw== +"@algolia/abtesting@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.3.0.tgz#3fade769bf5b03244baaee8034b83e2b49f8e86c" + integrity sha512-KqPVLdVNfoJzX5BKNGM9bsW8saHeyax8kmPFXul5gejrSPN3qss7PgsFH5mMem7oR8tvjvNkia97ljEYPYCN8Q== dependencies: - "@algolia/client-common" "5.17.1" - "@algolia/requester-browser-xhr" "5.17.1" - "@algolia/requester-fetch" "5.17.1" - "@algolia/requester-node-http" "5.17.1" + "@algolia/client-common" "5.37.0" + "@algolia/requester-browser-xhr" "5.37.0" + "@algolia/requester-fetch" "5.37.0" + "@algolia/requester-node-http" "5.37.0" -"@algolia/client-common@5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.17.1.tgz#9e75b4bfd510bf1fd39ec0abfb742958e6e2a144" - integrity sha512-5rb5+yPIie6912riAypTSyzbE23a7UM1UpESvD8GEPI4CcWQvA9DBlkRNx9qbq/nJ5pvv8VjZjUxJj7rFkzEAA== - -"@algolia/client-insights@5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.17.1.tgz#af6f5cbb97c35ab12b32872c6fb9f64d99234369" - integrity sha512-nb/tfwBMn209TzFv1DDTprBKt/wl5btHVKoAww9fdEVdoKK02R2KAqxe5tuXLdEzAsS+LevRyOM/YjXuLmPtjQ== +"@algolia/autocomplete-core@1.19.2": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.19.2.tgz#702df67a08cb3cfe8c33ee1111ef136ec1a9e232" + integrity sha512-mKv7RyuAzXvwmq+0XRK8HqZXt9iZ5Kkm2huLjgn5JoCPtDy+oh9yxUMfDDaVCw0oyzZ1isdJBc7l9nuCyyR7Nw== dependencies: - "@algolia/client-common" "5.17.1" - "@algolia/requester-browser-xhr" "5.17.1" - "@algolia/requester-fetch" "5.17.1" - "@algolia/requester-node-http" "5.17.1" + "@algolia/autocomplete-plugin-algolia-insights" "1.19.2" + "@algolia/autocomplete-shared" "1.19.2" -"@algolia/client-personalization@5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.17.1.tgz#4df4781347d7bd493403604841376fef3c79f80f" - integrity sha512-JuNlZe1SdW9KbV0gcgdsiVkFfXt0mmPassdS3cBSGvZGbPB9JsHthD719k5Y6YOY4dGvw1JmC1i9CwCQHAS8hg== +"@algolia/autocomplete-plugin-algolia-insights@1.19.2": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.2.tgz#3584b625b9317e333d1ae43664d02358e175c52d" + integrity sha512-TjxbcC/r4vwmnZaPwrHtkXNeqvlpdyR+oR9Wi2XyfORkiGkLTVhX2j+O9SaCCINbKoDfc+c2PB8NjfOnz7+oKg== dependencies: - "@algolia/client-common" "5.17.1" - "@algolia/requester-browser-xhr" "5.17.1" - "@algolia/requester-fetch" "5.17.1" - "@algolia/requester-node-http" "5.17.1" + "@algolia/autocomplete-shared" "1.19.2" -"@algolia/client-query-suggestions@5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.17.1.tgz#df3ceaada101f0265f08bf7911e0dd40d9b8f6e5" - integrity sha512-RBIFIv1QE3IlAikJKWTOpd6pwE4d2dY6t02iXH7r/SLXWn0HzJtsAPPeFg/OKkFvWAXt0H7In2/Mp7a1/Dy2pw== - dependencies: - "@algolia/client-common" "5.17.1" - "@algolia/requester-browser-xhr" "5.17.1" - "@algolia/requester-fetch" "5.17.1" - "@algolia/requester-node-http" "5.17.1" +"@algolia/autocomplete-shared@1.19.2": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.2.tgz#c0b7b8dc30a5c65b70501640e62b009535e4578f" + integrity sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w== -"@algolia/client-search@5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.17.1.tgz#ff5e699bfae2786f08557960a74afbfb94ba7930" - integrity sha512-bd5JBUOP71kPsxwDcvOxqtqXXVo/706NFifZ/O5Rx5GB8ZNVAhg4l7aGoT6jBvEfgmrp2fqPbkdIZ6JnuOpGcw== +"@algolia/client-abtesting@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.37.0.tgz#37df3674ccc37dfb0aa4cbfea42002bb136fb909" + integrity sha512-Dp2Zq+x9qQFnuiQhVe91EeaaPxWBhzwQ6QnznZQnH9C1/ei3dvtmAFfFeaTxM6FzfJXDLvVnaQagTYFTQz3R5g== dependencies: - "@algolia/client-common" "5.17.1" - "@algolia/requester-browser-xhr" "5.17.1" - "@algolia/requester-fetch" "5.17.1" - "@algolia/requester-node-http" "5.17.1" + "@algolia/client-common" "5.37.0" + "@algolia/requester-browser-xhr" "5.37.0" + "@algolia/requester-fetch" "5.37.0" + "@algolia/requester-node-http" "5.37.0" + +"@algolia/client-analytics@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.37.0.tgz#6fb4d748e1af43d8bc9f955d73d98205ce1c1ee5" + integrity sha512-wyXODDOluKogTuZxRII6mtqhAq4+qUR3zIUJEKTiHLe8HMZFxfUEI4NO2qSu04noXZHbv/sRVdQQqzKh12SZuQ== + dependencies: + "@algolia/client-common" "5.37.0" + "@algolia/requester-browser-xhr" "5.37.0" + "@algolia/requester-fetch" "5.37.0" + "@algolia/requester-node-http" "5.37.0" + +"@algolia/client-common@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.37.0.tgz#f7ca097c4bae44e4ea365ee8f420693d0005c98e" + integrity sha512-GylIFlPvLy9OMgFG8JkonIagv3zF+Dx3H401Uo2KpmfMVBBJiGfAb9oYfXtplpRMZnZPxF5FnkWaI/NpVJMC+g== + +"@algolia/client-insights@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.37.0.tgz#f4f4011fc89bc0b2dfc384acc3c6fb38f633f4ec" + integrity sha512-T63afO2O69XHKw2+F7mfRoIbmXWGzgpZxgOFAdP3fR4laid7pWBt20P4eJ+Zn23wXS5kC9P2K7Bo3+rVjqnYiw== + dependencies: + "@algolia/client-common" "5.37.0" + "@algolia/requester-browser-xhr" "5.37.0" + "@algolia/requester-fetch" "5.37.0" + "@algolia/requester-node-http" "5.37.0" + +"@algolia/client-personalization@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.37.0.tgz#c1688db681623b189f353599815a118033ceebb5" + integrity sha512-1zOIXM98O9zD8bYDCJiUJRC/qNUydGHK/zRK+WbLXrW1SqLFRXECsKZa5KoG166+o5q5upk96qguOtE8FTXDWQ== + dependencies: + "@algolia/client-common" "5.37.0" + "@algolia/requester-browser-xhr" "5.37.0" + "@algolia/requester-fetch" "5.37.0" + "@algolia/requester-node-http" "5.37.0" + +"@algolia/client-query-suggestions@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.37.0.tgz#fa514df8d36fb548258c712f3ba6f97eb84ebb87" + integrity sha512-31Nr2xOLBCYVal+OMZn1rp1H4lPs1914Tfr3a34wU/nsWJ+TB3vWjfkUUuuYhWoWBEArwuRzt3YNLn0F/KRVkg== + dependencies: + "@algolia/client-common" "5.37.0" + "@algolia/requester-browser-xhr" "5.37.0" + "@algolia/requester-fetch" "5.37.0" + "@algolia/requester-node-http" "5.37.0" + +"@algolia/client-search@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.37.0.tgz#38c7110d96fbbbda7b7fb0578a18b8cad3c25af2" + integrity sha512-DAFVUvEg+u7jUs6BZiVz9zdaUebYULPiQ4LM2R4n8Nujzyj7BZzGr2DCd85ip4p/cx7nAZWKM8pLcGtkTRTdsg== + dependencies: + "@algolia/client-common" "5.37.0" + "@algolia/requester-browser-xhr" "5.37.0" + "@algolia/requester-fetch" "5.37.0" + "@algolia/requester-node-http" "5.37.0" "@algolia/events@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== -"@algolia/ingestion@1.17.1": - version "1.17.1" - resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.17.1.tgz#e11cadca936a05f40d54f6ece5dc07d206e15048" - integrity sha512-T18tvePi1rjRYcIKhd82oRukrPWHxG/Iy1qFGaxCplgRm9Im5z96qnYOq75MSKGOUHkFxaBKJOLmtn8xDR+Mcw== +"@algolia/ingestion@1.37.0": + version "1.37.0" + resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.37.0.tgz#bb6016e656c68014050814abf130e103f977794e" + integrity sha512-pkCepBRRdcdd7dTLbFddnu886NyyxmhgqiRcHHaDunvX03Ij4WzvouWrQq7B7iYBjkMQrLS8wQqSP0REfA4W8g== dependencies: - "@algolia/client-common" "5.17.1" - "@algolia/requester-browser-xhr" "5.17.1" - "@algolia/requester-fetch" "5.17.1" - "@algolia/requester-node-http" "5.17.1" + "@algolia/client-common" "5.37.0" + "@algolia/requester-browser-xhr" "5.37.0" + "@algolia/requester-fetch" "5.37.0" + "@algolia/requester-node-http" "5.37.0" -"@algolia/monitoring@1.17.1": - version "1.17.1" - resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.17.1.tgz#c5fa1a0fe2bd07ed954e8925c7d8fb196bab427f" - integrity sha512-gDtow+AUywTehRP8S1tWKx2IvhcJOxldAoqBxzN3asuQobF7er5n72auBeL++HY4ImEuzMi7PDOA/Iuwxs2IcA== +"@algolia/monitoring@1.37.0": + version "1.37.0" + resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.37.0.tgz#6d20c220d648db8faea45679350f1516917cc13d" + integrity sha512-fNw7pVdyZAAQQCJf1cc/ih4fwrRdQSgKwgor4gchsI/Q/ss9inmC6bl/69jvoRSzgZS9BX4elwHKdo0EfTli3w== dependencies: - "@algolia/client-common" "5.17.1" - "@algolia/requester-browser-xhr" "5.17.1" - "@algolia/requester-fetch" "5.17.1" - "@algolia/requester-node-http" "5.17.1" + "@algolia/client-common" "5.37.0" + "@algolia/requester-browser-xhr" "5.37.0" + "@algolia/requester-fetch" "5.37.0" + "@algolia/requester-node-http" "5.37.0" -"@algolia/recommend@5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.17.1.tgz#42c296d39ba967c89410fb46b28721010bca59ec" - integrity sha512-2992tTHkRe18qmf5SP57N78kN1D3e5t4PO1rt10sJncWtXBZWiNOK6K/UcvWsFbNSGAogFcIcvIMAl5mNp6RWA== +"@algolia/recommend@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.37.0.tgz#dd5e814f30bbb92395902e120fdb28a120b91341" + integrity sha512-U+FL5gzN2ldx3TYfQO5OAta2TBuIdabEdFwD5UVfWPsZE5nvOKkc/6BBqP54Z/adW/34c5ZrvvZhlhNTZujJXQ== dependencies: - "@algolia/client-common" "5.17.1" - "@algolia/requester-browser-xhr" "5.17.1" - "@algolia/requester-fetch" "5.17.1" - "@algolia/requester-node-http" "5.17.1" + "@algolia/client-common" "5.37.0" + "@algolia/requester-browser-xhr" "5.37.0" + "@algolia/requester-fetch" "5.37.0" + "@algolia/requester-node-http" "5.37.0" -"@algolia/requester-browser-xhr@5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.17.1.tgz#e924954aa5c4f223be86ee38b2536959a7755560" - integrity sha512-XpKgBfyczVesKgr7DOShNyPPu5kqlboimRRPjdqAw5grSyHhCmb8yoTIKy0TCqBABZeXRPMYT13SMruUVRXvHA== +"@algolia/requester-browser-xhr@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.37.0.tgz#8851ab846d8005055c36a59422161ebe1594ae48" + integrity sha512-Ao8GZo8WgWFABrU7iq+JAftXV0t+UcOtCDL4mzHHZ+rQeTTf1TZssr4d0vIuoqkVNnKt9iyZ7T4lQff4ydcTrw== dependencies: - "@algolia/client-common" "5.17.1" + "@algolia/client-common" "5.37.0" -"@algolia/requester-fetch@5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.17.1.tgz#2d0385db7a08ce219325a001766065fa1e0d3c33" - integrity sha512-EhUomH+DZP5vb6DnEjT0GvXaXBSwzZnuU6hPGNU1EYKRXDouRjII/bIWpVjt7ycMgL2D2oQruqDh6rAWUhQwRw== +"@algolia/requester-fetch@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.37.0.tgz#93602fdc9a59b41ecd53768c53c11cddb0db846a" + integrity sha512-H7OJOXrFg5dLcGJ22uxx8eiFId0aB9b0UBhoOi4SMSuDBe6vjJJ/LeZyY25zPaSvkXNBN3vAM+ad6M0h6ha3AA== dependencies: - "@algolia/client-common" "5.17.1" + "@algolia/client-common" "5.37.0" -"@algolia/requester-node-http@5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.17.1.tgz#d42dcafb6784409252a27ee60055b4ce83ee2937" - integrity sha512-PSnENJtl4/wBWXlGyOODbLYm6lSiFqrtww7UpQRCJdsHXlJKF8XAP6AME8NxvbE0Qo/RJUxK0mvyEh9sQcx6bg== +"@algolia/requester-node-http@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.37.0.tgz#83da1b52f3ee86f262a5d4b2a88a74db665211c2" + integrity sha512-npZ9aeag4SGTx677eqPL3rkSPlQrnzx/8wNrl1P7GpWq9w/eTmRbOq+wKrJ2r78idlY0MMgmY/mld2tq6dc44g== dependencies: - "@algolia/client-common" "5.17.1" + "@algolia/client-common" "5.37.0" "@ampproject/remapping@^2.2.0": version "2.3.0" @@ -2040,20 +2077,23 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@docsearch/css@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.9.0.tgz#3bc29c96bf024350d73b0cfb7c2a7b71bf251cd5" - integrity sha512-cQbnVbq0rrBwNAKegIac/t6a8nWoUAn8frnkLFW6YARaRmAQr5/Eoe6Ln2fqkUCZ40KpdrKbpSAmgrkviOxuWA== +"@docsearch/css@4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.0.1.tgz#970436628cf03ba816ed6e4269cc866e9853bb0d" + integrity sha512-ouRI2SEwAg8qBqX4S3zfm4OJ/07o9Is7TzivNGkqP7FtYU4W0qgigumWkPbYvDwtG0koZw2ZebpcQiEpkCyv+g== -"@docsearch/react@^3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.9.0.tgz#d0842b700c3ee26696786f3c8ae9f10c1a3f0db3" - integrity sha512-mb5FOZYZIkRQ6s/NWnM98k879vu5pscWqTLubLFBO87igYYT4VzVazh4h5o/zCvTIZgEt3PvsCOMOswOUo9yHQ== +"@docsearch/react@^3.9.0", "@docsearch/react@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-4.0.1.tgz#337bc73a00e20036aa989af4c00869104195d672" + integrity sha512-X/0mSdAt2/8el0sTBpSQJM8XKRlCLmITaWYZf9gLLqiN3eXdglOtt3cH7RjTQDS75REwmhadKzQIjFF8mbmf+A== dependencies: - "@algolia/autocomplete-core" "1.17.9" - "@algolia/autocomplete-preset-algolia" "1.17.9" - "@docsearch/css" "3.9.0" - algoliasearch "^5.14.2" + "@ai-sdk/react" "^2.0.30" + "@algolia/autocomplete-core" "1.19.2" + "@docsearch/css" "4.0.1" + ai "^5.0.30" + algoliasearch "^5.28.0" + marked "^15.0.12" + zod "^4.1.8" "@docusaurus/responsive-loader@^1.7.0": version "1.7.0" @@ -3118,6 +3158,11 @@ dependencies: "@octokit/openapi-types" "^18.0.0" +"@opentelemetry/api@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" + integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== + "@parcel/watcher@2.0.4": version "2.0.4" resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.4.tgz#f300fef4cc38008ff4b8c29d92588eced3ce014b" @@ -3516,6 +3561,11 @@ resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA== +"@standard-schema/spec@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.0.0.tgz#f193b73dc316c4170f2e82a881da0f550d551b9c" + integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA== + "@surma/rollup-plugin-off-main-thread@^2.2.3": version "2.2.3" resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz#ee34985952ca21558ab0d952f00298ad2190c053" @@ -5144,6 +5194,16 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +ai@5.0.45, ai@^5.0.30: + version "5.0.45" + resolved "https://registry.yarnpkg.com/ai/-/ai-5.0.45.tgz#0e1472883914d2a031b1317cf53cc74891168a88" + integrity sha512-go6J78B1oTXZMN2XLlNJnrFxwcqXQtpPqUVyk1wvzvpb2dk5nP9yNuxqqOX9HrrKuf5U9M6rSezEJWr1eEG9RA== + dependencies: + "@ai-sdk/gateway" "1.0.23" + "@ai-sdk/provider" "2.0.0" + "@ai-sdk/provider-utils" "3.0.9" + "@opentelemetry/api" "1.9.0" + ajv-formats@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -5183,31 +5243,32 @@ ajv@^8.0.0, ajv@^8.0.1, ajv@^8.6.0, ajv@^8.9.0: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" -algoliasearch-helper@^3.22.6: - version "3.22.6" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.22.6.tgz#6a31c67d277a32f3f7ae1b8a6e57ca73f1e1a0b0" - integrity sha512-F2gSb43QHyvZmvH/2hxIjbk/uFdO2MguQYTFP7J+RowMW1csjIODMobEnpLI8nbLQuzZnGZdIxl5Bpy1k9+CFQ== +algoliasearch-helper@^3.26.0: + version "3.26.0" + resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.26.0.tgz#d6e283396a9fc5bf944f365dc3b712570314363f" + integrity sha512-Rv2x3GXleQ3ygwhkhJubhhYGsICmShLAiqtUuJTUkr9uOCOXyF2E71LVT4XDnVffbknv8XgScP4U0Oxtgm+hIw== dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^5.14.2, algoliasearch@^5.17.1: - version "5.17.1" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.17.1.tgz#8c8879dbf77ba38a3150d19ab8321c8d60b83035" - integrity sha512-3CcbT5yTWJDIcBe9ZHgsPi184SkT1kyZi3GWlQU5EFgvq1V73X2sqHRkPCQMe0RA/uvZbB+1sFeAk73eWygeLg== +algoliasearch@^5.28.0, algoliasearch@^5.37.0: + version "5.37.0" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.37.0.tgz#73dc4a09654e6e02b529300018d639706b95b47b" + integrity sha512-y7gau/ZOQDqoInTQp0IwTOjkrHc4Aq4R8JgpmCleFwiLl+PbN2DMWoDUWZnrK8AhNJwT++dn28Bt4NZYNLAmuA== dependencies: - "@algolia/client-abtesting" "5.17.1" - "@algolia/client-analytics" "5.17.1" - "@algolia/client-common" "5.17.1" - "@algolia/client-insights" "5.17.1" - "@algolia/client-personalization" "5.17.1" - "@algolia/client-query-suggestions" "5.17.1" - "@algolia/client-search" "5.17.1" - "@algolia/ingestion" "1.17.1" - "@algolia/monitoring" "1.17.1" - "@algolia/recommend" "5.17.1" - "@algolia/requester-browser-xhr" "5.17.1" - "@algolia/requester-fetch" "5.17.1" - "@algolia/requester-node-http" "5.17.1" + "@algolia/abtesting" "1.3.0" + "@algolia/client-abtesting" "5.37.0" + "@algolia/client-analytics" "5.37.0" + "@algolia/client-common" "5.37.0" + "@algolia/client-insights" "5.37.0" + "@algolia/client-personalization" "5.37.0" + "@algolia/client-query-suggestions" "5.37.0" + "@algolia/client-search" "5.37.0" + "@algolia/ingestion" "1.37.0" + "@algolia/monitoring" "1.37.0" + "@algolia/recommend" "5.37.0" + "@algolia/requester-browser-xhr" "5.37.0" + "@algolia/requester-fetch" "5.37.0" + "@algolia/requester-node-http" "5.37.0" ansi-align@^3.0.1: version "3.0.1" @@ -7773,7 +7834,7 @@ deprecation@^2.0.0, deprecation@^2.3.1: resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== -dequal@^2.0.0: +dequal@^2.0.0, dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== @@ -8714,6 +8775,11 @@ events@^3.2.0, events@^3.3.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +eventsource-parser@^3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.6.tgz#292e165e34cacbc936c3c92719ef326d4aeb4e90" + integrity sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg== + execa@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-5.0.0.tgz#4029b0007998a841fbd1032e5f4de86a3c1e3376" @@ -12243,10 +12309,10 @@ markdown-table@^3.0.0: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.3.tgz#e6331d30e493127e031dd385488b5bd326e4a6bd" integrity sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw== -marked@^15.0.7: - version "15.0.8" - resolved "https://registry.yarnpkg.com/marked/-/marked-15.0.8.tgz#39873a3fdf91a520111e48aeb2ef3746d58d7166" - integrity sha512-rli4l2LyZqpQuRve5C0rkn6pj3hT8EWPC+zkAxFTAJLxRbENfTAhEQq9itrmf1Y81QtAX5D/MYlGlIomNgj9lA== +marked@^15.0.12, marked@^15.0.7: + version "15.0.12" + resolved "https://registry.yarnpkg.com/marked/-/marked-15.0.12.tgz#30722c7346e12d0a2d0207ab9b0c4f0102d86c4e" + integrity sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA== math-intrinsics@^1.1.0: version "1.1.0" @@ -17420,6 +17486,14 @@ swc-loader@^0.2.6: dependencies: "@swc/counter" "^0.1.3" +swr@^2.2.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/swr/-/swr-2.3.6.tgz#5fee0ee8a0762a16871ee371075cb09422b64f50" + integrity sha512-wfHRmHWk/isGNMwlLGlZX5Gzz/uTgo0o2IRuTMcf4CPuPFJZlq0rDaKUx+ozB5nBOReNV1kiOyzMfj+MBMikLw== + dependencies: + dequal "^2.0.3" + use-sync-external-store "^1.4.0" + symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -17594,6 +17668,11 @@ thingies@^2.5.0: resolved "https://registry.yarnpkg.com/thingies/-/thingies-2.5.0.tgz#5f7b882c933b85989f8466b528a6247a6881e04f" integrity sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw== +throttleit@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-2.1.0.tgz#a7e4aa0bf4845a5bd10daa39ea0c783f631a07b4" + integrity sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw== + through2@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -18270,6 +18349,11 @@ use-editable@^2.3.3: resolved "https://registry.yarnpkg.com/use-editable/-/use-editable-2.3.3.tgz#a292fe9ba4c291cd28d1cc2728c75a5fc8d9a33f" integrity sha512-7wVD2JbfAFJ3DK0vITvXBdpd9JAz5BcKAAolsnLBuBn6UDDwBGuCIAGvR3yA2BNKm578vAMVHFCWaOcA+BhhiA== +use-sync-external-store@^1.4.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz#55122e2a3edd2a6c106174c27485e0fd59bcfca0" + integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A== + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -19179,9 +19263,14 @@ zod-validation-error@^3.0.3: integrity sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ== zod@^3.22.4: - version "3.24.2" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.2.tgz#8efa74126287c675e92f46871cfc8d15c34372b3" - integrity sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ== + version "3.25.76" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34" + integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== + +zod@^4.1.8: + version "4.1.9" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.9.tgz#c03a0ddb10f5578f13f8f70f1959f89fd09c1c06" + integrity sha512-HI32jTq0AUAC125z30E8bQNz0RQ+9Uc+4J7V97gLYjZVKRjeydPgGt6dvQzFrav7MYOUGFqqOGiHpA/fdbd0cQ== zwitch@^2.0.0, zwitch@^2.0.4: version "2.0.4" From 0bc6b6e394e8aac5a0ad451bc9ea8f7abe782a3b Mon Sep 17 00:00:00 2001 From: Akshat Sinha <113134119+akshatsinha0@users.noreply.github.com> Date: Mon, 22 Sep 2025 15:10:44 +0530 Subject: [PATCH 067/103] fix(website): showcase spelling mistake of the word docusaurus in user desc (#11417) --- website/src/data/users.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/data/users.tsx b/website/src/data/users.tsx index b742cd17e9..357989da69 100644 --- a/website/src/data/users.tsx +++ b/website/src/data/users.tsx @@ -158,7 +158,7 @@ const Users: User[] = [ }, { title: 'Blogasaurus', - description: 'A blog written using Docasaurus.', + description: 'A blog written using Docusaurus.', preview: require('./showcase/blogasaurus.png'), website: 'https://blog.palashsh.me/', source: 'https://github.com/BattleOfPlassey/blogasaurus', From 4dc05762ee5ad1a98c37d64b73948c79840cdd6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Tue, 23 Sep 2025 12:52:14 +0200 Subject: [PATCH 068/103] fix(theme): fix copy of indented code blocks, replace copy-text-to-clipboard by clipboard API (#11422) Co-authored-by: slorber <749374+slorber@users.noreply.github.com> --- packages/docusaurus-theme-classic/package.json | 1 - .../src/theme/CodeBlock/Buttons/CopyButton/index.tsx | 12 ++++++------ packages/docusaurus/src/webpack/base.ts | 12 +----------- project-words.txt | 2 +- yarn.lock | 5 ----- 5 files changed, 8 insertions(+), 24 deletions(-) diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index c2c887ef79..a21d1872ec 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -35,7 +35,6 @@ "@docusaurus/utils-validation": "3.8.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", - "copy-text-to-clipboard": "^3.2.0", "infima": "0.2.0-alpha.45", "lodash": "^4.17.21", "nprogress": "^0.2.0", diff --git a/packages/docusaurus-theme-classic/src/theme/CodeBlock/Buttons/CopyButton/index.tsx b/packages/docusaurus-theme-classic/src/theme/CodeBlock/Buttons/CopyButton/index.tsx index 0bc1001ff5..a094000298 100644 --- a/packages/docusaurus-theme-classic/src/theme/CodeBlock/Buttons/CopyButton/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/CodeBlock/Buttons/CopyButton/index.tsx @@ -13,7 +13,6 @@ import React, { type ReactNode, } from 'react'; import clsx from 'clsx'; -import copy from 'copy-text-to-clipboard'; import {translate} from '@docusaurus/Translate'; import {useCodeBlockContext} from '@docusaurus/theme-common/internal'; import Button from '@theme/CodeBlock/Buttons/Button'; @@ -53,11 +52,12 @@ function useCopyButton() { const copyTimeout = useRef(undefined); const copyCode = useCallback(() => { - copy(code); - setIsCopied(true); - copyTimeout.current = window.setTimeout(() => { - setIsCopied(false); - }, 1000); + navigator.clipboard.writeText(code).then(() => { + setIsCopied(true); + copyTimeout.current = window.setTimeout(() => { + setIsCopied(false); + }, 1000); + }); }, [code]); useEffect(() => () => window.clearTimeout(copyTimeout.current), []); diff --git a/packages/docusaurus/src/webpack/base.ts b/packages/docusaurus/src/webpack/base.ts index ed0b1f9fe5..1132cb4bb4 100644 --- a/packages/docusaurus/src/webpack/base.ts +++ b/packages/docusaurus/src/webpack/base.ts @@ -13,7 +13,6 @@ import { getCSSExtractPlugin, getMinimizers, } from '@docusaurus/bundler'; - import {getFileLoaderUtils, md5Hash} from '@docusaurus/utils'; import {loadDocusaurusAliases, loadThemeAliases} from './aliases'; import {BundlerCPUProfilerPlugin} from './plugins/BundlerCPUProfilerPlugin'; @@ -28,14 +27,6 @@ const CSS_REGEX = /\.css$/i; const CSS_MODULE_REGEX = /\.module\.css$/i; export const clientDir = path.join(__dirname, '..', 'client'); -const LibrariesToTranspile = [ - 'copy-text-to-clipboard', // Contains optional catch binding, incompatible with recent versions of Edge -]; - -const LibrariesToTranspileRegex = new RegExp( - LibrariesToTranspile.map((libName) => `(node_modules/${libName})`).join('|'), -); - function getReactAliases(siteDir: string): Record { // Escape hatch if (process.env.DOCUSAURUS_NO_REACT_ALIASES) { @@ -58,8 +49,7 @@ export function excludeJS(modulePath: string): boolean { // Don't transpile node_modules except any docusaurus npm package return ( modulePath.includes('node_modules') && - !/docusaurus(?:(?!node_modules).)*\.jsx?$/.test(modulePath) && - !LibrariesToTranspileRegex.test(modulePath) + !/docusaurus(?:(?!node_modules).)*\.jsx?$/.test(modulePath) ); } diff --git a/project-words.txt b/project-words.txt index 84ab6efecc..091a09bf97 100644 --- a/project-words.txt +++ b/project-words.txt @@ -27,6 +27,7 @@ Blockquotes blockquotes Bokmål bunx +BYOLLM caabernathy Candillon cdabcdab @@ -367,4 +368,3 @@ Zhou zoomable zpao ödingers -BYOLLM diff --git a/yarn.lock b/yarn.lock index b02878f9cd..caf9d6667d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6813,11 +6813,6 @@ cookie@~0.4.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== -copy-text-to-clipboard@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz#0202b2d9bdae30a49a53f898626dcc3b49ad960b" - integrity sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q== - copy-webpack-plugin@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" From 50ca86aa04a17980c78fa0342b38c40b3a4ef548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Tue, 23 Sep 2025 14:58:23 +0200 Subject: [PATCH 069/103] feat(theme): Add theme-tabs-container stable className (#11426) --- .../docusaurus-theme-classic/src/theme/Tabs/index.tsx | 10 +++++++++- .../src/utils/ThemeClassNames.ts | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx b/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx index ff8dd40bb3..878744add0 100644 --- a/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx @@ -7,6 +7,7 @@ import React, {cloneElement, type ReactElement, type ReactNode} from 'react'; import clsx from 'clsx'; +import {ThemeClassNames} from '@docusaurus/theme-common'; import { useScrollPositionBlocker, useTabs, @@ -143,7 +144,14 @@ function TabContent({ function TabsComponent(props: Props): ReactNode { const tabs = useTabs(props); return ( -
    +
    diff --git a/packages/docusaurus-theme-common/src/utils/ThemeClassNames.ts b/packages/docusaurus-theme-common/src/utils/ThemeClassNames.ts index a0a1834d1c..a414908d88 100644 --- a/packages/docusaurus-theme-common/src/utils/ThemeClassNames.ts +++ b/packages/docusaurus-theme-common/src/utils/ThemeClassNames.ts @@ -55,6 +55,10 @@ export const ThemeClassNames = { container: 'theme-announcement-bar', }, + tabs: { + container: 'theme-tabs-container', + }, + layout: { navbar: { container: 'theme-layout-navbar', From 70f6312c0dc36b962c94ea2c5e5ff88863b09e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Tue, 23 Sep 2025 15:08:02 +0200 Subject: [PATCH 070/103] feat(blog): Add support for email social icon + resize default social icon a bit (#11425) --- .../src/__tests__/authorsSocials.test.ts | 7 +++++ .../src/authorsSocials.ts | 8 ++++-- .../src/theme-classic.d.ts | 8 ++++++ .../Blog/Components/Author/Socials/index.tsx | 4 ++- .../src/theme/Icon/Socials/Default/index.tsx | 12 ++++---- .../src/theme/Icon/Socials/Email/index.tsx | 28 +++++++++++++++++++ .../2024-07-03-multiple-authors.mdx | 1 + website/_dogfooding/_blog tests/authors.yml | 1 + .../docs/api/plugins/plugin-content-blog.mdx | 3 +- website/docs/blog.mdx | 2 ++ 10 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 packages/docusaurus-theme-classic/src/theme/Icon/Socials/Email/index.tsx diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/authorsSocials.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/authorsSocials.test.ts index 9bc8afaf2c..ecbc3ea12a 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/authorsSocials.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/authorsSocials.test.ts @@ -21,11 +21,13 @@ describe('normalizeSocials', () => { twitch: 'gingergeek', youtube: 'gingergeekuk', mastodon: 'Mastodon', + email: 'seb@example.com', }; expect(normalizeSocials(socials)).toMatchInlineSnapshot(` { "bluesky": "https://bsky.app/profile/gingergeek.co.uk", + "email": "mailto:seb@example.com", "github": "https://github.com/ozakione", "instagram": "https://www.instagram.com/thisweekinreact", "linkedin": "https://www.linkedin.com/in/ozakione/", @@ -48,11 +50,13 @@ describe('normalizeSocials', () => { instaGRam: 'thisweekinreact', BLUESKY: 'gingergeek.co.uk', tHrEaDs: 'gingergeekuk', + eMAil: 'seb@example.com', }; expect(normalizeSocials(socials)).toMatchInlineSnapshot(` { "bluesky": "https://bsky.app/profile/gingergeek.co.uk", + "email": "mailto:seb@example.com", "github": "https://github.com/ozakione", "instagram": "https://www.instagram.com/thisweekinreact", "linkedin": "https://www.linkedin.com/in/ozakione/", @@ -69,6 +73,7 @@ describe('normalizeSocials', () => { linkedin: 'https://linkedin.com/ozakione', github: 'https://github.com/ozakione', stackoverflow: 'https://stackoverflow.com/ozakione', + email: 'mailto:seb@example.com', }; expect(normalizeSocials(socials)).toEqual(socials); @@ -81,10 +86,12 @@ describe('normalizeSocials', () => { github: 'https://github.com/ozakione', stackoverflow: 'https://stackoverflow.com/ozakione', mastodon: 'https://hachyderm.io/@hachyderm', + email: 'mailto:seb@example.com', }; expect(normalizeSocials(socials)).toMatchInlineSnapshot(` { + "email": "mailto:seb@example.com", "github": "https://github.com/ozakione", "linkedin": "https://www.linkedin.com/in/ozakione/", "mastodon": "https://hachyderm.io/@hachyderm", diff --git a/packages/docusaurus-plugin-content-blog/src/authorsSocials.ts b/packages/docusaurus-plugin-content-blog/src/authorsSocials.ts index 80bb3c5864..1517381e06 100644 --- a/packages/docusaurus-plugin-content-blog/src/authorsSocials.ts +++ b/packages/docusaurus-plugin-content-blog/src/authorsSocials.ts @@ -27,6 +27,7 @@ export const AuthorSocialsSchema = Joi.object({ mastodon: Joi.string(), twitch: Joi.string(), youtube: Joi.string(), + email: Joi.string(), }).unknown(); type PredefinedPlatformNormalizer = (value: string) => string; @@ -47,12 +48,12 @@ const PredefinedPlatformNormalizers: Record< mastodon: (handle: string) => `https://mastodon.social/@${handle}`, // can be in format user@other.server and it will redirect if needed twitch: (handle: string) => `https://twitch.tv/${handle}`, youtube: (handle: string) => `https://youtube.com/@${handle}`, // https://support.google.com/youtube/answer/6180214?hl=en + email: (email: string) => `mailto:${email}`, }; type SocialEntry = [string, string]; function normalizeSocialEntry([platform, value]: SocialEntry): SocialEntry { - const normalizer = PredefinedPlatformNormalizers[platform.toLowerCase()]; if (typeof value !== 'string') { throw new Error( `Author socials should be usernames/userIds/handles, or fully qualified HTTP(s) absolute URLs. @@ -60,7 +61,9 @@ Social platform '${platform}' has illegal value '${value}'`, ); } const isAbsoluteUrl = - value.startsWith('http://') || value.startsWith('https://'); + value.startsWith('http://') || + value.startsWith('https://') || + value.startsWith('mailto:'); if (isAbsoluteUrl) { return [platform, value]; } else if (value.includes('/')) { @@ -69,6 +72,7 @@ Social platform '${platform}' has illegal value '${value}'`, Social platform '${platform}' has illegal value '${value}'`, ); } + const normalizer = PredefinedPlatformNormalizers[platform.toLowerCase()]; if (normalizer && !isAbsoluteUrl) { const normalizedPlatform = platform.toLowerCase(); const normalizedValue = normalizer(value); diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index c801c97e79..c38431f8b7 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -1894,6 +1894,14 @@ declare module '@theme/Icon/Socials/Twitch' { export default function Twitch(props: Props): ReactNode; } +declare module '@theme/Icon/Socials/Email' { + import type {ComponentProps, ReactNode} from 'react'; + + export interface Props extends ComponentProps<'svg'> {} + + export default function Email(props: Props): ReactNode; +} + declare module '@theme/Icon/Socials/Mastodon' { import type {ComponentProps, ReactNode} from 'react'; diff --git a/packages/docusaurus-theme-classic/src/theme/Blog/Components/Author/Socials/index.tsx b/packages/docusaurus-theme-classic/src/theme/Blog/Components/Author/Socials/index.tsx index 1ba60c5ae7..e163a603de 100644 --- a/packages/docusaurus-theme-classic/src/theme/Blog/Components/Author/Socials/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Blog/Components/Author/Socials/index.tsx @@ -23,6 +23,7 @@ import Threads from '@theme/Icon/Socials/Threads'; import Youtube from '@theme/Icon/Socials/YouTube'; import Mastodon from '@theme/Icon/Socials/Mastodon'; import Twitch from '@theme/Icon/Socials/Twitch'; +import Email from '@theme/Icon/Socials/Email'; import styles from './styles.module.css'; @@ -42,6 +43,7 @@ const SocialPlatformConfigs: Record = { mastodon: {Icon: Mastodon, label: 'Mastodon'}, youtube: {Icon: Youtube, label: 'YouTube'}, twitch: {Icon: Twitch, label: 'Twitch'}, + email: {Icon: Email, label: 'Email'}, }; function getSocialPlatformConfig(platformKey: string): SocialPlatformConfig { @@ -57,7 +59,7 @@ function SocialLink({platform, link}: {platform: string; link: string}) { const {Icon, label} = getSocialPlatformConfig(platform); return ( - + ); } diff --git a/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Default/index.tsx b/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Default/index.tsx index 29f676caa9..b66fd118e9 100644 --- a/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Default/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Default/index.tsx @@ -7,7 +7,7 @@ import type {ReactNode, SVGProps} from 'react'; -// SVG Source: https://tabler.io/ +// SVG Source: https://github.com/tabler/tabler-icons function DefaultSocial(props: SVGProps): ReactNode { return ( ): ReactNode { strokeLinejoin="round" {...props}> - - - - - + + + + + ); } diff --git a/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Email/index.tsx b/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Email/index.tsx new file mode 100644 index 0000000000..b44991aa8b --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/Icon/Socials/Email/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 type {ReactNode, SVGProps} from 'react'; + +// SVG Source: https://github.com/tabler/tabler-icons +function Email(props: SVGProps): ReactNode { + return ( + + + + + + ); +} +export default Email; diff --git a/website/_dogfooding/_blog tests/2024-07-03-multiple-authors.mdx b/website/_dogfooding/_blog tests/2024-07-03-multiple-authors.mdx index b13b5215bd..59446635e7 100644 --- a/website/_dogfooding/_blog tests/2024-07-03-multiple-authors.mdx +++ b/website/_dogfooding/_blog tests/2024-07-03-multiple-authors.mdx @@ -11,6 +11,7 @@ authors: linkedin: https://www.linkedin.com/in/sebastienlorber/ instagram: https://www.instagram.com/thisweekinreact/ newsletter: https://thisweekinreact.com/newsletter + email: seb@example.com - name: Sébastien Lorber imageURL: https://github.com/slorber.png socials: diff --git a/website/_dogfooding/_blog tests/authors.yml b/website/_dogfooding/_blog tests/authors.yml index a7dac6a959..987c70a2c9 100644 --- a/website/_dogfooding/_blog tests/authors.yml +++ b/website/_dogfooding/_blog tests/authors.yml @@ -6,6 +6,7 @@ slorber: page: true socials: x: sebastienlorber + email: seb@example.com ozaki: name: ozaki diff --git a/website/docs/api/plugins/plugin-content-blog.mdx b/website/docs/api/plugins/plugin-content-blog.mdx index 8dee6fdcda..f8a17e4347 100644 --- a/website/docs/api/plugins/plugin-content-blog.mdx +++ b/website/docs/api/plugins/plugin-content-blog.mdx @@ -281,7 +281,7 @@ type AuthorKey = string; // Social platform name -> Social platform link // Example: {MyPlatform: 'https://myplatform.com/myusername'} // Pre-defined platforms -// ("x", "github", "twitter", "linkedin", "stackoverflow", "instagram", "bluesky", "mastodon", "threads", "twitch", "youtube") accept handles: +// ("x", "github", "twitter", "linkedin", "stackoverflow", "instagram", "bluesky", "mastodon", "threads", "twitch", "youtube", "email") accept handles: // Example: {github: 'slorber'} type AuthorSocials = Record; @@ -368,6 +368,7 @@ slorber: socials: x: sebastienlorber github: slorber + email: seb@example.com jmarcey: name: Joel Marcey diff --git a/website/docs/blog.mdx b/website/docs/blog.mdx index aec3c7b3a9..92a9551150 100644 --- a/website/docs/blog.mdx +++ b/website/docs/blog.mdx @@ -62,6 +62,7 @@ authors: socials: x: sebastienlorber github: slorber + email: seb@example.com tags: [hello, docusaurus-v2] image: https://i.imgur.com/mErPwqL.png hide_table_of_contents: false @@ -303,6 +304,7 @@ slorber: socials: x: sebastienlorber github: slorber + email: seb@example.com ``` :::tip From 422f5d91efd013b429c4e7fdb462f2fc530d5dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 25 Sep 2025 16:11:12 +0200 Subject: [PATCH 071/103] feat(theme-search-algolia): use DocSearch v4.1, optimize integration (#11421) Co-authored-by: slorber <749374+slorber@users.noreply.github.com> --- package.json | 3 - .../package.json | 2 +- .../src/client/useAlgoliaAskAi.ts | 10 +- .../src/docSearchVersion.ts | 12 + .../src/index.ts | 21 ++ .../src/theme-search-algolia.d.ts | 5 + .../src/theme/SearchBar/index.tsx | 7 +- .../src/validateThemeConfig.ts | 5 +- website/docusaurus.config.ts | 3 +- yarn.lock | 291 +++++++++--------- 10 files changed, 200 insertions(+), 159 deletions(-) create mode 100644 packages/docusaurus-theme-search-algolia/src/docSearchVersion.ts diff --git a/package.json b/package.json index 342345f82d..0e9d63abf9 100644 --- a/package.json +++ b/package.json @@ -129,8 +129,5 @@ "stylelint-config-standard": "^29.0.0", "typescript": "~5.8.2" }, - "resolutions": { - "@docsearch/react": "^4.0.1" - }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/packages/docusaurus-theme-search-algolia/package.json b/packages/docusaurus-theme-search-algolia/package.json index 25362274ab..b2832d1dc7 100644 --- a/packages/docusaurus-theme-search-algolia/package.json +++ b/packages/docusaurus-theme-search-algolia/package.json @@ -33,7 +33,7 @@ "copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch" }, "dependencies": { - "@docsearch/react": "^3.9.0", + "@docsearch/react": "^3.9.0 || ^4.1.0", "@docusaurus/core": "3.8.1", "@docusaurus/logger": "3.8.1", "@docusaurus/plugin-content-docs": "3.8.1", diff --git a/packages/docusaurus-theme-search-algolia/src/client/useAlgoliaAskAi.ts b/packages/docusaurus-theme-search-algolia/src/client/useAlgoliaAskAi.ts index ec80891fc6..071f50c98b 100644 --- a/packages/docusaurus-theme-search-algolia/src/client/useAlgoliaAskAi.ts +++ b/packages/docusaurus-theme-search-algolia/src/client/useAlgoliaAskAi.ts @@ -6,15 +6,15 @@ */ import {useCallback, useMemo, useState} from 'react'; -import { - version as docsearchVersion, - type DocSearchModalProps, - type DocSearchTranslations, -} from '@docsearch/react'; +import {version as docsearchVersion} from '@docsearch/react/version'; import translations from '@theme/SearchTranslations'; import {useAlgoliaContextualFacetFiltersIfEnabled} from './useAlgoliaContextualFacetFilters'; import {mergeFacetFilters} from './utils'; import type {AskAiConfig} from '@docusaurus/theme-search-algolia'; +import type { + DocSearchModalProps, + DocSearchTranslations, +} from '@docsearch/react'; import type {FacetFilters} from 'algoliasearch/lite'; // The minimal props the hook needs from DocSearch v4 props diff --git a/packages/docusaurus-theme-search-algolia/src/docSearchVersion.ts b/packages/docusaurus-theme-search-algolia/src/docSearchVersion.ts new file mode 100644 index 0000000000..1509af0c5f --- /dev/null +++ b/packages/docusaurus-theme-search-algolia/src/docSearchVersion.ts @@ -0,0 +1,12 @@ +/** + * 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 {version as docSearchVersion} from '@docsearch/react'; + +// TODO Docusaurus v4: upgrade to DocSearch v4 +// drop v3 compat, remove this file? +export const docSearchV3: boolean = docSearchVersion.startsWith('3.'); diff --git a/packages/docusaurus-theme-search-algolia/src/index.ts b/packages/docusaurus-theme-search-algolia/src/index.ts index f7fb8bdc32..1dd935115b 100644 --- a/packages/docusaurus-theme-search-algolia/src/index.ts +++ b/packages/docusaurus-theme-search-algolia/src/index.ts @@ -12,6 +12,7 @@ import { createOpenSearchHeadTags, shouldCreateOpenSearchFile, } from './opensearch'; +import {docSearchV3} from './docSearchVersion'; import type {LoadContext, Plugin} from '@docusaurus/types'; import type {ThemeConfig} from '@docusaurus/theme-search-algolia'; @@ -65,6 +66,26 @@ export default function themeSearchAlgolia(context: LoadContext): Plugin { } return {}; }, + + configureWebpack() { + // TODO Docusaurus v4: remove after dropping DocSearch v3 support + if (docSearchV3) { + // These aliases ensure DocSearch v3 imports are compatible with + // the newly added DocSearch v4 entry points + // See https://github.com/algolia/docsearch/pull/2764 + const docSearchV3Entry = require.resolve('@docsearch/react'); + return { + resolve: { + alias: { + '@docsearch/react/version': docSearchV3Entry, + '@docsearch/react/useDocSearchKeyboardEvents': docSearchV3Entry, + '@docsearch/react/useTheme': docSearchV3Entry, + }, + }, + }; + } + return undefined; + }, }; } diff --git a/packages/docusaurus-theme-search-algolia/src/theme-search-algolia.d.ts b/packages/docusaurus-theme-search-algolia/src/theme-search-algolia.d.ts index b5e8a26bc3..076a93eab3 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme-search-algolia.d.ts +++ b/packages/docusaurus-theme-search-algolia/src/theme-search-algolia.d.ts @@ -5,6 +5,11 @@ * LICENSE file in the root directory of this source tree. */ +// TODO Docusaurus v4: remove after we drop support for DocSearch v3 +declare module '@docsearch/react/button'; +declare module '@docsearch/react/useDocSearchKeyboardEvents'; +declare module '@docsearch/react/version'; + declare module '@docusaurus/theme-search-algolia' { import type {DeepPartial, Overwrite} from 'utility-types'; diff --git a/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx b/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx index 11f38a8ae1..e7cc5f7340 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx +++ b/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx @@ -13,7 +13,8 @@ import React, { type ReactNode, } from 'react'; import {createPortal} from 'react-dom'; -import {DocSearchButton, useDocSearchKeyboardEvents} from '@docsearch/react'; +import {DocSearchButton} from '@docsearch/react/button'; +import {useDocSearchKeyboardEvents} from '@docsearch/react/useDocSearchKeyboardEvents'; import Head from '@docusaurus/Head'; import Link from '@docusaurus/Link'; import {useHistory} from '@docusaurus/router'; @@ -73,9 +74,7 @@ function importDocSearchModalIfNeeded() { return Promise.resolve(); } return Promise.all([ - import('@docsearch/react/modal') as Promise< - typeof import('@docsearch/react') - >, + import('@docsearch/react/modal'), import('@docsearch/react/style'), import('./styles.css'), ]).then(([{DocSearchModal: Modal}]) => { diff --git a/packages/docusaurus-theme-search-algolia/src/validateThemeConfig.ts b/packages/docusaurus-theme-search-algolia/src/validateThemeConfig.ts index 01a3bec255..6f623e3032 100644 --- a/packages/docusaurus-theme-search-algolia/src/validateThemeConfig.ts +++ b/packages/docusaurus-theme-search-algolia/src/validateThemeConfig.ts @@ -7,7 +7,7 @@ import {escapeRegexp} from '@docusaurus/utils'; import {Joi} from '@docusaurus/utils-validation'; -import {version as docsearchVersion} from '@docsearch/react'; +import {docSearchV3} from './docSearchVersion'; import type {ThemeConfigValidationContext} from '@docusaurus/types'; import type { ThemeConfig, @@ -123,9 +123,10 @@ export const Schema = Joi.object({ .unknown(), }); +// TODO Docusaurus v4: remove this check when we drop DocSearch v3 function ensureAskAISupported(themeConfig: ThemeConfig) { // enforce DocsSearch v4 requirement when AskAI is configured - if (themeConfig.algolia.askAi && !docsearchVersion.startsWith('4.')) { + if (themeConfig.algolia.askAi && docSearchV3) { throw new Error( 'The askAi feature is only supported in DocSearch v4. ' + 'Please upgrade to DocSearch v4 by installing "@docsearch/react": "^4.0.0" ' + diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index 2f96f7ff39..89852250ba 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -656,7 +656,8 @@ export default async function createConfigAsync() { apiKey: 'bf7211c161e8205da2f933a02534105a', indexName: 'docusaurus-2', - // TODO temporary, for DocSearch v3/v4 conditional Ask AI integration + // TODO Docusaurus v4: remove after we drop DocSearch v3 + // temporary, for DocSearch v3/v4 conditional Ask AI integration // see https://github.com/facebook/docusaurus/pull/11327 // eslint-disable-next-line @typescript-eslint/no-var-requires,global-require ...(require('@docsearch/react').version.startsWith('4.') diff --git a/yarn.lock b/yarn.lock index caf9d6667d..afe8bc01c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@ai-sdk/gateway@1.0.23": - version "1.0.23" - resolved "https://registry.yarnpkg.com/@ai-sdk/gateway/-/gateway-1.0.23.tgz#284a7de5bf7c9e80ac68416f19cf3644d7bb2db6" - integrity sha512-ynV7WxpRK2zWLGkdOtrU2hW22mBVkEYVS3iMg1+ZGmAYSgzCqzC74bfOJZ2GU1UdcrFWUsFI9qAYjsPkd+AebA== +"@ai-sdk/gateway@1.0.29": + version "1.0.29" + resolved "https://registry.yarnpkg.com/@ai-sdk/gateway/-/gateway-1.0.29.tgz#b7e902c2d7139e2ca2a94cb6076febe517088fa0" + integrity sha512-o9LtmBiG2WAgs3GAmL79F8idan/UupxHG8Tyr2gP4aUSOzflM0bsvfzozBp8x6WatQnOx+Pio7YNw45Y6I16iw== dependencies: "@ai-sdk/provider" "2.0.0" "@ai-sdk/provider-utils" "3.0.9" @@ -27,24 +27,24 @@ json-schema "^0.4.0" "@ai-sdk/react@^2.0.30": - version "2.0.45" - resolved "https://registry.yarnpkg.com/@ai-sdk/react/-/react-2.0.45.tgz#ea368c59e0e200e6506c8f82abefaf8cf52833f3" - integrity sha512-jrTeBQpIsueV6EB/L6KNdH/yadK/Ehx1qCus+9RC29kRikVhjgj8xNvHfH3qHCwsfGqLX9ljj69dCRLrmzpvnw== + version "2.0.52" + resolved "https://registry.yarnpkg.com/@ai-sdk/react/-/react-2.0.52.tgz#851f1c2136b1c3d14bf8cb6f58dd87ea3d171946" + integrity sha512-4/i40pykN4gTGH264+k1g4tMGdw4xN7vZ1qESFCIm/lhS/8YiJPYheBOk9c349hytOT1sGxp3UNPcOWzWS0H2A== dependencies: "@ai-sdk/provider-utils" "3.0.9" - ai "5.0.45" + ai "5.0.52" swr "^2.2.5" throttleit "2.1.0" -"@algolia/abtesting@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.3.0.tgz#3fade769bf5b03244baaee8034b83e2b49f8e86c" - integrity sha512-KqPVLdVNfoJzX5BKNGM9bsW8saHeyax8kmPFXul5gejrSPN3qss7PgsFH5mMem7oR8tvjvNkia97ljEYPYCN8Q== +"@algolia/abtesting@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.4.0.tgz#d607790222f4ce9d183cc535fccc3bf7849318db" + integrity sha512-N0blWT/C0KOZ/OJ9GXBX66odJZlrYjMj3M+01y8ob1mjBFnBaBo7gOCyHBDQy60+H4pJXp3pSGlJOqJIueBH+A== dependencies: - "@algolia/client-common" "5.37.0" - "@algolia/requester-browser-xhr" "5.37.0" - "@algolia/requester-fetch" "5.37.0" - "@algolia/requester-node-http" "5.37.0" + "@algolia/client-common" "5.38.0" + "@algolia/requester-browser-xhr" "5.38.0" + "@algolia/requester-fetch" "5.38.0" + "@algolia/requester-node-http" "5.38.0" "@algolia/autocomplete-core@1.19.2": version "1.19.2" @@ -66,126 +66,126 @@ resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.2.tgz#c0b7b8dc30a5c65b70501640e62b009535e4578f" integrity sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w== -"@algolia/client-abtesting@5.37.0": - version "5.37.0" - resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.37.0.tgz#37df3674ccc37dfb0aa4cbfea42002bb136fb909" - integrity sha512-Dp2Zq+x9qQFnuiQhVe91EeaaPxWBhzwQ6QnznZQnH9C1/ei3dvtmAFfFeaTxM6FzfJXDLvVnaQagTYFTQz3R5g== +"@algolia/client-abtesting@5.38.0": + version "5.38.0" + resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.38.0.tgz#3362d7aa3c6732f800665d3e24e98eb9046779d1" + integrity sha512-15d6zv8vtj2l9pnnp/EH7Rhq3/snCCHRz56NnX6xIUPrbJl5gCsIYXAz8C2IEkwOpoDb0r5G6ArY2gKdVMNezw== dependencies: - "@algolia/client-common" "5.37.0" - "@algolia/requester-browser-xhr" "5.37.0" - "@algolia/requester-fetch" "5.37.0" - "@algolia/requester-node-http" "5.37.0" + "@algolia/client-common" "5.38.0" + "@algolia/requester-browser-xhr" "5.38.0" + "@algolia/requester-fetch" "5.38.0" + "@algolia/requester-node-http" "5.38.0" -"@algolia/client-analytics@5.37.0": - version "5.37.0" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.37.0.tgz#6fb4d748e1af43d8bc9f955d73d98205ce1c1ee5" - integrity sha512-wyXODDOluKogTuZxRII6mtqhAq4+qUR3zIUJEKTiHLe8HMZFxfUEI4NO2qSu04noXZHbv/sRVdQQqzKh12SZuQ== +"@algolia/client-analytics@5.38.0": + version "5.38.0" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.38.0.tgz#711a199f207a692e9e3d7ed28df99729743e8f1b" + integrity sha512-jJIbYAhYvTG3+gEAP5Q5Dp6PFJfUR+atz5rsqm5KjAKK+faLFdHJbM2IbOo0xdyGd+SH259MzfQKLJ9mZZ27dQ== dependencies: - "@algolia/client-common" "5.37.0" - "@algolia/requester-browser-xhr" "5.37.0" - "@algolia/requester-fetch" "5.37.0" - "@algolia/requester-node-http" "5.37.0" + "@algolia/client-common" "5.38.0" + "@algolia/requester-browser-xhr" "5.38.0" + "@algolia/requester-fetch" "5.38.0" + "@algolia/requester-node-http" "5.38.0" -"@algolia/client-common@5.37.0": - version "5.37.0" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.37.0.tgz#f7ca097c4bae44e4ea365ee8f420693d0005c98e" - integrity sha512-GylIFlPvLy9OMgFG8JkonIagv3zF+Dx3H401Uo2KpmfMVBBJiGfAb9oYfXtplpRMZnZPxF5FnkWaI/NpVJMC+g== +"@algolia/client-common@5.38.0": + version "5.38.0" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.38.0.tgz#f17f03822d377f6980aa5ff389c607bcb57fee42" + integrity sha512-aMCXzVPGJTeQnVU3Sdf30TfMN2+QyWcjfPTCCHyqVVgjPipb6RnK40aISGoO+rlYjh9LunDsNVFLwv+JEIF8bQ== -"@algolia/client-insights@5.37.0": - version "5.37.0" - resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.37.0.tgz#f4f4011fc89bc0b2dfc384acc3c6fb38f633f4ec" - integrity sha512-T63afO2O69XHKw2+F7mfRoIbmXWGzgpZxgOFAdP3fR4laid7pWBt20P4eJ+Zn23wXS5kC9P2K7Bo3+rVjqnYiw== +"@algolia/client-insights@5.38.0": + version "5.38.0" + resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.38.0.tgz#22a7f9be1990492693cb5f30a6e221a84acdbd6f" + integrity sha512-4c3FbpMiJX+VcaAj0rYaQdTLS/CkrdOn4hW+5y1plPov7KC7iSHai/VBbirmHuAfW1hVPCIh1w/4erKKTKuo+Q== dependencies: - "@algolia/client-common" "5.37.0" - "@algolia/requester-browser-xhr" "5.37.0" - "@algolia/requester-fetch" "5.37.0" - "@algolia/requester-node-http" "5.37.0" + "@algolia/client-common" "5.38.0" + "@algolia/requester-browser-xhr" "5.38.0" + "@algolia/requester-fetch" "5.38.0" + "@algolia/requester-node-http" "5.38.0" -"@algolia/client-personalization@5.37.0": - version "5.37.0" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.37.0.tgz#c1688db681623b189f353599815a118033ceebb5" - integrity sha512-1zOIXM98O9zD8bYDCJiUJRC/qNUydGHK/zRK+WbLXrW1SqLFRXECsKZa5KoG166+o5q5upk96qguOtE8FTXDWQ== +"@algolia/client-personalization@5.38.0": + version "5.38.0" + resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.38.0.tgz#9e73041c2499ca2c296b09e5c26753ae7a1247d7" + integrity sha512-FzLs6c8TBL4FSgNfnH2NL7O33ktecGiaKO4ZFG51QYORUzD5d6YwB9UBteaIYu/sgFoEdY57diYU4vyBH8R6iA== dependencies: - "@algolia/client-common" "5.37.0" - "@algolia/requester-browser-xhr" "5.37.0" - "@algolia/requester-fetch" "5.37.0" - "@algolia/requester-node-http" "5.37.0" + "@algolia/client-common" "5.38.0" + "@algolia/requester-browser-xhr" "5.38.0" + "@algolia/requester-fetch" "5.38.0" + "@algolia/requester-node-http" "5.38.0" -"@algolia/client-query-suggestions@5.37.0": - version "5.37.0" - resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.37.0.tgz#fa514df8d36fb548258c712f3ba6f97eb84ebb87" - integrity sha512-31Nr2xOLBCYVal+OMZn1rp1H4lPs1914Tfr3a34wU/nsWJ+TB3vWjfkUUuuYhWoWBEArwuRzt3YNLn0F/KRVkg== +"@algolia/client-query-suggestions@5.38.0": + version "5.38.0" + resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.38.0.tgz#8a212c86416763dfeb21316ac2a23c6a29851c8f" + integrity sha512-7apiahlgZLvOqrh0+hAYAp/UWjqz6AfSJrCwnsoQNzgIT09dLSPIKREelkuQeUrKy38vHWWpSQE3M0zWSp/YrA== dependencies: - "@algolia/client-common" "5.37.0" - "@algolia/requester-browser-xhr" "5.37.0" - "@algolia/requester-fetch" "5.37.0" - "@algolia/requester-node-http" "5.37.0" + "@algolia/client-common" "5.38.0" + "@algolia/requester-browser-xhr" "5.38.0" + "@algolia/requester-fetch" "5.38.0" + "@algolia/requester-node-http" "5.38.0" -"@algolia/client-search@5.37.0": - version "5.37.0" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.37.0.tgz#38c7110d96fbbbda7b7fb0578a18b8cad3c25af2" - integrity sha512-DAFVUvEg+u7jUs6BZiVz9zdaUebYULPiQ4LM2R4n8Nujzyj7BZzGr2DCd85ip4p/cx7nAZWKM8pLcGtkTRTdsg== +"@algolia/client-search@5.38.0": + version "5.38.0" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.38.0.tgz#ec10e2105d7c0fa8c4ee7b1e4b9b7fb5117bf165" + integrity sha512-PTAFMJOpVtJweExEYYgdmSCC6n4V/R+ctDL3fRQy77ulZM/p+zMLIQC9c7HCQE1zqpauvVck3f2zYSejaUTtrw== dependencies: - "@algolia/client-common" "5.37.0" - "@algolia/requester-browser-xhr" "5.37.0" - "@algolia/requester-fetch" "5.37.0" - "@algolia/requester-node-http" "5.37.0" + "@algolia/client-common" "5.38.0" + "@algolia/requester-browser-xhr" "5.38.0" + "@algolia/requester-fetch" "5.38.0" + "@algolia/requester-node-http" "5.38.0" "@algolia/events@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== -"@algolia/ingestion@1.37.0": - version "1.37.0" - resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.37.0.tgz#bb6016e656c68014050814abf130e103f977794e" - integrity sha512-pkCepBRRdcdd7dTLbFddnu886NyyxmhgqiRcHHaDunvX03Ij4WzvouWrQq7B7iYBjkMQrLS8wQqSP0REfA4W8g== +"@algolia/ingestion@1.38.0": + version "1.38.0" + resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.38.0.tgz#bb34e09d8852d3257f8f83be7303136ea23ae66a" + integrity sha512-qGSUGgceJHGyJLZ06bFLwVe2Tpf9KwabmoBjFvFscVmMmU5scKya6voCYd9bdX7V0Xy1qya9MGbmTm4zlLuveQ== dependencies: - "@algolia/client-common" "5.37.0" - "@algolia/requester-browser-xhr" "5.37.0" - "@algolia/requester-fetch" "5.37.0" - "@algolia/requester-node-http" "5.37.0" + "@algolia/client-common" "5.38.0" + "@algolia/requester-browser-xhr" "5.38.0" + "@algolia/requester-fetch" "5.38.0" + "@algolia/requester-node-http" "5.38.0" -"@algolia/monitoring@1.37.0": - version "1.37.0" - resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.37.0.tgz#6d20c220d648db8faea45679350f1516917cc13d" - integrity sha512-fNw7pVdyZAAQQCJf1cc/ih4fwrRdQSgKwgor4gchsI/Q/ss9inmC6bl/69jvoRSzgZS9BX4elwHKdo0EfTli3w== +"@algolia/monitoring@1.38.0": + version "1.38.0" + resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.38.0.tgz#5e89d1a9e62a97c213efeb28d0aa89c3870fe700" + integrity sha512-VnCtAUcHirvv/dDHg9jK1Z5oo4QOC5FKDxe40x8qloru2qDcjueT34jiAsB0gRos3VWf9v4iPSYTqMIFOcADpQ== dependencies: - "@algolia/client-common" "5.37.0" - "@algolia/requester-browser-xhr" "5.37.0" - "@algolia/requester-fetch" "5.37.0" - "@algolia/requester-node-http" "5.37.0" + "@algolia/client-common" "5.38.0" + "@algolia/requester-browser-xhr" "5.38.0" + "@algolia/requester-fetch" "5.38.0" + "@algolia/requester-node-http" "5.38.0" -"@algolia/recommend@5.37.0": - version "5.37.0" - resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.37.0.tgz#dd5e814f30bbb92395902e120fdb28a120b91341" - integrity sha512-U+FL5gzN2ldx3TYfQO5OAta2TBuIdabEdFwD5UVfWPsZE5nvOKkc/6BBqP54Z/adW/34c5ZrvvZhlhNTZujJXQ== +"@algolia/recommend@5.38.0": + version "5.38.0" + resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.38.0.tgz#0db13cfde331091fd02dc086775ca0dd7313abf8" + integrity sha512-fqgeU9GqxQorFUeGP4et1MyY28ccf9PCeciHwDPSbPYYiTqBItHdUIiytsNpjC5Dnc0RWtuXWCltLwSw9wN/bQ== dependencies: - "@algolia/client-common" "5.37.0" - "@algolia/requester-browser-xhr" "5.37.0" - "@algolia/requester-fetch" "5.37.0" - "@algolia/requester-node-http" "5.37.0" + "@algolia/client-common" "5.38.0" + "@algolia/requester-browser-xhr" "5.38.0" + "@algolia/requester-fetch" "5.38.0" + "@algolia/requester-node-http" "5.38.0" -"@algolia/requester-browser-xhr@5.37.0": - version "5.37.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.37.0.tgz#8851ab846d8005055c36a59422161ebe1594ae48" - integrity sha512-Ao8GZo8WgWFABrU7iq+JAftXV0t+UcOtCDL4mzHHZ+rQeTTf1TZssr4d0vIuoqkVNnKt9iyZ7T4lQff4ydcTrw== +"@algolia/requester-browser-xhr@5.38.0": + version "5.38.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.38.0.tgz#10ad28e7d282afa3b875185fa3dd08c43f8cbb74" + integrity sha512-nAUKbv4YQIXbpPi02AQvSPisD5FDDbT8XeYSh9HFoYP0Z3IpBLLDg7R4ahPvzd7gGsVKgEbXzRPWESXSji5yIg== dependencies: - "@algolia/client-common" "5.37.0" + "@algolia/client-common" "5.38.0" -"@algolia/requester-fetch@5.37.0": - version "5.37.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.37.0.tgz#93602fdc9a59b41ecd53768c53c11cddb0db846a" - integrity sha512-H7OJOXrFg5dLcGJ22uxx8eiFId0aB9b0UBhoOi4SMSuDBe6vjJJ/LeZyY25zPaSvkXNBN3vAM+ad6M0h6ha3AA== +"@algolia/requester-fetch@5.38.0": + version "5.38.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.38.0.tgz#7d6d189d918c4b39c715cd42798ae496825202ce" + integrity sha512-bkuAHaadC6OxJd3SVyQQnU1oJ9G/zdCqua7fwr1tJDrA/v7KzeS5np4/m6BuRUpTgVgFZHSewGnMcgj9DLBoaQ== dependencies: - "@algolia/client-common" "5.37.0" + "@algolia/client-common" "5.38.0" -"@algolia/requester-node-http@5.37.0": - version "5.37.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.37.0.tgz#83da1b52f3ee86f262a5d4b2a88a74db665211c2" - integrity sha512-npZ9aeag4SGTx677eqPL3rkSPlQrnzx/8wNrl1P7GpWq9w/eTmRbOq+wKrJ2r78idlY0MMgmY/mld2tq6dc44g== +"@algolia/requester-node-http@5.38.0": + version "5.38.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.38.0.tgz#29ebeb651fc5264c8b2b97c2a2998840520ca7f9" + integrity sha512-yHDKZTnMPR3/4bY0CVC1/uRnnbAaJ+pctRuX7G/HflBkKOrnUBDEGtQQHzEfMz2FHZ/tbCL+Q9r6mvwTSGp8nw== dependencies: - "@algolia/client-common" "5.37.0" + "@algolia/client-common" "5.38.0" "@ampproject/remapping@^2.2.0": version "2.3.0" @@ -2077,22 +2077,22 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@docsearch/css@4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.0.1.tgz#970436628cf03ba816ed6e4269cc866e9853bb0d" - integrity sha512-ouRI2SEwAg8qBqX4S3zfm4OJ/07o9Is7TzivNGkqP7FtYU4W0qgigumWkPbYvDwtG0koZw2ZebpcQiEpkCyv+g== +"@docsearch/css@4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.1.0.tgz#e156e011539d73624b2354dc8be8e96ac9be9ddc" + integrity sha512-nuNKGjHj/FQeWgE9t+i83QD/V67QiaAmGY7xS9TVCRUiCqSljOgIKlsLoQZKKVwEG8f+OWKdznzZkJxGZ7d06A== -"@docsearch/react@^3.9.0", "@docsearch/react@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-4.0.1.tgz#337bc73a00e20036aa989af4c00869104195d672" - integrity sha512-X/0mSdAt2/8el0sTBpSQJM8XKRlCLmITaWYZf9gLLqiN3eXdglOtt3cH7RjTQDS75REwmhadKzQIjFF8mbmf+A== +"@docsearch/react@^3.9.0 || ^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-4.1.0.tgz#a04f22324067f2e39dbe12f0e1247e7e0341d26d" + integrity sha512-4GHI7TT3sJZ2Vs4Kjadv7vAkMrTsJqHvzvxO3JA7UT8iPRKaDottG5o5uNshPWhVVaBYPC35Ukf8bfCotGpjSg== dependencies: "@ai-sdk/react" "^2.0.30" "@algolia/autocomplete-core" "1.19.2" - "@docsearch/css" "4.0.1" + "@docsearch/css" "4.1.0" ai "^5.0.30" algoliasearch "^5.28.0" - marked "^15.0.12" + marked "^16.3.0" zod "^4.1.8" "@docusaurus/responsive-loader@^1.7.0": @@ -5194,12 +5194,12 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ai@5.0.45, ai@^5.0.30: - version "5.0.45" - resolved "https://registry.yarnpkg.com/ai/-/ai-5.0.45.tgz#0e1472883914d2a031b1317cf53cc74891168a88" - integrity sha512-go6J78B1oTXZMN2XLlNJnrFxwcqXQtpPqUVyk1wvzvpb2dk5nP9yNuxqqOX9HrrKuf5U9M6rSezEJWr1eEG9RA== +ai@5.0.52, ai@^5.0.30: + version "5.0.52" + resolved "https://registry.yarnpkg.com/ai/-/ai-5.0.52.tgz#3aa9a6eab56505db2c94ce7a16a7ea089760977e" + integrity sha512-GLlRHjMlvN9+w7UYGxCpUQ8GgCRv5Z+JCprRH3Q8YbXJ/JyIc6EP9+YRUmQsyExX/qQsuehe7y/LLygarbSTOw== dependencies: - "@ai-sdk/gateway" "1.0.23" + "@ai-sdk/gateway" "1.0.29" "@ai-sdk/provider" "2.0.0" "@ai-sdk/provider-utils" "3.0.9" "@opentelemetry/api" "1.9.0" @@ -5251,24 +5251,24 @@ algoliasearch-helper@^3.26.0: "@algolia/events" "^4.0.1" algoliasearch@^5.28.0, algoliasearch@^5.37.0: - version "5.37.0" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.37.0.tgz#73dc4a09654e6e02b529300018d639706b95b47b" - integrity sha512-y7gau/ZOQDqoInTQp0IwTOjkrHc4Aq4R8JgpmCleFwiLl+PbN2DMWoDUWZnrK8AhNJwT++dn28Bt4NZYNLAmuA== + version "5.38.0" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.38.0.tgz#43615d81c493ca4a4efd74edb93910b2e71c91e1" + integrity sha512-8VJKIzheeI9cjuVJhU1hYEVetOTe7LvA+CujAI7yqvYsPtZfVEvv1pg9AeFNtHBg/ZoSLGU5LPijhcY5l3Ea9g== dependencies: - "@algolia/abtesting" "1.3.0" - "@algolia/client-abtesting" "5.37.0" - "@algolia/client-analytics" "5.37.0" - "@algolia/client-common" "5.37.0" - "@algolia/client-insights" "5.37.0" - "@algolia/client-personalization" "5.37.0" - "@algolia/client-query-suggestions" "5.37.0" - "@algolia/client-search" "5.37.0" - "@algolia/ingestion" "1.37.0" - "@algolia/monitoring" "1.37.0" - "@algolia/recommend" "5.37.0" - "@algolia/requester-browser-xhr" "5.37.0" - "@algolia/requester-fetch" "5.37.0" - "@algolia/requester-node-http" "5.37.0" + "@algolia/abtesting" "1.4.0" + "@algolia/client-abtesting" "5.38.0" + "@algolia/client-analytics" "5.38.0" + "@algolia/client-common" "5.38.0" + "@algolia/client-insights" "5.38.0" + "@algolia/client-personalization" "5.38.0" + "@algolia/client-query-suggestions" "5.38.0" + "@algolia/client-search" "5.38.0" + "@algolia/ingestion" "1.38.0" + "@algolia/monitoring" "1.38.0" + "@algolia/recommend" "5.38.0" + "@algolia/requester-browser-xhr" "5.38.0" + "@algolia/requester-fetch" "5.38.0" + "@algolia/requester-node-http" "5.38.0" ansi-align@^3.0.1: version "3.0.1" @@ -12304,11 +12304,16 @@ markdown-table@^3.0.0: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.3.tgz#e6331d30e493127e031dd385488b5bd326e4a6bd" integrity sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw== -marked@^15.0.12, marked@^15.0.7: +marked@^15.0.7: version "15.0.12" resolved "https://registry.yarnpkg.com/marked/-/marked-15.0.12.tgz#30722c7346e12d0a2d0207ab9b0c4f0102d86c4e" integrity sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA== +marked@^16.3.0: + version "16.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-16.3.0.tgz#2f513891f867d6edc4772b4a026db9cc331eb94f" + integrity sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w== + math-intrinsics@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" @@ -19263,9 +19268,9 @@ zod@^3.22.4: integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== zod@^4.1.8: - version "4.1.9" - resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.9.tgz#c03a0ddb10f5578f13f8f70f1959f89fd09c1c06" - integrity sha512-HI32jTq0AUAC125z30E8bQNz0RQ+9Uc+4J7V97gLYjZVKRjeydPgGt6dvQzFrav7MYOUGFqqOGiHpA/fdbd0cQ== + version "4.1.11" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.11.tgz#4aab62f76cfd45e6c6166519ba31b2ea019f75f5" + integrity sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg== zwitch@^2.0.0, zwitch@^2.0.4: version "2.0.4" From c24d7dc86a7c213a039e03c60e20ddd98e02e711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 25 Sep 2025 17:56:37 +0200 Subject: [PATCH 072/103] chore: release v3.9 (#11419) Co-authored-by: slorber <749374+slorber@users.noreply.github.com> --- CHANGELOG.md | 117 ++ admin/new.docusaurus.io/package.json | 2 +- admin/test-bad-package/package.json | 2 +- argos/package.json | 2 +- lerna.json | 2 +- packages/create-docusaurus/package.json | 6 +- .../templates/classic-typescript/package.json | 12 +- .../templates/classic/package.json | 10 +- packages/docusaurus-babel/package.json | 6 +- packages/docusaurus-bundler/package.json | 12 +- .../docusaurus-cssnano-preset/package.json | 2 +- packages/docusaurus-faster/package.json | 4 +- packages/docusaurus-logger/package.json | 2 +- packages/docusaurus-mdx-loader/package.json | 10 +- .../package.json | 4 +- .../package.json | 14 +- .../package.json | 18 +- .../package.json | 20 +- .../package.json | 12 +- .../package.json | 10 +- packages/docusaurus-plugin-debug/package.json | 8 +- .../package.json | 8 +- .../package.json | 8 +- .../package.json | 8 +- .../package.json | 14 +- packages/docusaurus-plugin-pwa/package.json | 20 +- .../docusaurus-plugin-rsdoctor/package.json | 8 +- .../docusaurus-plugin-sitemap/package.json | 14 +- packages/docusaurus-plugin-svgr/package.json | 10 +- .../package.json | 12 +- .../docusaurus-preset-classic/package.json | 32 +- .../package.json | 2 +- .../docusaurus-theme-classic/package.json | 28 +- packages/docusaurus-theme-common/package.json | 14 +- .../package.json | 12 +- .../docusaurus-theme-mermaid/package.json | 16 +- .../package.json | 18 +- .../package.json | 10 +- packages/docusaurus-tsconfig/package.json | 2 +- packages/docusaurus-types/package.json | 2 +- packages/docusaurus-utils-common/package.json | 4 +- .../docusaurus-utils-validation/package.json | 8 +- packages/docusaurus-utils/package.json | 8 +- packages/docusaurus/package.json | 20 +- packages/eslint-plugin/package.json | 2 +- packages/lqip-loader/package.json | 4 +- packages/stylelint-copyright/package.json | 2 +- project-words.txt | 1 + website/blog/releases/3.9/img/askai.png | Bin 0 -> 194259 bytes website/blog/releases/3.9/img/social-card.png | Bin 0 -> 191976 bytes website/blog/releases/3.9/index.mdx | 158 +++ website/docusaurus.config.ts | 1 + website/package.json | 34 +- .../version-3.9.0/advanced/architecture.mdx | 28 + .../version-3.9.0/advanced/client.mdx | 184 +++ .../version-3.9.0/advanced/index.mdx | 11 + .../version-3.9.0/advanced/plugins.mdx | 129 ++ .../version-3.9.0/advanced/routing.mdx | 289 ++++ .../version-3.9.0/advanced/ssg.mdx | 218 +++ .../api/docusaurus.config.js.mdx | 841 +++++++++++ .../version-3.9.0/api/misc/_category_.yml | 2 + .../api/misc/create-docusaurus.mdx | 58 + .../api/misc/eslint-plugin/README.mdx | 74 + .../api/misc/eslint-plugin/no-html-links.mdx | 47 + .../eslint-plugin/no-untranslated-text.mdx | 54 + .../prefer-docusaurus-heading.mdx | 31 + .../string-literal-i18n-messages.mdx | 50 + .../version-3.9.0/api/misc/logger/demo.png | Bin 0 -> 94456 bytes .../version-3.9.0/api/misc/logger/logger.mdx | 71 + .../api/plugin-methods/README.mdx | 144 ++ .../api/plugin-methods/_category_.yml | 2 + .../plugin-methods/extend-infrastructure.mdx | 132 ++ .../api/plugin-methods/i18n-lifecycles.mdx | 121 ++ .../api/plugin-methods/lifecycle-apis.mdx | 493 +++++++ .../api/plugin-methods/static-methods.mdx | 83 ++ .../version-3.9.0/api/plugins/_category_.yml | 5 + .../_partial-tags-file-api-ref-section.mdx | 54 + .../version-3.9.0/api/plugins/overview.mdx | 34 + .../api/plugins/plugin-client-redirects.mdx | 127 ++ .../api/plugins/plugin-content-blog.mdx | 419 ++++++ .../api/plugins/plugin-content-docs.mdx | 376 +++++ .../api/plugins/plugin-content-pages.mdx | 160 +++ .../api/plugins/plugin-css-cascade-layers.mdx | 95 ++ .../api/plugins/plugin-debug.mdx | 108 ++ .../api/plugins/plugin-google-analytics.mdx | 77 + .../api/plugins/plugin-google-gtag.mdx | 73 + .../api/plugins/plugin-google-tag-manager.mdx | 71 + .../api/plugins/plugin-ideal-image.mdx | 106 ++ .../version-3.9.0/api/plugins/plugin-pwa.mdx | 303 ++++ .../api/plugins/plugin-rsdoctor.mdx | 57 + .../api/plugins/plugin-sitemap.mdx | 110 ++ .../version-3.9.0/api/plugins/plugin-svgr.mdx | 55 + .../api/plugins/plugin-vercel-analytics.mdx | 57 + .../version-3.9.0/api/themes/_category_.yml | 5 + .../version-3.9.0/api/themes/overview.mdx | 34 + .../api/themes/theme-classic.mdx | 63 + .../api/themes/theme-configuration.mdx | 1239 +++++++++++++++++ .../api/themes/theme-live-codeblock.mdx | 29 + .../api/themes/theme-mermaid.mdx | 25 + .../api/themes/theme-search-algolia.mdx | 20 + .../docusaurus-asset-example-banner.png | Bin 0 -> 69264 bytes .../assets/docusaurus-asset-example.docx | Bin 0 -> 6114 bytes .../assets/docusaurus-asset-example.xyz | Bin 0 -> 125786 bytes website/versioned_docs/version-3.9.0/blog.mdx | 783 +++++++++++ .../version-3.9.0/browser-support.mdx | 106 ++ website/versioned_docs/version-3.9.0/cli.mdx | 190 +++ .../version-3.9.0/configuration.mdx | 294 ++++ .../version-3.9.0/deployment.mdx | 939 +++++++++++++ .../version-3.9.0/docusaurus-core.mdx | 770 ++++++++++ .../version-3.9.0/guides/creating-pages.mdx | 140 ++ .../guides/docs/docs-create-doc.mdx | 202 +++ .../guides/docs/docs-introduction.mdx | 120 ++ .../guides/docs/docs-multi-instance.mdx | 213 +++ .../guides/docs/sidebar/autogenerated.mdx | 497 +++++++ .../guides/docs/sidebar/index.mdx | 254 ++++ .../guides/docs/sidebar/items.mdx | 626 +++++++++ .../guides/docs/sidebar/multiple-sidebars.mdx | 143 ++ .../version-3.9.0/guides/docs/versioning.mdx | 375 +++++ .../_markdown-partial-example.mdx | 3 + .../markdown-features-admonitions.mdx | 372 +++++ .../markdown-features-assets.mdx | 235 ++++ .../markdown-features-code-blocks.mdx | 864 ++++++++++++ .../markdown-features-diagrams.mdx | 134 ++ .../markdown-features-head-metadata.mdx | 82 ++ .../markdown-features-intro.mdx | 235 ++++ .../markdown-features-links.mdx | 56 + .../markdown-features-math-equations.mdx | 204 +++ .../markdown-features-plugins.mdx | 247 ++++ .../markdown-features-react.mdx | 373 +++++ .../markdown-features-react.module.css | 17 + .../markdown-features-tabs-styles.module.css | 30 + .../markdown-features-tabs.mdx | 378 +++++ .../markdown-features-toc.mdx | 283 ++++ .../version-3.9.0/guides/whats-next.mdx | 21 + .../version-3.9.0/i18n/i18n-crowdin.mdx | 523 +++++++ .../version-3.9.0/i18n/i18n-git.mdx | 181 +++ .../version-3.9.0/i18n/i18n-introduction.mdx | 137 ++ .../version-3.9.0/i18n/i18n-tutorial.mdx | 564 ++++++++ .../version-3.9.0/installation.mdx | 194 +++ .../version-3.9.0/introduction.mdx | 200 +++ .../version-3.9.0/migration/index.mdx | 52 + .../migration/v2/migration-automated.mdx | 75 + .../migration/v2/migration-manual.mdx | 634 +++++++++ .../migration/v2/migration-overview.mdx | 105 ++ .../v2/migration-translated-sites.mdx | 167 +++ .../v2/migration-versioned-sites.mdx | 176 +++ .../version-3.9.0/migration/v3.mdx | 1026 ++++++++++++++ .../version-3.9.0/playground.mdx | 24 + .../versioned_docs/version-3.9.0/search.mdx | 427 ++++++ website/versioned_docs/version-3.9.0/seo.mdx | 220 +++ .../version-3.9.0/static-assets.mdx | 109 ++ .../version-3.9.0/styling-layout.mdx | 313 +++++ .../version-3.9.0/swizzling.mdx | 334 +++++ .../version-3.9.0/typescript-support.mdx | 140 ++ .../version-3.9.0/using-plugins.mdx | 310 +++++ .../version-3.9.0-sidebars.json | 162 +++ website/versions.json | 1 + 157 files changed, 22540 insertions(+), 239 deletions(-) create mode 100644 website/blog/releases/3.9/img/askai.png create mode 100644 website/blog/releases/3.9/img/social-card.png create mode 100644 website/blog/releases/3.9/index.mdx create mode 100644 website/versioned_docs/version-3.9.0/advanced/architecture.mdx create mode 100644 website/versioned_docs/version-3.9.0/advanced/client.mdx create mode 100644 website/versioned_docs/version-3.9.0/advanced/index.mdx create mode 100644 website/versioned_docs/version-3.9.0/advanced/plugins.mdx create mode 100644 website/versioned_docs/version-3.9.0/advanced/routing.mdx create mode 100644 website/versioned_docs/version-3.9.0/advanced/ssg.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/docusaurus.config.js.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/misc/_category_.yml create mode 100644 website/versioned_docs/version-3.9.0/api/misc/create-docusaurus.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/README.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/no-html-links.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/no-untranslated-text.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/prefer-docusaurus-heading.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/string-literal-i18n-messages.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/misc/logger/demo.png create mode 100644 website/versioned_docs/version-3.9.0/api/misc/logger/logger.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugin-methods/README.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugin-methods/_category_.yml create mode 100644 website/versioned_docs/version-3.9.0/api/plugin-methods/extend-infrastructure.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugin-methods/i18n-lifecycles.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugin-methods/lifecycle-apis.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugin-methods/static-methods.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/_category_.yml create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/_partial-tags-file-api-ref-section.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/overview.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-client-redirects.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-content-blog.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-content-docs.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-content-pages.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-css-cascade-layers.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-debug.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-google-analytics.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-google-gtag.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-google-tag-manager.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-ideal-image.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-pwa.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-rsdoctor.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-sitemap.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-svgr.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/plugins/plugin-vercel-analytics.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/themes/_category_.yml create mode 100644 website/versioned_docs/version-3.9.0/api/themes/overview.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/themes/theme-classic.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/themes/theme-configuration.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/themes/theme-live-codeblock.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/themes/theme-mermaid.mdx create mode 100644 website/versioned_docs/version-3.9.0/api/themes/theme-search-algolia.mdx create mode 100644 website/versioned_docs/version-3.9.0/assets/docusaurus-asset-example-banner.png create mode 100644 website/versioned_docs/version-3.9.0/assets/docusaurus-asset-example.docx create mode 100644 website/versioned_docs/version-3.9.0/assets/docusaurus-asset-example.xyz create mode 100644 website/versioned_docs/version-3.9.0/blog.mdx create mode 100644 website/versioned_docs/version-3.9.0/browser-support.mdx create mode 100644 website/versioned_docs/version-3.9.0/cli.mdx create mode 100644 website/versioned_docs/version-3.9.0/configuration.mdx create mode 100644 website/versioned_docs/version-3.9.0/deployment.mdx create mode 100644 website/versioned_docs/version-3.9.0/docusaurus-core.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/creating-pages.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/docs/docs-create-doc.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/docs/docs-introduction.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/docs/docs-multi-instance.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/docs/sidebar/autogenerated.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/docs/sidebar/index.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/docs/sidebar/items.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/docs/sidebar/multiple-sidebars.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/docs/versioning.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/_markdown-partial-example.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-admonitions.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-assets.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-code-blocks.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-diagrams.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-head-metadata.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-intro.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-links.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-math-equations.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-plugins.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-react.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-react.module.css create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-tabs-styles.module.css create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-tabs.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-toc.mdx create mode 100644 website/versioned_docs/version-3.9.0/guides/whats-next.mdx create mode 100644 website/versioned_docs/version-3.9.0/i18n/i18n-crowdin.mdx create mode 100644 website/versioned_docs/version-3.9.0/i18n/i18n-git.mdx create mode 100644 website/versioned_docs/version-3.9.0/i18n/i18n-introduction.mdx create mode 100644 website/versioned_docs/version-3.9.0/i18n/i18n-tutorial.mdx create mode 100644 website/versioned_docs/version-3.9.0/installation.mdx create mode 100644 website/versioned_docs/version-3.9.0/introduction.mdx create mode 100644 website/versioned_docs/version-3.9.0/migration/index.mdx create mode 100644 website/versioned_docs/version-3.9.0/migration/v2/migration-automated.mdx create mode 100644 website/versioned_docs/version-3.9.0/migration/v2/migration-manual.mdx create mode 100644 website/versioned_docs/version-3.9.0/migration/v2/migration-overview.mdx create mode 100644 website/versioned_docs/version-3.9.0/migration/v2/migration-translated-sites.mdx create mode 100644 website/versioned_docs/version-3.9.0/migration/v2/migration-versioned-sites.mdx create mode 100644 website/versioned_docs/version-3.9.0/migration/v3.mdx create mode 100644 website/versioned_docs/version-3.9.0/playground.mdx create mode 100644 website/versioned_docs/version-3.9.0/search.mdx create mode 100644 website/versioned_docs/version-3.9.0/seo.mdx create mode 100644 website/versioned_docs/version-3.9.0/static-assets.mdx create mode 100644 website/versioned_docs/version-3.9.0/styling-layout.mdx create mode 100644 website/versioned_docs/version-3.9.0/swizzling.mdx create mode 100644 website/versioned_docs/version-3.9.0/typescript-support.mdx create mode 100644 website/versioned_docs/version-3.9.0/using-plugins.mdx create mode 100644 website/versioned_sidebars/version-3.9.0-sidebars.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 59c365d070..970adeb021 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,122 @@ # Docusaurus Changelog +## 3.9.0 (2025-09-25) + +#### :rocket: New Feature + +- `docusaurus-theme-search-algolia` + - [#11421](https://github.com/facebook/docusaurus/pull/11421) feat(theme-search-algolia): use DocSearch v4.1, optimize integration ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic` + - [#11425](https://github.com/facebook/docusaurus/pull/11425) feat(blog): Add support for email social icon + resize default social icon a bit ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#11426](https://github.com/facebook/docusaurus/pull/11426) feat(theme): Add theme-tabs-container stable className ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations` + - [#11327](https://github.com/facebook/docusaurus/pull/11327) feat(search): add runtime support for DocSearch v4 ([@dylantientcheu](https://github.com/dylantientcheu)) +- `docusaurus-faster`, `docusaurus` + - [#11415](https://github.com/facebook/docusaurus/pull/11415) feat(faster): upgrade Rspack to 1.5, use lazyBarrel experiment, remove deprecated option ([@slorber](https://github.com/slorber)) + - [#11294](https://github.com/facebook/docusaurus/pull/11294) feat(faster): Upgrade to Rspack 1.4 ([@slorber](https://github.com/slorber)) +- `docusaurus-utils` + - [#11397](https://github.com/facebook/docusaurus/pull/11397) feat(mdx): resolve `@site/*` markdown links, fix resolution priority bugs ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-mermaid` + - [#11357](https://github.com/facebook/docusaurus/pull/11357) feat(mermaid): support elk layout ([@Feez2403](https://github.com/Feez2403)) +- `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#11316](https://github.com/facebook/docusaurus/pull/11316) feat(core): Add `i18n.localeConfigs[locale].{url,baseUrl}` config options, fix multi-domain deployments ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-types`, `docusaurus-utils`, `docusaurus` + - [#11304](https://github.com/facebook/docusaurus/pull/11304) feat(core): add `i18n.localeConfigs.translate` + skip translation process if `i18n/` dir doesn't exist ([@slorber](https://github.com/slorber)) +- `docusaurus-plugin-content-docs` + - [#11228](https://github.com/facebook/docusaurus/pull/11228) feat(docs): sidebar item `key` attribute - fix docs translations key conflicts ([@slorber](https://github.com/slorber)) +- `create-docusaurus` + - [#11293](https://github.com/facebook/docusaurus/pull/11293) feat(create-docusaurus): use respectPrefersColorScheme in init template ([@slorber](https://github.com/slorber)) +- `docusaurus-mdx-loader`, `docusaurus-types`, `docusaurus` + - [#11282](https://github.com/facebook/docusaurus/pull/11282) feat(core): add `siteConfig.markdown.emoji` config option to disable `remark-emoji` ([@slorber](https://github.com/slorber)) +- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-types`, `docusaurus` + - [#11283](https://github.com/facebook/docusaurus/pull/11283) feat(core): Add `siteConfig.markdown.hooks`, deprecate `siteConfig.onBrokenMarkdownLinks` ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-theme-classic`, `docusaurus` + - [#11422](https://github.com/facebook/docusaurus/pull/11422) fix(theme): fix copy of indented code blocks, replace copy-text-to-clipboard by clipboard API ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#11407](https://github.com/facebook/docusaurus/pull/11407) fix(theme): remove hardcoded fill from Bluesky and LinkedIn icons ([@Simek](https://github.com/Simek)) + - [#11389](https://github.com/facebook/docusaurus/pull/11389) fix(theme): render sidebar category index with unlisted children as a simple doc/link item ([@slorber](https://github.com/slorber)) + - [#11360](https://github.com/facebook/docusaurus/pull/11360) fix(theme): Add translate no to heading anchors and blog authors ([@slorber](https://github.com/slorber)) + - [#11356](https://github.com/facebook/docusaurus/pull/11356) fix(theme): Doc sidebar links/categories with long labels should display properly ([@slorber](https://github.com/slorber)) + - [#11338](https://github.com/facebook/docusaurus/pull/11338) fix(theme-classic): fix collapsed sidebar category expansion when navigating to another link within that category ([@qqq614](https://github.com/qqq614)) + - [#11289](https://github.com/facebook/docusaurus/pull/11289) fix(theme): Fix footnote ref scrolling behind the navbar when footnote back reference clicked ([@slorber](https://github.com/slorber)) +- `docusaurus` + - [#11410](https://github.com/facebook/docusaurus/pull/11410) fix(deps): upgrade webpack-dev-server to v5, fix security warning ([@slorber](https://github.com/slorber)) + - [#11347](https://github.com/facebook/docusaurus/pull/11347) fix(core): Fix docusaurus start on macOS when exec throws a synchronous error ([@slorber](https://github.com/slorber)) + - [#11271](https://github.com/facebook/docusaurus/pull/11271) fix(dev-server): use correct dev server HTML lang attribute ([@enumura1](https://github.com/enumura1)) +- `docusaurus-theme-common` + - [#11405](https://github.com/facebook/docusaurus/pull/11405) fix(theme): fix `useColorMode()` visual glitches due to provider unmounts/remounts ([@slorber](https://github.com/slorber)) + - [#11280](https://github.com/facebook/docusaurus/pull/11280) fix(theme-common): Export FooterColumnItem type ([@stubinubin](https://github.com/stubinubin)) +- `docusaurus-bundler`, `docusaurus-faster` + - [#11383](https://github.com/facebook/docusaurus/pull/11383) fix(ssg): HTML minifier should preserve `` for `og:image` crawlers ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-translations` + - [#11331](https://github.com/facebook/docusaurus/pull/11331) fix(theme): Add `aria-label` to `IconExternalLink` with value `'(opens in new tab)'` ([@WestonThayer](https://github.com/WestonThayer)) +- `docusaurus-plugin-content-docs` + - [#11281](https://github.com/facebook/docusaurus/pull/11281) fix(docs): Fix empty sidebar item category `className` lost when post-processed to a doc ([@slorber](https://github.com/slorber)) + - [#11251](https://github.com/facebook/docusaurus/pull/11251) fix(docs): prevent docs ids conflicts within a version ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common` + - [#11263](https://github.com/facebook/docusaurus/pull/11263) fix(theme): make `useHistorySelector()` hydration-safe + use it read search/hash in theme ([@slorber](https://github.com/slorber)) + +#### :memo: Documentation + +- [#11339](https://github.com/facebook/docusaurus/pull/11339) docs: clarify impact of document ID on the URL ([@shanti2530](https://github.com/shanti2530)) + +#### :robot: Dependencies + +- [#11402](https://github.com/facebook/docusaurus/pull/11402) chore(deps): bump actions/github-script from 7.0.1 to 8.0.0 ([@dependabot[bot]](https://github.com/apps/dependabot)) +- [#11401](https://github.com/facebook/docusaurus/pull/11401) chore(deps): bump actions/dependency-review-action from 4.7.2 to 4.7.3 ([@dependabot[bot]](https://github.com/apps/dependabot)) +- [#11403](https://github.com/facebook/docusaurus/pull/11403) chore(deps): bump actions/setup-node from 4.4.0 to 5.0.0 ([@dependabot[bot]](https://github.com/apps/dependabot)) +- [#11373](https://github.com/facebook/docusaurus/pull/11373) chore(deps): bump actions/dependency-review-action from 4.7.1 to 4.7.2 ([@dependabot[bot]](https://github.com/apps/dependabot)) +- [#11365](https://github.com/facebook/docusaurus/pull/11365) chore(deps): bump actions/checkout from 4 to 5 ([@dependabot[bot]](https://github.com/apps/dependabot)) +- [#11342](https://github.com/facebook/docusaurus/pull/11342) chore(deps): bump form-data from 4.0.1 to 4.0.4 ([@dependabot[bot]](https://github.com/apps/dependabot)) +- [#11341](https://github.com/facebook/docusaurus/pull/11341) chore(deps): bump marocchino/sticky-pull-request-comment from 2.9.3 to 2.9.4 ([@dependabot[bot]](https://github.com/apps/dependabot)) +- [#11285](https://github.com/facebook/docusaurus/pull/11285) chore(deps): bump marocchino/sticky-pull-request-comment from 2.9.2 to 2.9.3 ([@dependabot[bot]](https://github.com/apps/dependabot)) +- [#11272](https://github.com/facebook/docusaurus/pull/11272) chore(deps): bump stefanzweifel/git-auto-commit-action from 5 to 6 ([@dependabot[bot]](https://github.com/apps/dependabot)) +- [#11273](https://github.com/facebook/docusaurus/pull/11273) chore(deps): bump treosh/lighthouse-ci-action from 12.1.0 to 12.6.1 ([@dependabot[bot]](https://github.com/apps/dependabot)) + +#### :wrench: Maintenance + +- `create-docusaurus`, `docusaurus-babel`, `docusaurus-bundler`, `docusaurus-cssnano-preset`, `docusaurus-faster`, `docusaurus-logger`, `docusaurus-mdx-loader`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-css-cascade-layers`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-google-tag-manager`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-rsdoctor`, `docusaurus-plugin-sitemap`, `docusaurus-plugin-svgr`, `docusaurus-plugin-vercel-analytics`, `docusaurus-preset-classic`, `docusaurus-remark-plugin-npm2yarn`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-mermaid`, `docusaurus-theme-search-algolia`, `docusaurus-theme-translations`, `docusaurus-utils-common`, `docusaurus-utils-validation`, `docusaurus-utils`, `docusaurus`, `eslint-plugin`, `lqip-loader` + - [#11408](https://github.com/facebook/docusaurus/pull/11408) chore: drop support for Node 18, that reached End-of-Life ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#11317](https://github.com/facebook/docusaurus/pull/11317) chore: minor reduction to inline svg/js code ([@SethFalco](https://github.com/SethFalco)) +- `docusaurus-plugin-content-docs` + - [#11307](https://github.com/facebook/docusaurus/pull/11307) test(docs): fix docs tests issues ([@slorber](https://github.com/slorber)) +- `docusaurus-bundler` + - [#11290](https://github.com/facebook/docusaurus/pull/11290) chore: upgrade website to Rspack 1.4 + fix Rspack internal performance tracing ([@slorber](https://github.com/slorber)) +- Other + - [#11287](https://github.com/facebook/docusaurus/pull/11287) chore(website): split changelog per version + adjust changelog plugin implementation ([@slorber](https://github.com/slorber)) + +#### :globe_with_meridians: Translations + +- `docusaurus-theme-translations` + - [#11315](https://github.com/facebook/docusaurus/pull/11315) fix(theme-translations): Add missing Portuguese (pt-BR) theme translations and improve some of it. ([@marcelocell](https://github.com/marcelocell)) + - [#11305](https://github.com/facebook/docusaurus/pull/11305) fix(translations): Add missing Ukrainian translations ([@maluke](https://github.com/maluke)) + +#### Committers: 18 + +- Akshat Sinha ([@akshatsinha0](https://github.com/akshatsinha0)) +- Bartosz Kaszubowski ([@Simek](https://github.com/Simek)) +- Dylan Tientcheu ([@dylantientcheu](https://github.com/dylantientcheu)) +- Guo Ci ([@guoci](https://github.com/guoci)) +- Jaime Iniesta ([@jaimeiniesta](https://github.com/jaimeiniesta)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Marcelo Junior ([@marcelocell](https://github.com/marcelocell)) +- Maria Stellini ([@shanti2530](https://github.com/shanti2530)) +- Riccardo ([@3v0k4](https://github.com/3v0k4)) +- Sergey Schetinin ([@maluke](https://github.com/maluke)) +- Seth Falco ([@SethFalco](https://github.com/SethFalco)) +- Sébastien Lorber ([@slorber](https://github.com/slorber)) +- Weston Thayer ([@WestonThayer](https://github.com/WestonThayer)) +- [@Feez2403](https://github.com/Feez2403) +- [@stubinubin](https://github.com/stubinubin) +- [@ya-dvorovenko](https://github.com/ya-dvorovenko) +- enumura ([@enumura1](https://github.com/enumura1)) +- hjcho ([@qqq614](https://github.com/qqq614)) + ## 3.8.1 (2025-06-06) #### :bug: Bug Fix diff --git a/admin/new.docusaurus.io/package.json b/admin/new.docusaurus.io/package.json index 4146fb0d03..4f31756e8e 100644 --- a/admin/new.docusaurus.io/package.json +++ b/admin/new.docusaurus.io/package.json @@ -1,6 +1,6 @@ { "name": "new.docusaurus.io", - "version": "3.8.1", + "version": "3.9.0", "private": true, "scripts": { "start": "npx --package netlify-cli netlify dev" diff --git a/admin/test-bad-package/package.json b/admin/test-bad-package/package.json index 6b5043a5e9..026968510f 100644 --- a/admin/test-bad-package/package.json +++ b/admin/test-bad-package/package.json @@ -1,6 +1,6 @@ { "name": "test-bad-package", - "version": "3.8.1", + "version": "3.9.0", "private": true, "dependencies": { "@mdx-js/react": "1.0.1", diff --git a/argos/package.json b/argos/package.json index da71275545..ba255adda8 100644 --- a/argos/package.json +++ b/argos/package.json @@ -1,6 +1,6 @@ { "name": "argos", - "version": "3.8.1", + "version": "3.9.0", "description": "Argos visual diff tests", "license": "MIT", "private": true, diff --git a/lerna.json b/lerna.json index 08d375dded..d6f4c4ca2c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "3.8.1", + "version": "3.9.0", "npmClient": "yarn", "useWorkspaces": true, "useNx": false, diff --git a/packages/create-docusaurus/package.json b/packages/create-docusaurus/package.json index d48cff9740..1467fc7380 100755 --- a/packages/create-docusaurus/package.json +++ b/packages/create-docusaurus/package.json @@ -1,6 +1,6 @@ { "name": "create-docusaurus", - "version": "3.8.1", + "version": "3.9.0", "description": "Create Docusaurus apps easily.", "type": "module", "repository": { @@ -22,8 +22,8 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.1", - "@docusaurus/utils": "3.8.1", + "@docusaurus/logger": "3.9.0", + "@docusaurus/utils": "3.9.0", "commander": "^5.1.0", "execa": "5.1.1", "fs-extra": "^11.1.1", diff --git a/packages/create-docusaurus/templates/classic-typescript/package.json b/packages/create-docusaurus/templates/classic-typescript/package.json index 6232d002b2..f96af6abc7 100644 --- a/packages/create-docusaurus/templates/classic-typescript/package.json +++ b/packages/create-docusaurus/templates/classic-typescript/package.json @@ -1,6 +1,6 @@ { "name": "docusaurus-2-classic-typescript-template", - "version": "3.8.1", + "version": "3.9.0", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -15,8 +15,8 @@ "typecheck": "tsc" }, "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/preset-classic": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/preset-classic": "3.9.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "prism-react-renderer": "^2.3.0", @@ -24,9 +24,9 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.8.1", - "@docusaurus/tsconfig": "3.8.1", - "@docusaurus/types": "3.8.1", + "@docusaurus/module-type-aliases": "3.9.0", + "@docusaurus/tsconfig": "3.9.0", + "@docusaurus/types": "3.9.0", "typescript": "~5.6.2" }, "browserslist": { diff --git a/packages/create-docusaurus/templates/classic/package.json b/packages/create-docusaurus/templates/classic/package.json index 34ac77fad3..e7a78ceace 100644 --- a/packages/create-docusaurus/templates/classic/package.json +++ b/packages/create-docusaurus/templates/classic/package.json @@ -1,6 +1,6 @@ { "name": "docusaurus-2-classic-template", - "version": "3.8.1", + "version": "3.9.0", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -14,8 +14,8 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/preset-classic": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/preset-classic": "3.9.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "prism-react-renderer": "^2.3.0", @@ -23,8 +23,8 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.8.1", - "@docusaurus/types": "3.8.1" + "@docusaurus/module-type-aliases": "3.9.0", + "@docusaurus/types": "3.9.0" }, "browserslist": { "production": [ diff --git a/packages/docusaurus-babel/package.json b/packages/docusaurus-babel/package.json index 262d3163a2..8182886d54 100644 --- a/packages/docusaurus-babel/package.json +++ b/packages/docusaurus-babel/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/babel", - "version": "3.8.1", + "version": "3.9.0", "description": "Docusaurus package for Babel-related utils.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -38,8 +38,8 @@ "@babel/runtime": "^7.25.9", "@babel/runtime-corejs3": "^7.25.9", "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.8.1", - "@docusaurus/utils": "3.8.1", + "@docusaurus/logger": "3.9.0", + "@docusaurus/utils": "3.9.0", "babel-plugin-dynamic-import-node": "^2.3.3", "fs-extra": "^11.1.1", "tslib": "^2.6.0" diff --git a/packages/docusaurus-bundler/package.json b/packages/docusaurus-bundler/package.json index 098eea624d..b5b02fd1aa 100644 --- a/packages/docusaurus-bundler/package.json +++ b/packages/docusaurus-bundler/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/bundler", - "version": "3.8.1", + "version": "3.9.0", "description": "Docusaurus util package to abstract the current bundler.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -19,11 +19,11 @@ "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.8.1", - "@docusaurus/cssnano-preset": "3.8.1", - "@docusaurus/logger": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils": "3.8.1", + "@docusaurus/babel": "3.9.0", + "@docusaurus/cssnano-preset": "3.9.0", + "@docusaurus/logger": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils": "3.9.0", "babel-loader": "^9.2.1", "clean-css": "^5.3.3", "copy-webpack-plugin": "^11.0.0", diff --git a/packages/docusaurus-cssnano-preset/package.json b/packages/docusaurus-cssnano-preset/package.json index 9458712ef6..f4baeb34ae 100644 --- a/packages/docusaurus-cssnano-preset/package.json +++ b/packages/docusaurus-cssnano-preset/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/cssnano-preset", - "version": "3.8.1", + "version": "3.9.0", "description": "Advanced cssnano preset for maximum optimization.", "main": "lib/index.js", "license": "MIT", diff --git a/packages/docusaurus-faster/package.json b/packages/docusaurus-faster/package.json index 37de17ee2b..a4c1d042f0 100644 --- a/packages/docusaurus-faster/package.json +++ b/packages/docusaurus-faster/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/faster", - "version": "3.8.1", + "version": "3.9.0", "description": "Docusaurus experimental package exposing new modern dependencies to make the build faster.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -18,7 +18,7 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/types": "3.8.1", + "@docusaurus/types": "3.9.0", "@rspack/core": "^1.5.0", "@swc/core": "^1.7.39", "@swc/html": "^1.13.5", diff --git a/packages/docusaurus-logger/package.json b/packages/docusaurus-logger/package.json index 3f280dad8a..501413de0a 100644 --- a/packages/docusaurus-logger/package.json +++ b/packages/docusaurus-logger/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/logger", - "version": "3.8.1", + "version": "3.9.0", "description": "An encapsulated logger for semantically formatting console messages.", "main": "./lib/index.js", "repository": { diff --git a/packages/docusaurus-mdx-loader/package.json b/packages/docusaurus-mdx-loader/package.json index ed3f544c5e..71f28a4d31 100644 --- a/packages/docusaurus-mdx-loader/package.json +++ b/packages/docusaurus-mdx-loader/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/mdx-loader", - "version": "3.8.1", + "version": "3.9.0", "description": "Docusaurus Loader for MDX", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/logger": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -44,7 +44,7 @@ "webpack": "^5.88.1" }, "devDependencies": { - "@docusaurus/types": "3.8.1", + "@docusaurus/types": "3.9.0", "@types/escape-html": "^1.0.2", "@types/mdast": "^4.0.2", "@types/stringify-object": "^3.3.1", diff --git a/packages/docusaurus-module-type-aliases/package.json b/packages/docusaurus-module-type-aliases/package.json index 7ea74490b1..577209312b 100644 --- a/packages/docusaurus-module-type-aliases/package.json +++ b/packages/docusaurus-module-type-aliases/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/module-type-aliases", - "version": "3.8.1", + "version": "3.9.0", "description": "Docusaurus module type aliases.", "types": "./src/index.d.ts", "publishConfig": { @@ -12,7 +12,7 @@ "directory": "packages/docusaurus-module-type-aliases" }, "dependencies": { - "@docusaurus/types": "3.8.1", + "@docusaurus/types": "3.9.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", diff --git a/packages/docusaurus-plugin-client-redirects/package.json b/packages/docusaurus-plugin-client-redirects/package.json index 8520c63a8e..dc442d8d6d 100644 --- a/packages/docusaurus-plugin-client-redirects/package.json +++ b/packages/docusaurus-plugin-client-redirects/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-client-redirects", - "version": "3.8.1", + "version": "3.9.0", "description": "Client redirects plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,18 +18,18 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/logger": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-common": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/logger": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-common": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "eta": "^2.2.0", "fs-extra": "^11.1.1", "lodash": "^4.17.21", "tslib": "^2.6.0" }, "devDependencies": { - "@docusaurus/types": "3.8.1" + "@docusaurus/types": "3.9.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json index 4a4d3cd21c..f26e875cca 100644 --- a/packages/docusaurus-plugin-content-blog/package.json +++ b/packages/docusaurus-plugin-content-blog/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-content-blog", - "version": "3.8.1", + "version": "3.9.0", "description": "Blog plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-content-blog.d.ts", @@ -31,14 +31,14 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/logger": "3.8.1", - "@docusaurus/mdx-loader": "3.8.1", - "@docusaurus/theme-common": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-common": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/logger": "3.9.0", + "@docusaurus/mdx-loader": "3.9.0", + "@docusaurus/theme-common": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-common": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "cheerio": "1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", diff --git a/packages/docusaurus-plugin-content-docs/package.json b/packages/docusaurus-plugin-content-docs/package.json index 4f5f836ab5..6cc090730e 100644 --- a/packages/docusaurus-plugin-content-docs/package.json +++ b/packages/docusaurus-plugin-content-docs/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-content-docs", - "version": "3.8.1", + "version": "3.9.0", "description": "Docs plugin for Docusaurus.", "main": "lib/index.js", "sideEffects": false, @@ -35,15 +35,15 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/logger": "3.8.1", - "@docusaurus/mdx-loader": "3.8.1", - "@docusaurus/module-type-aliases": "3.8.1", - "@docusaurus/theme-common": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-common": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/logger": "3.9.0", + "@docusaurus/mdx-loader": "3.9.0", + "@docusaurus/module-type-aliases": "3.9.0", + "@docusaurus/theme-common": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-common": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", diff --git a/packages/docusaurus-plugin-content-pages/package.json b/packages/docusaurus-plugin-content-pages/package.json index dd3beced4d..7275c43128 100644 --- a/packages/docusaurus-plugin-content-pages/package.json +++ b/packages/docusaurus-plugin-content-pages/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-content-pages", - "version": "3.8.1", + "version": "3.9.0", "description": "Pages plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-content-pages.d.ts", @@ -18,11 +18,11 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/mdx-loader": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/mdx-loader": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" diff --git a/packages/docusaurus-plugin-css-cascade-layers/package.json b/packages/docusaurus-plugin-css-cascade-layers/package.json index 1adc84cf55..8428490050 100644 --- a/packages/docusaurus-plugin-css-cascade-layers/package.json +++ b/packages/docusaurus-plugin-css-cascade-layers/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-css-cascade-layers", - "version": "3.8.1", + "version": "3.9.0", "description": "CSS Cascade Layer plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,10 +18,10 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "tslib": "^2.6.0" }, "engines": { diff --git a/packages/docusaurus-plugin-debug/package.json b/packages/docusaurus-plugin-debug/package.json index a58da46b00..59f6c3b1cf 100644 --- a/packages/docusaurus-plugin-debug/package.json +++ b/packages/docusaurus-plugin-debug/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-debug", - "version": "3.8.1", + "version": "3.9.0", "description": "Debug plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-debug.d.ts", @@ -20,9 +20,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils": "3.9.0", "fs-extra": "^11.1.1", "react-json-view-lite": "^2.3.0", "tslib": "^2.6.0" diff --git a/packages/docusaurus-plugin-google-analytics/package.json b/packages/docusaurus-plugin-google-analytics/package.json index 9d4225ecb9..be4523df86 100644 --- a/packages/docusaurus-plugin-google-analytics/package.json +++ b/packages/docusaurus-plugin-google-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-google-analytics", - "version": "3.8.1", + "version": "3.9.0", "description": "Global analytics (analytics.js) plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "tslib": "^2.6.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-google-gtag/package.json b/packages/docusaurus-plugin-google-gtag/package.json index 36a36170df..8d7a78c19e 100644 --- a/packages/docusaurus-plugin-google-gtag/package.json +++ b/packages/docusaurus-plugin-google-gtag/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-google-gtag", - "version": "3.8.1", + "version": "3.9.0", "description": "Global Site Tag (gtag.js) plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, diff --git a/packages/docusaurus-plugin-google-tag-manager/package.json b/packages/docusaurus-plugin-google-tag-manager/package.json index 79e1c182bb..8012e5253b 100644 --- a/packages/docusaurus-plugin-google-tag-manager/package.json +++ b/packages/docusaurus-plugin-google-tag-manager/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-google-tag-manager", - "version": "3.8.1", + "version": "3.9.0", "description": "Google Tag Manager (gtm.js) plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "tslib": "^2.6.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-ideal-image/package.json b/packages/docusaurus-plugin-ideal-image/package.json index a6e77f5621..d5c918e99d 100644 --- a/packages/docusaurus-plugin-ideal-image/package.json +++ b/packages/docusaurus-plugin-ideal-image/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-ideal-image", - "version": "3.8.1", + "version": "3.9.0", "description": "Docusaurus Plugin to generate an almost ideal image (responsive, lazy-loading, and low quality placeholder).", "main": "lib/index.js", "types": "src/plugin-ideal-image.d.ts", @@ -20,18 +20,18 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/lqip-loader": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/lqip-loader": "3.9.0", "@docusaurus/responsive-loader": "^1.7.0", - "@docusaurus/theme-translations": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/theme-translations": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "sharp": "^0.32.3", "tslib": "^2.6.0", "webpack": "^5.88.1" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/module-type-aliases": "3.9.0", "fs-extra": "^11.1.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-pwa/package.json b/packages/docusaurus-plugin-pwa/package.json index 411778c7ab..410001947d 100644 --- a/packages/docusaurus-plugin-pwa/package.json +++ b/packages/docusaurus-plugin-pwa/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-pwa", - "version": "3.8.1", + "version": "3.9.0", "description": "Docusaurus Plugin to add PWA support.", "main": "lib/index.js", "types": "src/plugin-pwa.d.ts", @@ -22,14 +22,14 @@ "dependencies": { "@babel/core": "^7.25.9", "@babel/preset-env": "^7.25.9", - "@docusaurus/bundler": "3.8.1", - "@docusaurus/core": "3.8.1", - "@docusaurus/logger": "3.8.1", - "@docusaurus/theme-common": "3.8.1", - "@docusaurus/theme-translations": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/bundler": "3.9.0", + "@docusaurus/core": "3.9.0", + "@docusaurus/logger": "3.9.0", + "@docusaurus/theme-common": "3.9.0", + "@docusaurus/theme-translations": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "babel-loader": "^9.2.1", "clsx": "^2.0.0", "core-js": "^3.31.1", @@ -41,7 +41,7 @@ "workbox-window": "^7.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/module-type-aliases": "3.9.0", "fs-extra": "^11.1.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-rsdoctor/package.json b/packages/docusaurus-plugin-rsdoctor/package.json index d7e57cbf86..b6f9106869 100644 --- a/packages/docusaurus-plugin-rsdoctor/package.json +++ b/packages/docusaurus-plugin-rsdoctor/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-rsdoctor", - "version": "3.8.1", + "version": "3.9.0", "description": "Rsdoctor plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "@rsdoctor/rspack-plugin": "^0.4.6", "@rsdoctor/webpack-plugin": "^0.4.6", "tslib": "^2.6.0" diff --git a/packages/docusaurus-plugin-sitemap/package.json b/packages/docusaurus-plugin-sitemap/package.json index 54dab7877e..e5f2339aa4 100644 --- a/packages/docusaurus-plugin-sitemap/package.json +++ b/packages/docusaurus-plugin-sitemap/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-sitemap", - "version": "3.8.1", + "version": "3.9.0", "description": "Simple sitemap generation plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,12 +18,12 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/logger": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-common": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/logger": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-common": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" diff --git a/packages/docusaurus-plugin-svgr/package.json b/packages/docusaurus-plugin-svgr/package.json index 6e303179e3..09d0de00db 100644 --- a/packages/docusaurus-plugin-svgr/package.json +++ b/packages/docusaurus-plugin-svgr/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-svgr", - "version": "3.8.1", + "version": "3.9.0", "description": "SVGR plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,10 +18,10 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "@svgr/core": "8.1.0", "@svgr/webpack": "^8.1.0", "tslib": "^2.6.0", diff --git a/packages/docusaurus-plugin-vercel-analytics/package.json b/packages/docusaurus-plugin-vercel-analytics/package.json index 69671f0f5a..a3ad4b0d6a 100644 --- a/packages/docusaurus-plugin-vercel-analytics/package.json +++ b/packages/docusaurus-plugin-vercel-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-vercel-analytics", - "version": "3.8.1", + "version": "3.9.0", "description": "Global vercel analytics plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,11 +18,11 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/logger": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/logger": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "@vercel/analytics": "^1.1.1", "tslib": "^2.6.0" }, diff --git a/packages/docusaurus-preset-classic/package.json b/packages/docusaurus-preset-classic/package.json index e9688ac1a1..ee5e23bb0a 100644 --- a/packages/docusaurus-preset-classic/package.json +++ b/packages/docusaurus-preset-classic/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/preset-classic", - "version": "3.8.1", + "version": "3.9.0", "description": "Classic preset for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,21 +18,21 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/plugin-content-blog": "3.8.1", - "@docusaurus/plugin-content-docs": "3.8.1", - "@docusaurus/plugin-content-pages": "3.8.1", - "@docusaurus/plugin-css-cascade-layers": "3.8.1", - "@docusaurus/plugin-debug": "3.8.1", - "@docusaurus/plugin-google-analytics": "3.8.1", - "@docusaurus/plugin-google-gtag": "3.8.1", - "@docusaurus/plugin-google-tag-manager": "3.8.1", - "@docusaurus/plugin-sitemap": "3.8.1", - "@docusaurus/plugin-svgr": "3.8.1", - "@docusaurus/theme-classic": "3.8.1", - "@docusaurus/theme-common": "3.8.1", - "@docusaurus/theme-search-algolia": "3.8.1", - "@docusaurus/types": "3.8.1" + "@docusaurus/core": "3.9.0", + "@docusaurus/plugin-content-blog": "3.9.0", + "@docusaurus/plugin-content-docs": "3.9.0", + "@docusaurus/plugin-content-pages": "3.9.0", + "@docusaurus/plugin-css-cascade-layers": "3.9.0", + "@docusaurus/plugin-debug": "3.9.0", + "@docusaurus/plugin-google-analytics": "3.9.0", + "@docusaurus/plugin-google-gtag": "3.9.0", + "@docusaurus/plugin-google-tag-manager": "3.9.0", + "@docusaurus/plugin-sitemap": "3.9.0", + "@docusaurus/plugin-svgr": "3.9.0", + "@docusaurus/theme-classic": "3.9.0", + "@docusaurus/theme-common": "3.9.0", + "@docusaurus/theme-search-algolia": "3.9.0", + "@docusaurus/types": "3.9.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", diff --git a/packages/docusaurus-remark-plugin-npm2yarn/package.json b/packages/docusaurus-remark-plugin-npm2yarn/package.json index 22f16b013b..25176c2c01 100644 --- a/packages/docusaurus-remark-plugin-npm2yarn/package.json +++ b/packages/docusaurus-remark-plugin-npm2yarn/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/remark-plugin-npm2yarn", - "version": "3.8.1", + "version": "3.9.0", "description": "Remark plugin for converting npm commands to Yarn commands as tabs.", "main": "lib/index.js", "publishConfig": { diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index a21d1872ec..45f5bea769 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-classic", - "version": "3.8.1", + "version": "3.9.0", "description": "Classic theme for Docusaurus", "main": "lib/index.js", "types": "src/theme-classic.d.ts", @@ -20,19 +20,19 @@ "copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch" }, "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/logger": "3.8.1", - "@docusaurus/mdx-loader": "3.8.1", - "@docusaurus/module-type-aliases": "3.8.1", - "@docusaurus/plugin-content-blog": "3.8.1", - "@docusaurus/plugin-content-docs": "3.8.1", - "@docusaurus/plugin-content-pages": "3.8.1", - "@docusaurus/theme-common": "3.8.1", - "@docusaurus/theme-translations": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-common": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/logger": "3.9.0", + "@docusaurus/mdx-loader": "3.9.0", + "@docusaurus/module-type-aliases": "3.9.0", + "@docusaurus/plugin-content-blog": "3.9.0", + "@docusaurus/plugin-content-docs": "3.9.0", + "@docusaurus/plugin-content-pages": "3.9.0", + "@docusaurus/theme-common": "3.9.0", + "@docusaurus/theme-translations": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-common": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "infima": "0.2.0-alpha.45", diff --git a/packages/docusaurus-theme-common/package.json b/packages/docusaurus-theme-common/package.json index 0448a7c441..72aa177401 100644 --- a/packages/docusaurus-theme-common/package.json +++ b/packages/docusaurus-theme-common/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-common", - "version": "3.8.1", + "version": "3.9.0", "description": "Common code for Docusaurus themes.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -30,10 +30,10 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/mdx-loader": "3.8.1", - "@docusaurus/module-type-aliases": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-common": "3.8.1", + "@docusaurus/mdx-loader": "3.9.0", + "@docusaurus/module-type-aliases": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-common": "3.9.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -44,8 +44,8 @@ "utility-types": "^3.10.0" }, "devDependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/types": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/types": "3.9.0", "@total-typescript/shoehorn": "^0.1.2", "fs-extra": "^11.1.1", "lodash": "^4.17.21" diff --git a/packages/docusaurus-theme-live-codeblock/package.json b/packages/docusaurus-theme-live-codeblock/package.json index 541cea0db2..1b0ff1911f 100644 --- a/packages/docusaurus-theme-live-codeblock/package.json +++ b/packages/docusaurus-theme-live-codeblock/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-live-codeblock", - "version": "3.8.1", + "version": "3.9.0", "description": "Docusaurus live code block component.", "main": "lib/index.js", "types": "src/theme-live-codeblock.d.ts", @@ -23,10 +23,10 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/theme-common": "3.8.1", - "@docusaurus/theme-translations": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/theme-common": "3.9.0", + "@docusaurus/theme-translations": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "@philpl/buble": "^0.19.7", "clsx": "^2.0.0", "fs-extra": "^11.1.1", @@ -34,7 +34,7 @@ "tslib": "^2.6.0" }, "devDependencies": { - "@docusaurus/types": "3.8.1", + "@docusaurus/types": "3.9.0", "@types/buble": "^0.20.1" }, "peerDependencies": { diff --git a/packages/docusaurus-theme-mermaid/package.json b/packages/docusaurus-theme-mermaid/package.json index 327e8a29e4..730f6519e6 100644 --- a/packages/docusaurus-theme-mermaid/package.json +++ b/packages/docusaurus-theme-mermaid/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-mermaid", - "version": "3.8.1", + "version": "3.9.0", "description": "Mermaid components for Docusaurus.", "main": "lib/index.js", "types": "src/theme-mermaid.d.ts", @@ -33,11 +33,11 @@ "copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch" }, "dependencies": { - "@docusaurus/core": "3.8.1", - "@docusaurus/module-type-aliases": "3.8.1", - "@docusaurus/theme-common": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/module-type-aliases": "3.9.0", + "@docusaurus/theme-common": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "mermaid": ">=11.6.0", "tslib": "^2.6.0" }, @@ -45,9 +45,9 @@ "react-test-renderer": "^18.0.0" }, "peerDependencies": { + "@mermaid-js/layout-elk": "^0.1.9", "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0", - "@mermaid-js/layout-elk": "^0.1.9" + "react-dom": "^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@mermaid-js/layout-elk": { diff --git a/packages/docusaurus-theme-search-algolia/package.json b/packages/docusaurus-theme-search-algolia/package.json index b2832d1dc7..1225190618 100644 --- a/packages/docusaurus-theme-search-algolia/package.json +++ b/packages/docusaurus-theme-search-algolia/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-search-algolia", - "version": "3.8.1", + "version": "3.9.0", "description": "Algolia search component for Docusaurus.", "main": "lib/index.js", "sideEffects": [ @@ -34,13 +34,13 @@ }, "dependencies": { "@docsearch/react": "^3.9.0 || ^4.1.0", - "@docusaurus/core": "3.8.1", - "@docusaurus/logger": "3.8.1", - "@docusaurus/plugin-content-docs": "3.8.1", - "@docusaurus/theme-common": "3.8.1", - "@docusaurus/theme-translations": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/logger": "3.9.0", + "@docusaurus/plugin-content-docs": "3.9.0", + "@docusaurus/theme-common": "3.9.0", + "@docusaurus/theme-translations": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "algoliasearch": "^5.37.0", "algoliasearch-helper": "^3.26.0", "clsx": "^2.0.0", @@ -51,7 +51,7 @@ "utility-types": "^3.10.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.8.1" + "@docusaurus/module-type-aliases": "3.9.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", diff --git a/packages/docusaurus-theme-translations/package.json b/packages/docusaurus-theme-translations/package.json index 78ddde4b82..511e960f1a 100644 --- a/packages/docusaurus-theme-translations/package.json +++ b/packages/docusaurus-theme-translations/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-translations", - "version": "3.8.1", + "version": "3.9.0", "description": "Docusaurus theme translations.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -23,10 +23,10 @@ "tslib": "^2.6.0" }, "devDependencies": { - "@docusaurus/babel": "3.8.1", - "@docusaurus/core": "3.8.1", - "@docusaurus/logger": "3.8.1", - "@docusaurus/utils": "3.8.1", + "@docusaurus/babel": "3.9.0", + "@docusaurus/core": "3.9.0", + "@docusaurus/logger": "3.9.0", + "@docusaurus/utils": "3.9.0", "lodash": "^4.17.21" }, "engines": { diff --git a/packages/docusaurus-tsconfig/package.json b/packages/docusaurus-tsconfig/package.json index 789859431d..f2b05ed91e 100644 --- a/packages/docusaurus-tsconfig/package.json +++ b/packages/docusaurus-tsconfig/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/tsconfig", - "version": "3.8.1", + "version": "3.9.0", "description": "Docusaurus base TypeScript configuration.", "main": "tsconfig.json", "publishConfig": { diff --git a/packages/docusaurus-types/package.json b/packages/docusaurus-types/package.json index 6636f2592d..77ef80c1fd 100644 --- a/packages/docusaurus-types/package.json +++ b/packages/docusaurus-types/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/types", - "version": "3.8.1", + "version": "3.9.0", "description": "Common types for Docusaurus packages.", "types": "./src/index.d.ts", "publishConfig": { diff --git a/packages/docusaurus-utils-common/package.json b/packages/docusaurus-utils-common/package.json index cc2e54cd21..052fd9c061 100644 --- a/packages/docusaurus-utils-common/package.json +++ b/packages/docusaurus-utils-common/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/utils-common", - "version": "3.8.1", + "version": "3.9.0", "description": "Common (Node/Browser) utility functions for Docusaurus packages.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -19,7 +19,7 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/types": "3.8.1", + "@docusaurus/types": "3.9.0", "tslib": "^2.6.0" }, "engines": { diff --git a/packages/docusaurus-utils-validation/package.json b/packages/docusaurus-utils-validation/package.json index a8c40528d4..8a769f0947 100644 --- a/packages/docusaurus-utils-validation/package.json +++ b/packages/docusaurus-utils-validation/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/utils-validation", - "version": "3.8.1", + "version": "3.9.0", "description": "Node validation utility functions for Docusaurus packages.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-common": "3.8.1", + "@docusaurus/logger": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-common": "3.9.0", "fs-extra": "^11.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", diff --git a/packages/docusaurus-utils/package.json b/packages/docusaurus-utils/package.json index 030266b428..a69164d93d 100644 --- a/packages/docusaurus-utils/package.json +++ b/packages/docusaurus-utils/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/utils", - "version": "3.8.1", + "version": "3.9.0", "description": "Node utility functions for Docusaurus packages.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.1", - "@docusaurus/types": "3.8.1", - "@docusaurus/utils-common": "3.8.1", + "@docusaurus/logger": "3.9.0", + "@docusaurus/types": "3.9.0", + "@docusaurus/utils-common": "3.9.0", "escape-string-regexp": "^4.0.0", "execa": "5.1.1", "file-loader": "^6.2.0", diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index 9bab02348a..93b8e57645 100644 --- a/packages/docusaurus/package.json +++ b/packages/docusaurus/package.json @@ -1,7 +1,7 @@ { "name": "@docusaurus/core", "description": "Easy to Maintain Open Source Documentation Websites", - "version": "3.8.1", + "version": "3.9.0", "license": "MIT", "publishConfig": { "access": "public" @@ -33,13 +33,13 @@ "url": "https://github.com/facebook/docusaurus/issues" }, "dependencies": { - "@docusaurus/babel": "3.8.1", - "@docusaurus/bundler": "3.8.1", - "@docusaurus/logger": "3.8.1", - "@docusaurus/mdx-loader": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-common": "3.8.1", - "@docusaurus/utils-validation": "3.8.1", + "@docusaurus/babel": "3.9.0", + "@docusaurus/bundler": "3.9.0", + "@docusaurus/logger": "3.9.0", + "@docusaurus/mdx-loader": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-common": "3.9.0", + "@docusaurus/utils-validation": "3.9.0", "boxen": "^6.2.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -77,8 +77,8 @@ "webpack-merge": "^6.0.1" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.8.1", - "@docusaurus/types": "3.8.1", + "@docusaurus/module-type-aliases": "3.9.0", + "@docusaurus/types": "3.9.0", "@total-typescript/shoehorn": "^0.1.2", "@types/detect-port": "^1.3.3", "@types/react-dom": "^18.2.7", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index c968b537e2..1d8913bd74 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/eslint-plugin", - "version": "3.8.1", + "version": "3.9.0", "description": "ESLint plugin to enforce best Docusaurus practices.", "main": "lib/index.js", "keywords": [ diff --git a/packages/lqip-loader/package.json b/packages/lqip-loader/package.json index 3a89e0dd02..1c5963f6dc 100644 --- a/packages/lqip-loader/package.json +++ b/packages/lqip-loader/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/lqip-loader", - "version": "3.8.1", + "version": "3.9.0", "description": "Low Quality Image Placeholders (LQIP) loader for webpack.", "main": "lib/index.js", "publishConfig": { @@ -17,7 +17,7 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.8.1", + "@docusaurus/logger": "3.9.0", "file-loader": "^6.2.0", "lodash": "^4.17.21", "sharp": "^0.32.3", diff --git a/packages/stylelint-copyright/package.json b/packages/stylelint-copyright/package.json index dfe3ef7603..9b50ede686 100644 --- a/packages/stylelint-copyright/package.json +++ b/packages/stylelint-copyright/package.json @@ -1,6 +1,6 @@ { "name": "stylelint-copyright", - "version": "3.8.1", + "version": "3.9.0", "description": "Stylelint plugin to check CSS files for a copyright header.", "main": "lib/index.js", "license": "MIT", diff --git a/project-words.txt b/project-words.txt index 091a09bf97..258725c808 100644 --- a/project-words.txt +++ b/project-words.txt @@ -49,6 +49,7 @@ Csapo Csvg Dabit dabit +Dagre dagre Daishi Datagit diff --git a/website/blog/releases/3.9/img/askai.png b/website/blog/releases/3.9/img/askai.png new file mode 100644 index 0000000000000000000000000000000000000000..1c88b5f1013a14666f81e0392baace74a220fde7 GIT binary patch literal 194259 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 !S|}+jH#OMN9D8*9?q)QugJcl8i{NW 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 z iDFlr@fO9C5v~)ww?QVY64}B2 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%0A)G#Fs6P3~)h6=si}l*G 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 z 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

    9)txU|F!&86X>u`4^eozME+PTjsiv4*-!#hW-X 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 literal 0 HcmV?d00001 diff --git a/website/blog/releases/3.9/img/social-card.png b/website/blog/releases/3.9/img/social-card.png new file mode 100644 index 0000000000000000000000000000000000000000..1d40a2bdac699239644215e3a9afa5209507a555 GIT binary patch literal 191976 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¾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 z zxmmj2q*@vc$SV*@mDObx6(Fz9{K>CqLMkd|zV=tTEl1w}qiXc<3Dpi%`ZnFpAoL}# zIFR=A@BU)lgtJq~_6;$!J)yudnHRQ8ndP&BVH9G@W^!mEr=(KL2Kc)ge_8P5BwI-d zf`kF{OHB#}1We|kp}JozKoVCja*Fm_H7lfjsm=m8VU@%RhMc^TD;e6zDw9HMi$ zuqTK;R?@6`icN6;Rx02&u%h7J;pG}}Wd@lFVr4CmJs_^?<*}ve7i%xbQhf!oV0Cph zv9G@-n97EN2E-N20P)gH#1;NQT)||J%muUAj5>Vyur}2|I+#IfN81-K)*S_7!azXI5VZ&UT9LJPQ?AT?#t`u$+l&b(5pmKtjhtX%8|Go8 zhQOF%QilnLJ}w+x(_|KT2wX8kDjE*yg9#JGYF(QXMy`;mw=EzKLCBD4nC;x`-MgpB zxw4!Dm$aG7QoT+-z9t9MG*+@s>NlB{Nz#T04I)~q?LveiAOPr`LQP0y zFIVjG`^cmsl4?C(uT)=BT@;de8S+q_Tm?mb=g3DE$AVUb&NsBvR5w>OHmL1Zl(SCh zWSsg+<11l%j?uG(>O>ppIm-z%B4kX?&1rnGx}J#?=5>+EwNA*fI{7n-n>E@Ts-vG= z?PcpDT^p2#oXg~u0OKu*|SF##>ds@ z$fzc*v{@`ORo%IBchJ{D{dXC^f%wg%^AhFvxE1n>_ksL$aZ^GQ@IHYRHL++3t@t}O zI--fJ{6K%*v=DF+SwQOW{l)+%U>pb7A|HFk5f zxdzHMsjvW$aAfA#3Sb&1&HX^Kz$7le`+znxlx>3FCz$z3^%Y2&@tf|{1k(Je2bDL1 z^45a#;7iLyUZGqvc?7Bs#hM~)V05zTYYNWP2Pc}yA`{`{ODJix!JyokuYSf! zUQwGj>%7wBZ>*Eh3M^H7&Y8>zWt>!IwF{;d3|&s%<$fG9L)Z4s;{l=YvK8&9JwlqNsh}=1)A&+b3DV~W8z)6o<;+q?)mJ9s3LrmM zc%i2kc@S41t?*SFU#gL2RufkjwD|`7Pmzfp2PQ#?x0wk7QTt44Dbv#A()@={wx|s> z21v*K3rTXtR=1qka=%R`WtAkgFdnqx8r5quDUAp zEj6fQWSs;uo0BWI`CQ-idYL+rhyWT_4&GOJ&-tuy2XOMLYL-^2UxT(f0o)(xD<3P< zIW;M#_i30z~LyJg`uJG{2JzKDfXMB_cCj0YI_*xE?PFrFhdtD}NLSr~;#!nuQw ztaQ^0i#vngX(*|sk1XA96Om@Q^#tcbl2~%vrp%Hn7se&A07+y?<(2Jt z6qw8iDKz=alH0)KvqNfSGI%jMURJrvjrYdFmve=wU=wkrowJ*NiO5;(VnFh&1uwXq zxRRt52VO!Y>A=6lCk2zgB7i$+&(<8q*3|$tKUYLvfwMt+#T5W#hQ^g3w)~{xlByR{_eg?Ff~z`ox|%|V6IU`X zcOGscpnO&r7P+>%z8v*jg42qzXdeGL^u`^w?F zG9lH=!A)EXj`KqRS-@3a)OPOoC#>EEvLdLLo2Hq7_#J~2^}28!q6}Q0v!ywwi6Zw2 z$ARn2wW=Z!DCA>}6pQ)VeIZxYl=Yj)FYeQ;6w$Pi`XcL+W@b(GTFmKWehO(NKv}1( zOSX&1D;j4qVYaQ#S+94#)Ue7T0HvO-y|P{+ljt5K$a+l#FkKra)9$c)4{A7Wrfeh3 z8W1#RM$PI?lWD9kQD|DU0p{%0)gR}y66@f>gPPz036u+dt4BsQ$t*yd6$ZcSHBob@ zUns3N`N`rd7fOfkDT%ecfb)ruv`{Wpmhl_j=qwwK)-xkG>CsH{N&zVbLX1cytU72@ zVa=Zno=u0U%Be8(MDovzHk-@{qpn8i0?46*Z+)LOZ6ko3!D@P?rMX65SorOG_F?US zoC5^d#PQp-`l__%Z$5|>2d_W+m8S9lB7;yS(&<$OSxAJFB!%GEU9V1f)13-W9guVc ztA4jYxSSPM3;f~n> z5LfVT1;rJJ9+)H`PQpZD;l&w~i$S5l0&x`QE3XSCG6W=wB(4DX{(#v6Ui3j+>B({M zBSYjB+FLc}xT053By&N)G)c0N6G`<&mseZ0jGVCpF8@co9Svqv2FJvSdFeF(uw?cf9l z)hk!DGnGMY=A@aA;!D?C+Fa?c-rkzZhw2Txu8ANdWli*m@he3)}@GKG^1K}f>NL}pRFAm8YDAy?)! z)k{8|$OI4lm+CE>19pkcbF*S?udJ8MO1bjU1uBbtuE|vzee#;fUfZ=V$-bz+VY;q) z|AjhC;6y*bpE-EG<2MPvS@?ZBbm)*?bOg#{kUk)-bQx^*OZ;|g=jp*Y7z}BaS73X796g3v9u;_Q1%m{tPLc1wgSk(XX`Ks?q{ElxDS=IiURxaEd?C)ACrbN~a zfU89i7|kRL%=LUh1k}Y#BkGBBQw_&JhFyQIxqO%{-jZKdV~@;O(obNlL5$$QM39GWR%u*oWRc^A8WJ)iX{A#0u3Y-%;8H@C4DVGjfK?- z$;s}A5zSXy4z?=3SkvufwgIZfQ*gH$G0eGibP zg}_0}%7r!}3m*deQ-*8XKs#CYOzScogkoyC-@Gc})2Bw%?%l;u|5ahD5lXZ=Ps#77 z`mf@?nu;~Drm7sOs)`n$eON1;IG{cP*#v?H1W*)|W-e==RuX$&`uZlbL2g>9L#U~0 zbvF`Nm-H%sx-Bur#5Rr~+X`3DHxW-D+pwae_PfQ%GE;eYUQFEiCN+QhlwOsvQ_xRW zQehz^Qi^+NadqvDNy6{6>AAZxzu&_2U2P z$tATrh|B%MaA-aok>y&oFl3KY|_RjlLV=F;>S((0%2n<{ZjEfVP;4KkXO5R?+M7OE1~&# z+oMeGBvA-O#%j##2>pdKav*GcZ1vK)@VzdO*JKiAt6vh7RFA7(A9YF;WeEB9k^SY@ zw5`sl3KU6(kf|B@Rg?9G!RA9sstF}20|Mjl;k-I@_^^(HiS(H>FX(O4J!z}kro6J% zOD2Ibzp2miIY25bBK*iy6)H0L9<;SbUe96m%41|^P321PMJY@QLQ>+&XC*xwZ0Aab zuJPq*_&sPNG;tgXVwk=jJa|YeszB(#tWf_>QhM$m3&)_kh9WCSU+wd#Uf?9ES)mJ@ zywV@FLf#2XW`s>;viFb6SFY5EtSNQizyZ})TW#32a^bFtRW+Siv#wl7CTRdS_e#+l zfTkSAo5JD0l#GvMaGK|`01MWH0Eq!=Fl?AmG znLkEu8>^DW7GzuD((_GeL88Ie77=F1YZCHoFeMkv7-gGn^+$p2I;cMlNrgq`f_365 zh~s3I%dtBrscg!uPQawTviZ$2`OpG+HUFx``h&X{)hbD0tNJaMIGw$HSxuGtRPNCs zul!trTwcdV_jUuz*oOBId-?HBW$5;XIR_0@1DuYDNSC1uz<6E z5D&gYgKd&*YNL%1G!buMWtsZsA~sCzjyoZBO}<@_*RyZ=u73IU+0;(C?=x<$^rrG{ zZD|E^9A$YRFmN4@jg4!6NRyL0f_rpP`|=})<-Up^o<{c5lsC+;7=H$E@D=^wWPNzJ zIvLSsoTbJU1#RWW8Ef*pN8k!UzCt0M3FMQI+6L8`Y@57xZ0E`~hCXQkBHxH)BcEP0 zM%S**=;!eC?6h807r%*68{;>boV;`3Hy?x%ekY+)#>XcRUr;pTBM|rdMeTB(51(Ur zC!mi`XdBd0s1Kx6uJ(RG?-?c(YpOB|@%D#ptd0zSognS@?%7j!5dd&S7PSG!K(3Vw z>+e}9an)0hq?7hpb+E6=YQgqijqMk%4ja{1cO010A&8}$PA;iu9~*5-17%hvyR42K z>$h4;_+C=Ht#QjBGPXY;d!T%hE9OCk1#)Zo`6snmAqPkpn9jj8&Rf2ws-&;JgV*MD zeT`-AQKhBp$`>HPkf(vbf(q;M*}4g0RLHRd>4Y{(^%(#%ipVw+lbE3UyzX~WT6v_b z8`!V-z=%b!uG^#f{D_RWSuXkXdPgy7f-Gz zxK8yYu?Qx@O2(NKSvIAX4>(EXQex5ZxUiWM_MaP2BYX076WHy5%tl{i|5hCM0$M3o zeF5#?w@)PjkX7aK9_?I}UU;E^N)p`ht6c36z)SjS&6fwjR~HJv+ckiuF2!@8-E7m~0l|FH^;Z{L2sjq%LoF4ajd+nDl?2uXo_6gI?3@~qZwd{Dqg znxUF$J<{Zd3TjCEiX3WCP_Nfk{~M~URH#5G!8caTM-_JiK<0o^l+~1;La3nk?A=#) zG*8a}oD;l1NYV@_25rcRYseHw05O`WDdz?U?Y{Gx9ljUUL;bmQ<-%V(-7tEw10lSfZSC$Rt% zY2_lg;;OMsiYrcHCAD&4y???ac6g&-6|V;q?7pfQY_F&YO>95n;NvPTaYew3B-Bgz zPYSCw^TS;`r}T$NTDxIZivO@OQl#i+ z@M~8uXi*~|aGyYF2qf)?C<*Xq5cx4gi03msXMEbt2@+QrwOs(IeW{%oPgC1W&$M=g zzU|g+AKH9B#0MNGtX3_GIUJK874(Oq!Dx#ogkdruDW|9RsL6?m29w$93a`n%lMtl( z$^`E4{l5N%(3K05A{4p-H`=_;)L+CA@nSO_g!*cDtX!XAXyWNmKv%rbTpmcR6WJ9t ze5=xCXC?w@-Qyyvo3FMoC*t*B6+Wyc2&I)&VVPFmgMY04{BT`;wVu$0->QRit?F8v zSG-MeNjAVnI%#vq9XpJ9TETk44-n_C0yit<+eA!B|5!e%EFX1NQn2~Kk|u))XQvD5 z{GCA?GSzf9ve{s_fsMWB_EFUsUDy@j5vXNJmCn+*3 zv(m3}rw3L4-MvFz0o*PeD+=C{nN^32i)vRkn3Rkz#3HUZlAO%orFo!M-jIG_Uai-G zFTFmFgyVutDS)~vs}`E-C5N?1zm$i8J7(^d@)B(m8*@4*VP*3)GGAEeTaItLWqAay z9LaPc0kEA>F%XJ$4k{sJBR^MRX?p>t{(x+7UE}1_s2!w0yFkz9e21UUVW4M1uZ<^x zt`nQ`HOb#54%2fOYA>jw2lGQ(39c34m5Nq|Z8ga%S1vR;eAn-0!n|-R9lp0(chZyT zZUh{q`}A{VF>7_)4#LWGm)vsOvUc7s0aL=MeN~6?m z_{-m}$D7D2sIRo?plT$E+ViCF$Kdi6wLz-^GWcG{QLguPtR&cu`_1{(#mj0Jr1A<*+jrl*p;l_EHKgQK_ko{}>%#$Yx<8{^BFpR`<)lKEgG+ODVeX&$u3(GZS0QNDtviXSfg|8`H+|X1X zp_k0zZY02W50D#hPen#XM$||^oRG;B%%_%@mbA|wtjGpa*h0;8nyzivGc@cu)XH&6 z69+!e{Z`8MA;@ic31Mlw3Gx}=E~3g+zYUd|nWgW75}gG35#{EECL)VZMz@j(x)DgI zb_3+qJ3k z_}1kcAJ(@xZE4prSDGkeE3Ys3ddb(WQzmCtsCw)#4aawRpzj0)lx z;cp10&=dl==0HXc2G=9^`Gez{q!cFFaqk~O*z>lXux#Chn-YuoQuL?QEi z$_i7%`T_)O_*&ZC0qG}8I()yL8Au7FE(gp4T}r4*pV@Q}fcgqVl?^y{%WWm23hVlF z%j)8e5p{5H@@_QZLaVTjo>1eLo;MO$Aei9nJ-_#G@D9}Y4iQy>Mdo*n3kIS$>1SZ}2!hwsu~7ALeo64@YCSYZmTq_H+p)?^4S zP>>@jdDY$E=LhF)$A#d<_H?5Pi<4Jzh%AChnH5G}#dZ1)*pyjxEUM2eG9%2~RVDq1 zpzRizh^x&N1>5iFx}AW7Sgz`!7hl`Uug~Pk1gtPvU*#y1j2p#ri(iJ(j&c`%U2YZI zrC;a={K3FS8&=%9cJ-=`?}T&t6e*&DR?##$L?=H@{5hB+g%9w&BmY+}LQ1N*T2XW5 zdhi-G5?Q%mBF$DVB#Xus|xGMhc?vI zYqC}n49c%gf>c-|$4+V$7GEV0CUa0n>xbGC6$p~)W>C$ZuZSvF_yCPfxc zV{!oR3+^Y2@AK`bKC7Y05*1wHEXbD>|C|XSM5@ zkR7bCpo^J+$f^mlqL5i!g(a0)Hs|j)baM4VkXJiiR94IBmxG>0m_IB@WXa<;*oZ3W z{9UGzBvxEMS$yBLa-nHOLldb571q$Rd9`}`vZ|=9zt-`iJGN0Ju3pktRC|YmuROu? zCN6Phddcgi7r%D--hkTR$l=54@R6e`Kh)@4H#-na>`V4ZU)b>!+Z%;dQ2yuiHH4KZ zQ>5r+z%e!!&A{qz6FYXR6e)axXCVmvX98lW9jgYnf^K<-k?&L7;rlz(vYP3yR8?91 zRrA8xltk_bd`W?eml{p^@D9GTlrj3f0zh6xG5rfOC7j(cSWm|Ra?MnKyT4z9u)#l> z^;3BOEE=5*<@MG0! z(?O~B8mRQETe8&^1*fN~YAYSz;;)tIC9hpCeo=@qOsJyxz;c-ungD-AaBd9p3WSt| zDK5(K6x$b`saYPeV5-?GesxDLgQI%hy9Ga9TmeNYDiBa6k_(D7{DaJc z|1U{EVIRcQo>#w1jh%Q&QyILSohGkPAhe6SNM)y+%kRQZDq{QT~%k!oY6k8K!So40eUs$;BmHX8*FKO%G|2$6q{Hn zl+@L$Gg^f;6^zl1@JveL+0w4(cbsxfdD{K^g0geDTz%ny?T&VQ+_SD+*w?snVT$$v zr@%%$fhfX12qM}y0mp6Teqlf!e}D`jV7g_(!$D!nW3tBt+KkT3YVVO#23$paCT~1Zx0{2&D=(#->plU zFdI94O8dDY=ki!#5cR^TJt@+lv@)&GxTM>0MU6diXHyxnot=jEfh9rY6{)d&$tzNbGeVeGuH-snHa4){-xdC?y3L0KN7U7vd`%Jg3qODH zk4i}KPPYA9t@OjqR^0?}?m19a1 zW&CaFY{zN8(uE6ibo0B53uIonYhqPRXV#ilE=*Nf?E_R;w;!A}I%Nl3#1W~VTJb-H zymzQ(5)0_NGNZ{XR~y1sJ?uq*Almh^w`jsj5=+(pE1GoTK%9vXA~jVeAid=3faKfD zWVVR1X1;bwtFw6A{Nk}^@f>u#Q-qd&nhY|MN{0M+6w^WpuE+vt zn+Pc)wl-FSiQRyTrNr_fvX+k)RAE=S?nrUFIvl*w94QuqAI|KdqRJj$Q-#x;GDk^H zNm5HHvv{7Uki?W!V-ci@p^S^vZ>Gqi(Buq0b9O)tj25+8tsMYiI$5bYgYFi`?5(~4 zCixOc1XNs8Lf@skZIc+&L?LWq;+pWdNE_QE!jzW7mmCWtc1#l^UN*(K`e5p_t1rIo zklVJ2m`op5cG$!b+cPuQ)cN!0_5N0nSN*CIJXw=jDKkY1iDJM*%mrVCah*%kYS;5H zjC{7;$F^sui%9YzX~M`g*K@)3-1B)x`#j^q(uS4oDu=h-w(rvp+i#og8Q*Q_^~DI# zeoSQ>h^%zw!nT4`SYawB2_mm-&fcTc51_2M<(-s$oE@M8n7{KJc)wV*lWlHaA>(2Y$s>8(&niA^S zlvH7H63cXqhdEC(Qchlh%p%Cu2TkOY4~Zqql5qfhaKUtNyRp0}st-?)Gv)mywLY{t z(U%G=3T;l^O~-s8S0vlR;BxE7z9B_VwSiZ<>6W(wioyF7Wb}7w6QK z%a^OBgIlD$lH?T#t+4G@(2g<*zP_k@>NTZlwY_0|Z|B&wyIfoOI43YA#C4AA-Sy0~ z-Loc`o;R{Q+p|+{yV_zSxp;b6ziglBm~Z>So>{KvksMFcZ-k4KQ_B79b;XGwu*;gTX5Xcg3fxw^Sv7>K-r)Al4@)iJk5 zSx|ya9vkt>(~9Y0F95{S?l-(w9enHiG`S>IOfDcT@*Mou@7F|_&1V(?DlGV`LO$Pm zxYz~c*w|ffjMP@70eQ9m9sfit#5#$FUz7&Z!5YHUS+sf~j|+pzywGG?Xj{e579uU3 z3aQEhW)BBn1BTaCNu}71z>T^^Z*@ zU?Q?ilK@k>{J5=5+m~{l*3}lC*Yp+N_O)GxruLi0$u$-}W9u7dn$X$C(^R)_pD?k% zHZ!9gw|A4-ASbkJ+wCYn3HXkqPrarzt+qF;@9i9$c9&}_pUw%c^UGJRs3ZBI;64~N z-fy<&3c>bV@VUobaJ9u$w~L7Jz5jg_N@48?`>MH`$!P)xFyMIPqf8)fbgdzO1CE0q26Z6)O>%6kS!4Y>y_)$d{HH zoM<{H97zi(`tJFW3;NQL#1+9rT#+v0IL&b&_1v{;@ibEvvJV_8yD5G4issN^^_o~&^RlN;ALk~avh`M<3g5Kwj+2uCi zOJH&3)x_kay8EuX)b70ptYl3?TRp#k`{uQ!^*J85&agDT?X=Y&Wg?hF8s9N;9rGP0 zC{jRTtrZHYSSqPfvHH7OEOnp%mlT}^)S>`ZPW4Sg`x34)qP9ntr&X<3-PO?E+(7Uf zl*{RbE#Q!Q=hT#%44#ph+>o)3IM1E9&sd+lGQSUDl=QPZspqn-jXvqa;(Xd0>}G_W0xK@}<`NwuG7aA2@JO9X@hcFEjwGtyL$Z6BCmvpHJ}1qChu(2rSiRvQ;8$ zP@5N~L{{>^Ft06SHIYOhQ$47)+Wp#2^#ko_!+N2aaEP+H;8xX%GAhf9s-zQv?CQsY^Sr*VR99gElAy9Vc9$V1tddY;*&Mx_!nn@f2~v?Yyqr~qa(`?;Sa>jv zFJ4l|R~OXXCr8!Z%%JL9?;ZbEJWnTH=uG63B(LPQgekp=@Unejm)iuFQcC7Al@m5W z@cq*7`;|PboUnGvI9vZ+d3}hmCnjH0L=e8?-L85!H5|GDW~shobyNwIw}PQl-E_a?b&84E9@C#D=X}|99EuY3+s?2$Tmh9CYUbOv zdcw|S9QZD@(rI*~KP}hFg^#XQ=WXpKBDOm~7LX!KJ7;Im!@m)pKQ3rWK=q@neU3K7 zsSEi*z%*ead7^~s)5W(?XPqnx%IFXNhj;F6AbjddtG>;02~qmQ$A(rdqg2_h~!Q}A09nRhX8;NDh6Nk)#AFPqJteP1q zMt+ds;WrtOSFc?BhW^T(pFg11V4{)DXcZE|FpyelJAp`mvLFMX4lsR@jrx*nN{_fw zsic)O95y1vM2h$lP_{Uqe7qjn23vcgPKaD(new~R_~tdm`h6e+q7QSNQuG%m8)mM#h*&bQ-yln85=Pkpv}Tx|$zzo~B5?^jsaVSR9godn*U zbo*-W3s?aW?-1GY_BCUa?|tZRrCfb?feH;{u(G&;0k7kR~xnaHdtKC(>UzOVq>>Vy6jhj>&OVEba+jkX!S( zSGKevpRcM63ad+MfGvuFg&?6os1#SV3x7W3zAx*hbUt~brm>}uGpXqGM5G(xGqx#G zY*iSE_mARhiz4gxjKI8q zwbpqS;++HwTV#U|PQxR9PN(AnAGJW#(7OY+5#mD>5nH{6qT~IBlXUbRMCR)-T`v|3 zIv(R+2*zSzVL>ehB-V70{`!s`Dwnx4)aOqMH*5rji-<`QQsHAFuaYR=R98D-s*kp# zlmXbtyCg`xuzGy!X!rSR6?Gq2aWPh@Dy;yMLJP;qj8OW}N&;MwCF2mTPX-UlH>{?< zuWm5l=9)Y`q;d}qJAGlV9hP70}D^9 z6Jv8~Gp+U9XK@G^Q0eH$gU z(Kq1S28cM}+oljoVC3^nZz8T-adLYrz<+;QNn=ZI%j^0bj8l)RTtK$RbUca~G<`th zzr*-#1%a}>wB#gXS^<$$@Xa!F!TEu6>DCk5y`EmtXrmYVzKSlyv&8rl~S-H@LhSdw1Ng<(}ucYMF4G26)iie6`Dl8ME3d`4LRx8RZg7l9? zaV`?e*ZDjAU|mJYY;T5DN7dDR+TJ7wMjFD+V2JIB^l zA1Ag_bOzb}(G9h}6mP^${<5S=p(zhHG30SR$}G8RA?;HfU#Sr4tGNROwNItE5wS8* zQMvskm5oSX+5BQjRhIASg-JMn4>K{eIe%|LsZZsCCu~%IaBHQ@I>eVs0BS3I?Z(T8 zoZx`Q0*RH&R{J`b8*4bev0i<7E0)*m8-~T%_LGE5QRY&ak+KvjNSZ{GB9h`I z;!L*V!g&2(4-ccRUPkG8xK+3j{4%zpvXXJFkQqysP=&<%fV&-ly8`Kkz!l#~xb79Y z4@}29d9SRA?YQ-FcMU~t4p<#~Qko6qR85i9_}-0GLU}r!zoy<=T3%L#LP7N}ENq$^ zR@T&Z^$eDhSIL0LBN=X&`ck-&CGx5jBFm({(x!zD<&()bmXBE>C$IQEC$>n5wS2Uo zCJy1HbNiVor0_@i_*x_q%jN^iq{6c0cM(}p!O1I=19-r+f+3G5;2z7a_p4&266?Xc zyuA5s3@<;cg*7#lA5t$Rk8$+IsL%s-m?O$tb^HxlJ`6QPnvT{)Z+IEGT{W8a= zXhf2$AGTsrWP)q5O>vkk)1(<;5|Cw@!d^xkGHg3R`e>y6sJq+l1|Ls zYywuTQ%;T&4Wj08` zu586Ks-5=_z1#R6$3DNO>9{GK?YJw>R8|Js7qS4c!;q57y?f z)!^RQBsg=9I-AO^1bs}&ffOF-G>MdwR^5TR384&uR#aJl$*izpTPf`ei=Z98E7jyH zD=J8hb#!-DUGFQU62BW5#o*+ZW0(<|;6rHfw34jiVO%ncKm=7(A6cW92G#Zb)t84> z9>RD*rI!&}1{%)XC2YQJ05TziDoQ)}6feDSg3gH-Ixa(=j<$(Bp(UI7aeyB)!Iwax z`lQ45tsq)teSDugu%$^+)NR6A&{xD!NRt&;DAUXGU1L+5HP8Q!qDpK!|i}< zldFxs?KhEE>y^!G7Ar3zj!3LtUU4x+itP@Qd1N<-)|s;;vRZ{)oltHAAgmmNW`iFSS&mZ}~e7e*=(QN@Wbd0di9Jdez0iZ|6Q(+Jarm2V#IXJ21#DY zZCA)uJf?haZBnO%kq~Z1qrCDURhoQ63 zBotYksIr+9+MK^P#4q}Jm*E_mZNY!6k3!MLn;eaUG7yL+`&Z?1`TS$Z; zu|^Vd6DiFKIdSE)YN5?zC@2igu;JQZX*i8S3I3+6}2VilRdDfvJpECzq1Q@|gg((hr%pQ)Eig zDy&Yxq;LwWzgzlYGa0j)s+qQZP1Gol+?MHFzHMZ_c7*MQ&ojsMY%-~tc-e77le#mE zLua|bCzmls?x@Fju(4ffjRc4u1B$Vo^ zL5D9axpJY243mKKc79T}>OaNSqm)_KW`qP%UlEDLrowWmvwZTm z8${By^WUTrFqr|y4S5+!AqpAQ%4D$BNmr}j3J2OZ9S<|Bllweh(*Kg03FM(nf_a-u@2lEM^AuH)@cI3+db=Zh{)AP?<#-{mTxzc=} zZJHUH^PAAC%8>0E0(4H24touzcK3Q*I|#9MBAY1&6K)VuLFk$)bN^UL_{uUVttd1p zvG_4bYDraAX6$NQYfDvYHVw5Rl+b}Qc*H| zCAaxYl6h^D922qA3c`G!Y$Z(fyC#ZJ!%h+#HY7n}ZDk*PCZbVEtaiinHQtuS6i=`@ z!FCZtQB_4@$9>bd@GhggwH zr?@_yk|wcCWt;ZH(#zv3D=Tdyf+c|y1#$AVo5V8J6_(c32dTa)GZHJC$!byyDY!Ft zo|i~3_(3fM_d9=1NM#6t_S0}{LVj+N2<7?hM#whuZK+V>=%sW?LzdmQx}r9Qh7;S* zLUGkMo6#iH##BXbBU~3D;tA5>dlF9HrQ(Xm!MXb)JBEF3PAFF_ERI&xo{1$3`mJjBxpMU!Axj63Z3>am@@}{;|SVHMIH1!hRfw?^2ZoNA4TNf+n!S z##%r0YHF>|mG-Cu&wN%54Gjgv)Q}nu{>R401L7*LMn^`pAB5rIVNGfc1#t*ru7?%+ zvf0KlgyM>vsN;o&mZ0uMn20hPaTZlkU?TKV#D{A_Yns@~xOO;E?j*wex$xt(O)Fl} zN>Mw67At-5#)Z7Xji$dl-|9mz3kzy#aZ%?5;Cq!U1=>lTq+#^X1WE8j*>{!OEm$uEzathh z1?}hil4zm0O33k~%9H!N?O}Dh;#=L9b+o##6{A0;D2}xYFx_Tjz zS(VE{KaTs2HC`lO5V$sXMV&cwMw3(^tw5+C#EXjFM;MS+RpKhENi4+Sg@ybeY_3Mr z`0@jEi=T)TDO@NE0xQc@A>}rbTd1ep!{k|t_Cih?X;W8rZ&&s{p#vnM{-Uu_$Td`1X=*^zj|$%5UqV4@~1G>nF%GJieFBwzo6r zc^5`lx`@)Ub|X>IWepAG)%s0$1{2iDdKx}y#hWrF!)t6`PMkX$m)p_M&Nag%zTsGq z-c~k&lOo+1rwrpkp{<|3$6aF?b?m*;TiT&#WW~+2ynU|otg{8gN?$F6^$O-rNQW?2 zBVKq&#{f!;GEMo2%q4ZAsXUp^mdBQcZ|59!@wl+#oP?(9pw)Pk-FNrDKignvSIKQS zNh}KWU|UpLNfKESCiN9uk<$&DD??_Kn#TK`{qkJUA<3CDMJ3d$YhPmGi~$q0F^28Z)KcGDdg&Bl;d(d zla9BIyQxpE{B&;kd2($>F;~11z{e$35jq=5mj!`^qw=|JvE9(hbFmwqq5QYV6wkqbyLg-}eJcnX%U*>frz9C=%~v*)T8je{YV_ti z)xNiUKn)(fO~--2;wDm@NZ_y$2evdxq>EE8CvCz=51u}(jW#5i&bO@Xh@|_T5?RRr zq^lGG9~PL@z0;p3M@%Xal|3Bh?Md%D+H1S+S93K$IHuqaS|#}1X5+^_O`57p-`TzTa)$+r^WM5_cA0b@-7p#_wdu5ZSzE^j7Yn^!4Pq)3q>MT!(D zwlM}L8g?^7BRV7p?O53wz`MFhb(O*&Nt+eQ^d==ySX@|{ru{JAQDI85R@>(4yGd0Q y)(6vmJH{c-`H5S9)X-MHZJfi-1I6K4@&5wOVUm!kkf7`U0000 + <>![Algolia DocSearch v4 - Ask AI screenshot](./img/askai.png) + +``` + +:::tip DocSearch v4 is opt-in + +Docusaurus v3 adds support for DocSearch v4 while keeping support for DocSearch v3. + +Existing sites using DocSearch v3 can either stay on v3 or upgrade to v4 using their package manager (npm command: `npm update @docsearch/react`). + +When using DocSearch v4, the new AskAI feature is not enabled by default: you also need to [create an AskAI assistant](https://docsearch.algolia.com/docs/v4/askai/) and add it to the [`themeConfig.algolia.askAi` config attribute](/docs/search#ask-ai). + +::: + +## i18n improvements + +In [#11316](https://github.com/facebook/docusaurus/pull/11316), we added new `i18n.localeConfigs[locale].{url,baseUrl}` config options to better support complex and multi-domain i18n deployments. Previously, Docusaurus relied on hard-coded heuristics that made sense for most i18n projects, but weren't flexible enough to accommodate all use cases, leading UX and SEO issues. It is now possible to configure each locale's deployment URL and base URL independently, overriding the default values inferred by Docusaurus: + +```ts title="docusaurus.config.js" +export default { + i18n: { + defaultLocale: 'en', + locales: ['en', 'fr'], + localeConfigs: { + en: { + // highlight-start + url: 'https://en.docusaurus.io', + baseUrl: '/', + // highlight-end + }, + fr: { + // highlight-start + url: 'https://fr.docusaurus.io', + baseUrl: '/', + // highlight-end + }, + }, + }, +}; +``` + +In [#11304](https://github.com/facebook/docusaurus/pull/11304), we optimized our i18n infrastructure with a new `i18n.localeConfigs[locale].translate` flag that is now `false` by default for sites that do not use any translations. This leads to an improved dev experience and faster builds for non-i18n sites by avoiding unnecessary file system read attempts of the `i18n` directory. + +In [#11228](https://github.com/facebook/docusaurus/pull/11228), we added a new `key` attribute to the docs sidebar items, allowing to assign explicit translation keys to each sidebar item that use the same label and would otherwise lead to translation key conflicts: + +```ts title="sidebars.js" +export default { + sidebar: [ + { + type: 'category', + label: 'API', + // highlight-next-line + key: 'api-for-feature-1', + items: [], + }, + { + type: 'category', + label: 'API', + // highlight-next-line + key: 'api-for-feature-2', + items: [], + }, + ], +}; +``` + +## Mermaid ELK layouts + +In [#11357](https://github.com/facebook/docusaurus/pull/11357), we added support for [Mermaid ELK layout algorithm](https://mermaid.js.org/intro/syntax-reference.html#supported-layout-algorithms), based on the [Eclipse Layout Kernel (ELK)](https://www.eclipse.org/elk/). Compared to the default Dagre layout, it provides more sophisticated layout capabilities and configuration options, especially useful when working with large or intricate diagrams. + +You can enable it by adding the extra `@mermaid-js/layout-elk` npm dependency, making it possible to use the `layout: elk` Mermaid diagram metadata: + +````md +```mermaid +--- +config: +# highlight-next-line + layout: elk +--- +erDiagram + CUSTOMER ||--o{ ORDER : places + ORDER ||--|{ LINE-ITEM : contains + CUSTOMER }|..|{ DELIVERY-ADDRESS : uses +``` +```` + +```mermaid +--- +config: + layout: elk +--- +erDiagram + CUSTOMER ||--o{ ORDER : places + ORDER ||--|{ LINE-ITEM : contains + CUSTOMER }|..|{ DELIVERY-ADDRESS : uses +``` + +## Translations + +- 🇧🇷 [#11315](https://github.com/facebook/docusaurus/pull/11315): Add missing Brazilian Portuguese theme translations. +- 🇺🇦 [#11305](https://github.com/facebook/docusaurus/pull/11305): Add missing Ukrainian theme translations. + +## Other changes + +Other notable changes include: + +- In [#11283](https://github.com/facebook/docusaurus/pull/11283), we added `siteConfig.markdown.hooks.{onBrokenMarkdownLinks,onBrokenMarkdownLinks}` and deprecated `siteConfig.onBrokenMarkdownLinks`. The new callback hooks also let you recover from broken links/images by returning a fallback URL. +- In [#11282](https://github.com/facebook/docusaurus/pull/11282), we added the `siteConfig.markdown.emoji` config option to disable the previously hard-coded `remark-emoji` behavior. +- In [#11397](https://github.com/facebook/docusaurus/pull/11397), we can now resolve site-aliased Markdown links starting with `@site/*`, that we already supported for ES imports. +- In [#11294](https://github.com/facebook/docusaurus/pull/11294) and [#11415](https://github.com/facebook/docusaurus/pull/11415), we upgraded to Rspack 1.5 and leveraging new Rspack config options to make Docusaurus build faster. +- In [#11356](https://github.com/facebook/docusaurus/pull/11356), we improved the display of docs sidebar items with long labels. +- In [#11405](https://github.com/facebook/docusaurus/pull/11405), we improved visual glitches caused by the `useColorMode()` hook when switching color modes, glitches that also affected your site's logo in the navbar. +- In [#11383](https://github.com/facebook/docusaurus/pull/11383), we disabled a Docusaurus Faster HTML minifier optimization that prevents your site's social card from displaying properly on some social platforms (e.g., LinkedIn). +- In [#11425](https://github.com/facebook/docusaurus/pull/11425), we added the ability for blog authors to display an email icon with a `mailto:` link (`author.socials.email`). +- In [#11422](https://github.com/facebook/docusaurus/pull/11422), we removed the `copy-text-to-clipboard` in favor of the native `navigator.clipboard` API. + +Check the **[3.9.0 changelog entry](/changelog/3.9.0)** for an exhaustive list of changes. diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index 89852250ba..c5c3d3fc80 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -664,6 +664,7 @@ export default async function createConfigAsync() { ? { // cSpell:ignore IMYF askAi: 'RgIMYFUmTfrN', + // indexName: 'docusaurus-markdown', } : {}), diff --git a/website/package.json b/website/package.json index 7c2f4aa96c..80a24e9bff 100644 --- a/website/package.json +++ b/website/package.json @@ -1,6 +1,6 @@ { "name": "website", - "version": "3.8.1", + "version": "3.9.0", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -39,20 +39,20 @@ "dependencies": { "@crowdin/cli": "^3.13.0", "@crowdin/crowdin-api-client": "^1.29.5", - "@docusaurus/core": "3.8.1", - "@docusaurus/logger": "3.8.1", - "@docusaurus/plugin-client-redirects": "3.8.1", - "@docusaurus/plugin-ideal-image": "3.8.1", - "@docusaurus/plugin-pwa": "3.8.1", - "@docusaurus/plugin-rsdoctor": "3.8.1", - "@docusaurus/preset-classic": "3.8.1", - "@docusaurus/remark-plugin-npm2yarn": "3.8.1", - "@docusaurus/theme-classic": "3.8.1", - "@docusaurus/theme-common": "3.8.1", - "@docusaurus/theme-live-codeblock": "3.8.1", - "@docusaurus/theme-mermaid": "3.8.1", - "@docusaurus/utils": "3.8.1", - "@docusaurus/utils-common": "3.8.1", + "@docusaurus/core": "3.9.0", + "@docusaurus/logger": "3.9.0", + "@docusaurus/plugin-client-redirects": "3.9.0", + "@docusaurus/plugin-ideal-image": "3.9.0", + "@docusaurus/plugin-pwa": "3.9.0", + "@docusaurus/plugin-rsdoctor": "3.9.0", + "@docusaurus/preset-classic": "3.9.0", + "@docusaurus/remark-plugin-npm2yarn": "3.9.0", + "@docusaurus/theme-classic": "3.9.0", + "@docusaurus/theme-common": "3.9.0", + "@docusaurus/theme-live-codeblock": "3.9.0", + "@docusaurus/theme-mermaid": "3.9.0", + "@docusaurus/utils": "3.9.0", + "@docusaurus/utils-common": "3.9.0", "@mermaid-js/layout-elk": "^0.1.9", "clsx": "^2.0.0", "color": "^4.2.3", @@ -84,8 +84,8 @@ ] }, "devDependencies": { - "@docusaurus/eslint-plugin": "3.8.1", - "@docusaurus/tsconfig": "3.8.1", + "@docusaurus/eslint-plugin": "3.9.0", + "@docusaurus/tsconfig": "3.9.0", "@types/color": "^3.0.4", "@types/jest": "^29.5.3", "cross-env": "^7.0.3", diff --git a/website/versioned_docs/version-3.9.0/advanced/architecture.mdx b/website/versioned_docs/version-3.9.0/advanced/architecture.mdx new file mode 100644 index 0000000000..8d1f8bdb2d --- /dev/null +++ b/website/versioned_docs/version-3.9.0/advanced/architecture.mdx @@ -0,0 +1,28 @@ +--- +description: How Docusaurus works to build your app +--- + +# Architecture + +```mdx-code-block +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Zoom from 'react-medium-image-zoom'; +``` + + + +![Architecture overview](/img/architecture.png) + + + +This diagram shows how Docusaurus works to build your app. Plugins each collect their content and emit JSON data; themes provide layout components which receive the JSON data as route modules. The bundler bundles all the components and emits a server bundle and a client bundle. + +Although you (either plugin authors or site creators) are writing JavaScript all the time, bear in mind that the JS is actually run in different environments: + +- All plugin lifecycle methods are run in Node. Therefore, until we support ES Modules in our codebase, plugin source code must be provided as ES modules that can be imported, or CommonJS that can be `require`'d. +- The theme code is built with Webpack. They can be provided as ESM—following React conventions. + +Plugin code and theme code never directly import each other: they only communicate through protocols (in our case, through JSON temp files and calls to `addRoute`). A useful mental model is to imagine that the plugins are not written in JavaScript, but in another language like Rust. The only way to interact with plugins for the user is through `docusaurus.config.js`, which itself is run in Node (hence you can use `require` and pass callbacks as plugin options). + +During bundling, the config file itself is serialized and bundled, allowing the theme to access config options like `themeConfig` or `baseUrl` through [`useDocusaurusContext()`](../docusaurus-core.mdx#useDocusaurusContext). However, the `siteConfig` object only contains **serializable values** (values that are preserved after `JSON.stringify()`). Functions, regexes, etc. would be lost on the client side. The `themeConfig` is designed to be entirely serializable. diff --git a/website/versioned_docs/version-3.9.0/advanced/client.mdx b/website/versioned_docs/version-3.9.0/advanced/client.mdx new file mode 100644 index 0000000000..f4d37d296d --- /dev/null +++ b/website/versioned_docs/version-3.9.0/advanced/client.mdx @@ -0,0 +1,184 @@ +--- +description: How the Docusaurus client is structured +--- + +# Client architecture + +## Theme aliases {#theme-aliases} + +A theme works by exporting a set of components, e.g. `Navbar`, `Layout`, `Footer`, to render the data passed down from plugins. Docusaurus and users use these components by importing them using the `@theme` webpack alias: + +```js +import Navbar from '@theme/Navbar'; +``` + +The alias `@theme` can refer to a few directories, in the following priority: + +1. A user's `website/src/theme` directory, which is a special directory that has the higher precedence. +2. A Docusaurus theme package's `theme` directory. +3. Fallback components provided by Docusaurus core (usually not needed). + +This is called a _layered architecture_: a higher-priority layer providing the component would shadow a lower-priority layer, making swizzling possible. Given the following structure: + +``` +website +├── node_modules +│ └── @docusaurus/theme-classic +│ └── theme +│ └── Navbar.js +└── src + └── theme + └── Navbar.js +``` + +`website/src/theme/Navbar.js` takes precedence whenever `@theme/Navbar` is imported. This behavior is called component swizzling. If you are familiar with Objective C where a function's implementation can be swapped during runtime, it's the exact same concept here with changing the target `@theme/Navbar` is pointing to! + +We already talked about how the "userland theme" in `src/theme` can re-use a theme component through the [`@theme-original`](../swizzling.mdx#wrapping) alias. One theme package can also wrap a component from another theme, by importing the component from the initial theme, using the `@theme-init` import. + +Here's an example of using this feature to enhance the default theme `CodeBlock` component with a `react-live` playground feature. + +```js +import InitialCodeBlock from '@theme-init/CodeBlock'; +import React from 'react'; + +export default function CodeBlock(props) { + return props.live ? ( + + ) : ( + + ); +} +``` + +Check the code of `@docusaurus/theme-live-codeblock` for details. + +:::warning + +Unless you want to publish a re-usable "theme enhancer" (like `@docusaurus/theme-live-codeblock`), you likely don't need `@theme-init`. + +::: + +It can be quite hard to wrap your mind around these aliases. Let's imagine the following case with a super convoluted setup with three themes/plugins and the site itself all trying to define the same component. Internally, Docusaurus loads these themes as a "stack". + +```text ++-------------------------------------------------+ +| `website/src/theme/CodeBlock.js` | <-- `@theme/CodeBlock` always points to the top ++-------------------------------------------------+ +| `theme-live-codeblock/theme/CodeBlock/index.js` | <-- `@theme-original/CodeBlock` points to the topmost non-swizzled component ++-------------------------------------------------+ +| `plugin-awesome-codeblock/theme/CodeBlock.js` | ++-------------------------------------------------+ +| `theme-classic/theme/CodeBlock/index.js` | <-- `@theme-init/CodeBlock` always points to the bottom ++-------------------------------------------------+ +``` + +The components in this "stack" are pushed in the order of `preset plugins > preset themes > plugins > themes > site`, so the swizzled component in `website/src/theme` always comes out on top because it's loaded last. + +`@theme/*` always points to the topmost component—when `CodeBlock` is swizzled, all other components requesting `@theme/CodeBlock` receive the swizzled version. + +`@theme-original/*` always points to the topmost non-swizzled component. That's why you can import `@theme-original/CodeBlock` in the swizzled component—it points to the next one in the "component stack", a theme-provided one. Plugin authors should not try to use this because your component could be the topmost component and cause a self-import. + +`@theme-init/*` always points to the bottommost component—usually, this comes from the theme or plugin that first provides this component. Individual plugins / themes trying to enhance code block can safely use `@theme-init/CodeBlock` to get its basic version. Site creators should generally not use this because you likely want to enhance the _topmost_ instead of the _bottommost_ component. It's also possible that the `@theme-init/CodeBlock` alias does not exist at all—Docusaurus only creates it when it points to a different one from `@theme-original/CodeBlock`, i.e. when it's provided by more than one theme. We don't waste aliases! + +## Client modules {#client-modules} + +Client modules are part of your site's bundle, just like theme components. However, they are usually side-effect-ful. Client modules are anything that can be `import`ed by Webpack—CSS, JS, etc. JS scripts usually work on the global context, like registering event listeners, creating global variables... + +These modules are imported globally before React even renders the initial UI. + +```js title="@docusaurus/core/App.tsx" +// How it works under the hood +import '@generated/client-modules'; +``` + +Plugins and sites can both declare client modules, through [`getClientModules`](../api/plugin-methods/lifecycle-apis.mdx#getClientModules) and [`siteConfig.clientModules`](../api/docusaurus.config.js.mdx#clientModules), respectively. + +Client modules are called during server-side rendering as well, so remember to check the [execution environment](./ssg.mdx#escape-hatches) before accessing client-side globals. + +```js title="mySiteGlobalJs.js" +import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; + +if (ExecutionEnvironment.canUseDOM) { + // As soon as the site loads in the browser, register a global event listener + window.addEventListener('keydown', (e) => { + if (e.code === 'Period') { + location.assign(location.href.replace('.com', '.dev')); + } + }); +} +``` + +CSS stylesheets imported as client modules are [global](../styling-layout.mdx#global-styles). + +```css title="mySiteGlobalCss.css" +/* This stylesheet is global. */ +.globalSelector { + color: red; +} +``` + +### Client module lifecycles {#client-module-lifecycles} + +Besides introducing side-effects, client modules can optionally export two lifecycle functions: `onRouteUpdate` and `onRouteDidUpdate`. + +Because Docusaurus builds a single-page application, `script` tags will only be executed the first time the page loads, but will not re-execute on page transitions. These lifecycles are useful if you have some imperative JS logic that should execute every time a new page has loaded, e.g., to manipulate DOM elements, to send analytics data, etc. + +For every route transition, there will be several important timings: + +1. The user clicks a link, which causes the router to change its current location. +2. Docusaurus preloads the next route's assets, while keeping displaying the current page's content. +3. The next route's assets have loaded. +4. The new location's route component gets rendered to DOM. + +`onRouteUpdate` will be called at event (2), and `onRouteDidUpdate` will be called at (4). They both receive the current location and the previous location (which can be `null`, if this is the first screen). + +`onRouteUpdate` can optionally return a "cleanup" callback, which will be called at (3). For example, if you want to display a progress bar, you can start a timeout in `onRouteUpdate`, and clear the timeout in the callback. (The classic theme already provides an `nprogress` integration this way.) + +Note that the new page's DOM is only available during event (4). If you need to manipulate the new page's DOM, you'll likely want to use `onRouteDidUpdate`, which will be fired as soon as the DOM on the new page has mounted. + +```js title="myClientModule.js" +export function onRouteDidUpdate({location, previousLocation}) { + // Don't execute if we are still on the same page; the lifecycle may be fired + // because the hash changes (e.g. when navigating between headings) + if (location.pathname !== previousLocation?.pathname) { + const title = document.getElementsByTagName('h1')[0]; + if (title) { + title.innerText += '❤️'; + } + } +} + +export function onRouteUpdate({location, previousLocation}) { + if (location.pathname !== previousLocation?.pathname) { + const progressBarTimeout = window.setTimeout(() => { + nprogress.start(); + }, delay); + return () => window.clearTimeout(progressBarTimeout); + } + return undefined; +} +``` + +Or, if you are using TypeScript and you want to leverage contextual typing: + +```ts title="myClientModule.ts" +import type {ClientModule} from '@docusaurus/types'; + +const module: ClientModule = { + onRouteUpdate({location, previousLocation}) { + // ... + }, + onRouteDidUpdate({location, previousLocation}) { + // ... + }, +}; +export default module; +``` + +Both lifecycles will fire on first render, but they will not fire on server-side, so you can safely access browser globals in them. + +:::tip Prefer using React + +Client module lifecycles are purely imperative, and you can't use React hooks or access React contexts within them. If your operations are state-driven or involve complicated DOM manipulations, you should consider [swizzling components](../swizzling.mdx) instead. + +::: diff --git a/website/versioned_docs/version-3.9.0/advanced/index.mdx b/website/versioned_docs/version-3.9.0/advanced/index.mdx new file mode 100644 index 0000000000..b5e5deb222 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/advanced/index.mdx @@ -0,0 +1,11 @@ +# Advanced Tutorials + +This section is not going to be very structured, but we will cover the following topics: + +```mdx-code-block +import DocCardList from '@theme/DocCardList'; + + +``` + +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.mdx) or other architecture details. Don't panic if you don't understand everything😉 diff --git a/website/versioned_docs/version-3.9.0/advanced/plugins.mdx b/website/versioned_docs/version-3.9.0/advanced/plugins.mdx new file mode 100644 index 0000000000..1f09ea723a --- /dev/null +++ b/website/versioned_docs/version-3.9.0/advanced/plugins.mdx @@ -0,0 +1,129 @@ +# Plugins + +Plugins are the building blocks of features in a Docusaurus site. Each plugin handles its own individual feature. Plugins may work and be distributed as part of a bundle via presets. + +## Creating plugins {#creating-plugins} + +A plugin is a function that takes two parameters: `context` and `options`. It returns a plugin instance object (or a promise). You can create plugins as functions or modules. For more information, refer to the [plugin method references section](../api/plugin-methods/README.mdx). + +### Function definition {#function-definition} + +You can use a plugin as a function directly included in the Docusaurus config file: + +```js title="docusaurus.config.js" +export default { + // ... + plugins: [ + // highlight-start + async function myPlugin(context, options) { + // ... + return { + name: 'my-plugin', + async loadContent() { + // ... + }, + async contentLoaded({content, actions}) { + // ... + }, + /* other lifecycle API */ + }; + }, + // highlight-end + ], +}; +``` + +### Module definition {#module-definition} + +You can use a plugin as a module path referencing a separate file or npm package: + +```js title="docusaurus.config.js" +export default { + // ... + plugins: [ + // without options: + './my-plugin', + // or with options: + ['./my-plugin', options], + ], +}; +``` + +Then in the folder `my-plugin`, you can create an `index.js` such as this: + +```js title="my-plugin/index.js" +export default async function myPlugin(context, options) { + // ... + return { + name: 'my-plugin', + async loadContent() { + /* ... */ + }, + async contentLoaded({content, actions}) { + /* ... */ + }, + /* other lifecycle API */ + }; +} +``` + +--- + +You can view all plugins installed in your site using the [debug plugin's metadata panel](/__docusaurus/debug/metadata). + +Plugins come as several types: + +- `package`: an external package you installed +- `project`: a plugin you created in your project, given to Docusaurus as a local file path +- `local`: a plugin created using the function definition +- `synthetic`: a "fake plugin" Docusaurus created internally, so we take advantage of our modular architecture and don't let the core do much special work. You won't see this in the metadata because it's an implementation detail. + +You can access them on the client side with `useDocusaurusContext().siteMetadata.pluginVersions`. + +## Plugin design {#plugin-design} + +Docusaurus' implementation of the plugins system provides us with a convenient way to hook into the website's lifecycle to modify what goes on during development/build, which involves (but is not limited to) extending the webpack config, modifying the data loaded, and creating new components to be used in a page. + +### Theme design {#theme-design} + +When plugins have loaded their content, the data is made available to the client side through actions like [`createData` + `addRoute`](../api/plugin-methods/lifecycle-apis.mdx#addRoute) or [`setGlobalData`](../api/plugin-methods/lifecycle-apis.mdx#setGlobalData). This data has to be _serialized_ to plain strings, because [plugins and themes run in different environments](./architecture.mdx). Once the data arrives on the client side, the rest becomes familiar to React developers: data is passed along components, components are bundled with Webpack, and rendered to the window through `ReactDOM.render`... + +**Themes provide the set of UI components to render the content.** Most content plugins need to be paired with a theme in order to be actually useful. The UI is a separate layer from the data schema, which makes swapping designs easy. + +For example, a Docusaurus blog may consist of a blog plugin and a blog theme. + +:::note + +This is a contrived example: in practice, `@docusaurus/theme-classic` provides the theme for docs, blog, and layouts. + +::: + +```js title="docusaurus.config.js" +export default { + // highlight-next-line + themes: ['theme-blog'], + plugins: ['plugin-content-blog'], +}; +``` + +And if you want to use Bootstrap styling, you can swap out the theme with `theme-blog-bootstrap` (another fictitious non-existing theme): + +```js title="docusaurus.config.js" +export default { + // highlight-next-line + themes: ['theme-blog-bootstrap'], + plugins: ['plugin-content-blog'], +}; +``` + +Now, although the theme receives the same data from the plugin, how the theme chooses to _render_ the data as UI can be drastically different. + +While themes share the exact same lifecycle methods with plugins, themes' implementations can look very different from those of plugins based on themes' designed objectives. + +Themes are designed to complete the build of your Docusaurus site and supply the components used by your site, plugins, and the themes themselves. A theme still acts like a plugin and exposes some lifecycle methods, but most likely they would not use [`loadContent`](../api/plugin-methods/lifecycle-apis.mdx#loadContent), since they only receive data from plugins, but don't generate data themselves; themes are typically also accompanied by an `src/theme` directory full of components, which are made known to the core through the [`getThemePath`](../api/plugin-methods/extend-infrastructure.mdx#getThemePath) lifecycle. + +To summarize: + +- Themes share the same lifecycle methods with Plugins +- Themes are run after all existing Plugins +- Themes add component aliases by providing `getThemePath`. diff --git a/website/versioned_docs/version-3.9.0/advanced/routing.mdx b/website/versioned_docs/version-3.9.0/advanced/routing.mdx new file mode 100644 index 0000000000..ea62c06f35 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/advanced/routing.mdx @@ -0,0 +1,289 @@ +--- +description: "Docusaurus' routing system follows single-page application conventions: one route, one component." +--- + +# Routing + +```mdx-code-block +import Link from '@docusaurus/Link'; +import {useLatestVersion, useActiveDocContext} from '@docusaurus/plugin-content-docs/client'; +import {useLocation} from '@docusaurus/router'; +import BrowserWindow from '@site/src/components/BrowserWindow'; +``` + +Docusaurus' routing system follows single-page application conventions: one route, one component. In this section, we will begin by talking about routing within the three content plugins (docs, blog, and pages), and then go beyond to talk about the underlying routing system. + +## Routing in content plugins {#routing-in-content-plugins} + +Every content plugin provides a `routeBasePath` option. It defines where the plugins append their routes to. By default, the docs plugin puts its routes under `/docs`; the blog plugin, `/blog`; and the pages plugin, `/`. You can think about the route structure like this: + +```mermaid +graph LR; + A(["https://example.com/"]) + B(["/base-url/"]) + C(["/docs/"]) + D(["/blog/"]) + E(["/"]) + F["All docs
    routes"] + G["All blog
    routes"] + H["All pages
    routes"] + A---B; + B---C; + B---D; + B---E; + C---F; + D---G; + E---H; +``` + +Any route will be matched against this nested route config until a good match is found. For example, when given a route `/docs/configuration`, Docusaurus first enters the `/docs` branch, and then searches among the subroutes created by the docs plugin. + +Changing `routeBasePath` can effectively alter your site's route structure. For example, in [Docs-only mode](../guides/docs/docs-introduction.mdx#docs-only-mode), we mentioned that configuring `routeBasePath: '/'` for docs means that all routes that the docs plugin create would not have the `/docs` prefix, yet it doesn't prevent you from having more subroutes like `/blog` created by other plugins. + +Next, let's look at how the three plugins structure their own "boxes of subroutes". + +### Pages routing {#pages-routing} + +Pages routing are straightforward: the file paths directly map to URLs, without any other way to customize. See the [pages docs](../guides/creating-pages.mdx#routing) for more information. + +The component used for Markdown pages is `@theme/MDXPage`. React pages are directly used as the route's component. + +### Blog routing {#blog-routing} + +The blog creates the following routes: + +- **Posts list pages**: `/`, `/page/2`, `/page/3`... + - The route is customizable through the `pageBasePath` option. + - The component is `@theme/BlogListPage`. +- **Post pages**: `/2021/11/21/algolia-docsearch-migration`, `/2021/05/12/announcing-docusaurus-two-beta`... + - Generated from each Markdown post. + - The routes are fully customizable through the `slug` front matter. + - The component is `@theme/BlogPostPage`. +- **Tags list page**: `/tags` + - The route is customizable through the `tagsBasePath` option. + - The component is `@theme/BlogTagsListPage`. +- **Tag pages**: `/tags/adoption`, `/tags/beta`... + - Generated through the tags defined in each post's front matter. + - The routes always have base defined in `tagsBasePath`, but the subroutes are customizable through the tag's `permalink` field. + - The component is `@theme/BlogTagsPostsPage`. +- **Archive page**: `/archive` + - The route is customizable through the `archiveBasePath` option. + - The component is `@theme/BlogArchivePage`. + +### Docs routing {#docs-routing} + +The docs is the only plugin that creates **nested routes**. At the top, it registers [**version paths**](../guides/docs/versioning.mdx): `/`, `/next`, `/2.0.0-beta.13`... which provide the version context, including the layout and sidebar. This ensures that when switching between individual docs, the sidebar's state is preserved, and that you can switch between versions through the navbar dropdown while staying on the same doc. The component used is `@theme/DocPage`. + +```mdx-code-block +export const URLPath = () => {useLocation().pathname}; + +export const FilePath = () => { + const currentVersion = useActiveDocContext('default').activeVersion.name; + return {currentVersion === 'current' ? './docs/' : `./versioned_docs/version-${currentVersion}/`}advanced/routing.md; +} +``` + +The individual docs are rendered in the remaining space after the navbar, footer, sidebar, etc. have all been provided by the `DocPage` component. For example, this page, , is generated from the file at . The component used is `@theme/DocItem`. + +The doc's `slug` front matter customizes the last part of the route, but the base route is always defined by the plugin's `routeBasePath` and the version's `path`. + +### File paths and URL paths {#file-paths-and-url-paths} + +Throughout the documentation, we always try to be unambiguous about whether we are talking about file paths or URL paths. Content plugins usually map file paths directly to URL paths, for example, `./docs/advanced/routing.md` will become `/docs/advanced/routing`. However, with `slug`, you can make URLs totally decoupled from the file structure. + +When writing links in Markdown, you could either mean a _file path_, or a _URL path_, which Docusaurus would use several heuristics to determine. + +- If the path has a `@site` prefix, it is _always_ an asset file path. +- If the path has an `http(s)://` prefix, it is _always_ a URL path. +- If the path doesn't have an extension, it is a URL path. For example, a link `[page](../plugins)` on a page with URL `/docs/advanced/routing` will link to `/docs/plugins`. Docusaurus will only detect broken links when building your site (when it knows the full route structure), but will make no assumptions about the existence of a file. It is exactly equivalent to writing `
    page` in a JSX file. +- If the path has an `.md(x)` extension, Docusaurus would try to resolve that Markdown file to a URL, and replace the file path with a URL path. +- If the path has any other extension, Docusaurus would treat it as [an asset](../guides/markdown-features/markdown-features-assets.mdx) and bundle it. + +The following directory structure may help you visualize this file → URL mapping. Assume that there's no slug customization in any page. + +

    + +A sample site structure + +```bash +. +├── blog # blog plugin has routeBasePath: '/blog' +│ ├── 2019-05-28-first-blog-post.md # -> /blog/2019/05/28/first-blog-post +│ ├── 2019-05-29-long-blog-post.md # -> /blog/2019/05/29/long-blog-post +│ ├── 2021-08-01-mdx-blog-post.mdx # -> /blog/2021/08/01/mdx-blog-post +│ └── 2021-08-26-welcome +│ ├── docusaurus-plushie-banner.jpeg +│ └── index.md # -> /blog/2021/08/26/welcome +├── docs # docs plugin has routeBasePath: '/docs'; current version has base path '/' +│ ├── intro.md # -> /docs/intro +│ ├── tutorial-basics +│ │ ├── _category_.json +│ │ ├── congratulations.md # -> /docs/tutorial-basics/congratulations +│ │ └── markdown-features.mdx # -> /docs/tutorial-basics/markdown-features +│ └── tutorial-extras +│ ├── _category_.json +│ ├── manage-docs-versions.md # -> /docs/tutorial-extras/manage-docs-versions +│ └── translate-your-site.md # -> /docs/tutorial-extras/translate-your-site +├── src +│ └── pages # pages plugin has routeBasePath: '/' +│ ├── index.module.css +│ ├── index.tsx # -> / +│ └── markdown-page.md # -> /markdown-page +└── versioned_docs + └── version-1.0.0 # version has base path '/1.0.0' + ├── intro.md # -> /docs/1.0.0/intro + ├── tutorial-basics + │ ├── _category_.json + │ ├── congratulations.md # -> /docs/1.0.0/tutorial-basics/congratulations + │ └── markdown-features.mdx # -> /docs/1.0.0/tutorial-basics/markdown-features + └── tutorial-extras + ├── _category_.json + ├── manage-docs-versions.md # -> /docs/1.0.0/tutorial-extras/manage-docs-versions + └── translate-your-site.md # -> /docs/1.0.0/tutorial-extras/translate-your-site +``` + +
    + +So much about content plugins. Let's take one step back and talk about how routing works in a Docusaurus app in general. + +## Routes become HTML files {#routes-become-html-files} + +Because Docusaurus is a server-side rendering framework, all routes generated will be server-side rendered into static HTML files. If you are familiar with the behavior of HTTP servers like [Apache2](https://httpd.apache.org/docs/trunk/getting-started.html), you will understand how this is done: when the browser sends a request to the route `/docs/advanced/routing`, the server interprets that as request for the HTML file `/docs/advanced/routing/index.html`, and returns that. + +The `/docs/advanced/routing` route can correspond to either `/docs/advanced/routing/index.html` or `/docs/advanced/routing.html`. Some hosting providers differentiate between them using the presence of a trailing slash, and may or may not tolerate the other. Read more in the [trailing slash guide](https://github.com/slorber/trailing-slash-guide). + +For example, the build output of the directory above is (ignoring other assets and JS bundle): + +
    + +Output of the above workspace + +```bash +build +├── 404.html # /404/ +├── blog +│ ├── archive +│ │ └── index.html # /blog/archive/ +│ ├── first-blog-post +│ │ └── index.html # /blog/first-blog-post/ +│ ├── index.html # /blog/ +│ ├── long-blog-post +│ │ └── index.html # /blog/long-blog-post/ +│ ├── mdx-blog-post +│ │ └── index.html # /blog/mdx-blog-post/ +│ ├── tags +│ │ ├── docusaurus +│ │ │ └── index.html # /blog/tags/docusaurus/ +│ │ ├── hola +│ │ │ └── index.html # /blog/tags/hola/ +│ │ └── index.html # /blog/tags/ +│ └── welcome +│ └── index.html # /blog/welcome/ +├── docs +│ ├── 1.0.0 +│ │ ├── intro +│ │ │ └── index.html # /docs/1.0.0/intro/ +│ │ ├── tutorial-basics +│ │ │ ├── congratulations +│ │ │ │ └── index.html # /docs/1.0.0/tutorial-basics/congratulations/ +│ │ │ └── markdown-features +│ │ │ └── index.html # /docs/1.0.0/tutorial-basics/markdown-features/ +│ │ └── tutorial-extras +│ │ ├── manage-docs-versions +│ │ │ └── index.html # /docs/1.0.0/tutorial-extras/manage-docs-versions/ +│ │ └── translate-your-site +│ │ └── index.html # /docs/1.0.0/tutorial-extras/translate-your-site/ +│ ├── intro +│ │ └── index.html # /docs/1.0.0/intro/ +│ ├── tutorial-basics +│ │ ├── congratulations +│ │ │ └── index.html # /docs/tutorial-basics/congratulations/ +│ │ └── markdown-features +│ │ └── index.html # /docs/tutorial-basics/markdown-features/ +│ └── tutorial-extras +│ ├── manage-docs-versions +│ │ └── index.html # /docs/tutorial-extras/manage-docs-versions/ +│ └── translate-your-site +│ └── index.html # /docs/tutorial-extras/translate-your-site/ +├── index.html # / +└── markdown-page + └── index.html # /markdown-page/ +``` + +
    + +If `trailingSlash` is set to `false`, the build would emit `intro.html` instead of `intro/index.html`. + +All HTML files will reference its JS assets using absolute URLs, so in order for the correct assets to be located, you have to configure the `baseUrl` field. Note that `baseUrl` doesn't affect the emitted bundle's file structure: the base URL is one level above the Docusaurus routing system. You can see the aggregate of `url` and `baseUrl` as the actual location of your Docusaurus site. + +For example, the emitted HTML would contain links like ``. Because absolute URLs are resolved from the host, if the bundle placed under the path `https://example.com/base/`, the link will point to `https://example.com/assets/js/runtime~main.7ed5108a.js`, which is, well, non-existent. By specifying `/base/` as base URL, the link will correctly point to `/base/assets/js/runtime~main.7ed5108a.js`. + +Localized sites have the locale as part of the base URL as well. For example, `https://docusaurus.io/zh-CN/docs/advanced/routing/` has base URL `/zh-CN/`. + +## Generating and accessing routes {#generating-and-accessing-routes} + +The `addRoute` lifecycle action is used to generate routes. It registers a piece of route config to the route tree, giving a route, a component, and props that the component needs. The props and the component are both provided as paths for the bundler to `require`, because as explained in the [architecture overview](architecture.mdx), server and client only communicate through temp files. + +All routes are aggregated in `.docusaurus/routes.js`, which you can view with the debug plugin's [routes panel](/__docusaurus/debug/routes). + +On the client side, we offer `@docusaurus/router` to access the page's route. `@docusaurus/router` is a re-export of the [`react-router-dom`](https://www.npmjs.com/package/react-router-dom/v/5.3.0) package. For example, you can use `useLocation` to get the current page's [location](https://developer.mozilla.org/en-US/docs/Web/API/Location), and `useHistory` to access the [history object](https://developer.mozilla.org/en-US/docs/Web/API/History). (They are not the same as the browser API, although similar in functionality. Refer to the React Router documentation for specific APIs.) + +This API is **SSR safe**, as opposed to the browser-only `window.location`. + +```jsx title="myComponent.js" +import React from 'react'; +import {useLocation} from '@docusaurus/router'; + +export function PageRoute() { + // React router provides the current component's route, even in SSR + const location = useLocation(); + return ( + + We are currently on {location.pathname} + + ); +} +``` + +```mdx-code-block +export function PageRoute() { + const location = useLocation(); + return ( + + We are currently on {location.pathname} + + ); +} + + + + + + +``` + +## Escaping from SPA redirects {#escaping-from-spa-redirects} + +Docusaurus builds a [single-page application](https://developer.mozilla.org/en-US/docs/Glossary/SPA), where route transitions are done through the `history.push()` method of React router. This operation is done on the client side. However, the prerequisite for a route transition to happen this way is that the target URL is known to our router. Otherwise, the router catches this path and displays a 404 page instead. + +If you put some HTML pages under the `static` folder, they will be copied to the build output and therefore become accessible as part of your website, yet it's not part of the Docusaurus route system. We provide a `pathname://` protocol that allows you to redirect to another part of your domain in a non-SPA fashion, as if this route is an external link. + +```md +- [pathname:///pure-html](pathname:///pure-html) +``` + + + +- [`pathname:///pure-html`](pathname:///pure-html) + + + +The `pathname://` protocol is useful for referencing any content in the static folder. For example, Docusaurus would convert [all Markdown static assets to require() calls](../guides/markdown-features/markdown-features-assets.mdx#static-assets). You can use `pathname://` to keep it a regular link instead of being hashed by Webpack. + +```md title="my-doc.md" +![An image from the static](pathname:///img/docusaurus.png) + +[An asset from the static](pathname:///files/asset.pdf) +``` + +Docusaurus will only strip the `pathname://` prefix without processing the content. diff --git a/website/versioned_docs/version-3.9.0/advanced/ssg.mdx b/website/versioned_docs/version-3.9.0/advanced/ssg.mdx new file mode 100644 index 0000000000..07931249bb --- /dev/null +++ b/website/versioned_docs/version-3.9.0/advanced/ssg.mdx @@ -0,0 +1,218 @@ +--- +sidebar_label: Static site generation +description: Docusaurus statically renders your React code into HTML, allowing faster load speed and better SEO. +--- + +# Static site generation (SSG) + +In [architecture](architecture.mdx), we mentioned that the theme is run in Webpack. But beware: that doesn't mean it always has access to browser globals! The theme is built twice: + +- During **server-side rendering**, the theme is compiled in a sandbox called [React DOM Server](https://reactjs.org/docs/react-dom-server.html). You can see this as a "headless browser", where there is no `window` or `document`, only React. SSR produces static HTML pages. +- During **client-side rendering**, the theme is compiled to JavaScript that gets eventually executed in the browser, so it has access to browser variables. + +:::info SSR or SSG? + +_Server-side rendering_ and _static site generation_ can be different concepts, but we use them interchangeably. + +Strictly speaking, Docusaurus is a static site generator, because there's no server-side runtime—we statically render to HTML files that are deployed on a CDN, instead of dynamically pre-rendering on each request. This differs from the working model of [Next.js](https://nextjs.org/). + +::: + +Therefore, while you probably know not to access Node globals like `process` ([or can we?](#node-env)) or the `'fs'` module, you can't freely access browser globals either. + +```jsx +import React from 'react'; + +export default function WhereAmI() { + return {window.location.href}; +} +``` + +This looks like idiomatic React, but if you run `docusaurus build`, you will get an error: + +``` +ReferenceError: window is not defined +``` + +This is because during server-side rendering, the Docusaurus app isn't actually run in browser, and it doesn't know what `window` is. + +```mdx-code-block +
    +What about process.env.NODE_ENV? +``` + +One exception to the "no Node globals" rule is `process.env.NODE_ENV`. In fact, you can use it in React, because Webpack injects this variable as a global: + +```jsx +import React from 'react'; + +export default function expensiveComp() { + if (process.env.NODE_ENV === 'development') { + return <>This component is not shown in development; + } + const res = someExpensiveOperationThatLastsALongTime(); + return <>{res}; +} +``` + +During Webpack build, the `process.env.NODE_ENV` will be replaced with the value, either `'development'` or `'production'`. You will then get different build results after dead code elimination: + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +```mdx-code-block + + +``` + +```diff +import React from 'react'; + +export default function expensiveComp() { + // highlight-next-line + if ('development' === 'development') { ++ return <>This component is not shown in development; + } +- const res = someExpensiveOperationThatLastsALongTime(); +- return <>{res}; +} +``` + +```mdx-code-block + + +``` + +```diff +import React from 'react'; + +export default function expensiveComp() { + // highlight-next-line +- if ('production' === 'development') { +- return <>This component is not shown in development; +- } ++ const res = someExpensiveOperationThatLastsALongTime(); ++ return <>{res}; +} +``` + +```mdx-code-block + + +
    +``` + +## Understanding SSR {#understanding-ssr} + +React is not just a dynamic UI runtime—it's also a templating engine. Because Docusaurus sites mostly contain static contents, it should be able to work without any JavaScript (which React runs in), but only plain HTML/CSS. And that's what server-side rendering offers: statically rendering your React code into HTML, without any dynamic content. An HTML file has no concept of client state (it's purely markup), hence it shouldn't rely on browser APIs. + +These HTML files are the first to arrive at the user's browser screen when a URL is visited (see [routing](routing.mdx)). Afterwards, the browser fetches and runs other JS code to provide the "dynamic" parts of your site—anything implemented with JavaScript. However, before that, the main content of your page is already visible, allowing faster loading. + +In CSR-only apps, all DOM elements are generated on client side with React, and the HTML file only ever contains one root element for React to mount DOM to; in SSR, React is already facing a fully built HTML page, and it only needs to correlate the DOM elements with the virtual DOM in its model. This step is called "hydration". After React has hydrated the static markup, the app starts to work as any normal React app. + +Note that Docusaurus is ultimately a single-page application, so static site generation is only an optimization (_progressive enhancement_, as it's called), but our functionality does not fully depend on those HTML files. This is contrary to site generators like [Jekyll](https://jekyllrb.com/) and [Docusaurus v1](https://v1.docusaurus.io/), where all files are statically transformed to markup, and interactiveness is added through external JavaScript linked with ` + <% }); %> + <%~ it.postBodyTags %> + +`, +}; +``` + +### `titleDelimiter` {#titleDelimiter} + +- Type: `string` + +Will be used as title delimiter in the generated `` tag. + +Example: + +```js title="docusaurus.config.js" +export default { + titleDelimiter: '🦖', // Defaults to `|` +}; +``` + +### `baseUrlIssueBanner` {#baseUrlIssueBanner} + +- Type: `boolean` + +When enabled, will show a banner in case your site can't load its CSS or JavaScript files, which is a very common issue, often related to a wrong `baseUrl` in site config. + +Example: + +```js title="docusaurus.config.js" +export default { + baseUrlIssueBanner: true, // Defaults to `true` +}; +``` + +![A sample base URL issue banner. The style is very raw since the stylesheets failed to load. The text says "Your Docusaurus site did not load properly... Current configured baseUrl = / (default value); We suggest trying baseUrl = /build/](/img/baseUrlIssueBanner.png) + +:::warning + +This banner needs to inline CSS / JS in case all asset loading fails due to wrong base URL. + +If you have a strict [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP), you should rather disable it. + +::: diff --git a/website/versioned_docs/version-3.9.0/api/misc/_category_.yml b/website/versioned_docs/version-3.9.0/api/misc/_category_.yml new file mode 100644 index 0000000000..2fb3073764 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/misc/_category_.yml @@ -0,0 +1,2 @@ +label: Miscellaneous +position: 4 diff --git a/website/versioned_docs/version-3.9.0/api/misc/create-docusaurus.mdx b/website/versioned_docs/version-3.9.0/api/misc/create-docusaurus.mdx new file mode 100644 index 0000000000..c79540e564 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/misc/create-docusaurus.mdx @@ -0,0 +1,58 @@ +--- +sidebar_position: 0 +slug: /api/misc/create-docusaurus +--- + +# 📦 create-docusaurus + +A scaffolding utility to help you instantly set up a functional Docusaurus app. + +## Usage {#usage} + +```bash +npx create-docusaurus@latest [name] [template] [rootDir] +``` + +The `name` argument will be used as the site's path as well as the `name` field in the created app's package.json. It can be an absolute path, or a path relative to `rootDir`. + +The `template` argument can be one of the following: + +- `classic`: Uses the classic template (recommended) +- `facebook`: Uses the Facebook/Meta template, which contains some Meta-specific setup +- A git repo URL (beginning with `https://` or `git@`), which can be cloned to the destination +- A local file path relative to CWD, which contains the files to be copied to destination + +The `rootDir` will be used to resolve the absolute path to the site directory. The default is CWD. + +:::warning + +This command should be preferably used in an interactive shell so all features are available. + +::: + +## Options {#options} + +### `-t, --typescript` {#typescript} + +Used when the template argument is a recognized name. Currently, only `classic` provides a TypeScript variant. + +### `-g, --git-strategy` {#git-strategy} + +Used when the template argument is a git repo. It needs to be one of: + +- `deep`: preserves full git history +- `shallow`: clones with `--depth=1` +- `copy`: does a shallow clone, but does not create a git repo +- `custom`: enter your custom git clone command. We will prompt you for it. You can write something like `git clone --depth 10`, and we will append the repository URL and destination directory. + +### `-p, --package-manager` {#package-manager} + +Value should be one of `npm`, `yarn`, `pnpm`, or `bun`. If it's not explicitly provided, Docusaurus will infer one based on: + +- The lockfile already present in the CWD (e.g. if you are setting up website in an existing project) +- The command used to invoke `create-docusaurus` (e.g. `npm init`, `npx`, `yarn create`, `bunx`, etc.) +- Interactive prompting, in case all heuristics are not present + +### `-s, --skip-install` {#skip-install} + +If provided, Docusaurus will not automatically install dependencies after creating the app. The `--package-manager` option is only useful when you are actually installing dependencies. diff --git a/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/README.mdx b/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/README.mdx new file mode 100644 index 0000000000..a0d41ee4d4 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/README.mdx @@ -0,0 +1,74 @@ +--- +sidebar_position: 1 +slug: /api/misc/@docusaurus/eslint-plugin +--- + +# 📦 eslint-plugin + +[ESLint](https://eslint.org/) is a tool that statically analyzes your code and reports problems or suggests best practices through editor hints and command line. Docusaurus provides an ESLint plugin to enforce best Docusaurus practices. + +## Installation + +```bash npm2yarn +npm install --save-dev @docusaurus/eslint-plugin +``` + +## Usage + +### Recommended config + +Add `plugin:@docusaurus/recommended` to the `extends` section of your `.eslintrc` configuration file: + +```json title=".eslintrc" +{ + "extends": ["plugin:@docusaurus/recommended"] +} +``` + +This will enable the `@docusaurus` eslint plugin and use the `recommended` config. See [Supported rules](#supported-rules) below for a list of rules that this will enable. + +### Manual config + +For more fine-grained control, you can also enable the plugin manually and configure the rules you want to use directly: + +```json title=".eslintrc" +{ + "plugins": ["@docusaurus"], + "rules": { + "@docusaurus/string-literal-i18n-messages": "error", + "@docusaurus/no-untranslated-text": "warn" + } +} +``` + +## Supported configs + +- Recommended: recommended rule set for most Docusaurus sites that should be extended from. +- All: **all** rules enabled. This will change between minor versions, so you should not use this if you want to avoid unexpected breaking changes. + +## Supported rules + +| Name | Description | | +| --- | --- | --- | +| [`@docusaurus/no-untranslated-text`](./no-untranslated-text.mdx) | Enforce text labels in JSX to be wrapped by translate calls | | +| [`@docusaurus/string-literal-i18n-messages`](./string-literal-i18n-messages.mdx) | Enforce translate APIs to be called on plain text labels | ✅ | +| [`@docusaurus/no-html-links`](./no-html-links.mdx) | Ensures @docusaurus/Link is used instead of `<a>` tags | ✅ | +| [`@docusaurus/prefer-docusaurus-heading`](./prefer-docusaurus-heading.mdx) | Ensures @theme/Heading is used instead of `<hn>` tags for headings | ✅ | + +✅ = recommended + +## Example configuration + +Here's an example configuration: + +```js title=".eslintrc.js" +module.exports = { + extends: ['plugin:@docusaurus/recommended'], + rules: { + '@docusaurus/no-untranslated-text': [ + 'warn', + {ignoredStrings: ['·', '—', '×']}, + ], + }, +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/no-html-links.mdx b/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/no-html-links.mdx new file mode 100644 index 0000000000..2c01a5c114 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/no-html-links.mdx @@ -0,0 +1,47 @@ +--- +slug: /api/misc/@docusaurus/eslint-plugin/no-html-links +--- + +# no-html-links + +import APITable from '@site/src/components/APITable'; + +Ensure that the Docusaurus [`<Link>`](../../../docusaurus-core.mdx#link) component is used instead of `<a>` tags. + +The `<Link>` component has prefetching and preloading built-in. It also does build-time broken link detection, and helps Docusaurus understand your site's structure better. + +## Rule Details {#details} + +Examples of **incorrect** code for this rule: + +```html +<a href="/page">go to page!</a> + +<a href="https://x.com/docusaurus" target="_blank">X</a> +``` + +Examples of **correct** code for this rule: + +```js +import Link from '@docusaurus/Link' + +<Link to="/page">go to page!</Link> + +<Link to="https://x.com/docusaurus">X</Link> +``` + +## Rule Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Option | Type | Default | Description | +| --- | --- | --- | --- | +| `ignoreFullyResolved` | `boolean` | `false` | Set to true will not report any `<a>` tags with absolute URLs including a protocol. | + +```mdx-code-block +</APITable> +``` diff --git a/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/no-untranslated-text.mdx b/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/no-untranslated-text.mdx new file mode 100644 index 0000000000..589d90e4a2 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/no-untranslated-text.mdx @@ -0,0 +1,54 @@ +--- +slug: /api/misc/@docusaurus/eslint-plugin/no-untranslated-text +--- + +# no-untranslated-text + +import APITable from '@site/src/components/APITable'; + +Enforce text labels in JSX to be wrapped by translate calls. + +When the [i18n feature](../../../i18n/i18n-introduction.mdx) is used, this rule ensures that all labels appearing on the website are translatable, so no string accidentally slips through untranslated. + +## Rule Details {#details} + +Examples of **incorrect** code for this rule: + +```js +// Hello World is not translated +<Component>Hello World</Component> +``` + +Examples of **correct** code for this rule: + +```js +// Hello World is translated +<Component> + <Translate>Hello World</Translate> +</Component> +``` + +## Rule Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Option | Type | Default | Description | +| --- | --- | --- | --- | +| `ignoredStrings` | `string[]` | `[]` | Text labels that only contain strings in this list will not be reported. | + +```mdx-code-block +</APITable> +``` + +## When Not To Use It {#when-not-to-use} + +If you're not using the [i18n feature](../../../i18n/i18n-introduction.mdx), you can disable this rule. You can also disable this rule where the text is not supposed to be translated. + +## Further Reading {#further-reading} + +- https://docusaurus.io/docs/docusaurus-core#translate +- https://docusaurus.io/docs/docusaurus-core#translate-imperative diff --git a/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/prefer-docusaurus-heading.mdx b/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/prefer-docusaurus-heading.mdx new file mode 100644 index 0000000000..e1d758898d --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/prefer-docusaurus-heading.mdx @@ -0,0 +1,31 @@ +--- +slug: /api/misc/@docusaurus/eslint-plugin/prefer-docusaurus-heading +--- + +# prefer-docusaurus-heading + +Ensures that the `@theme/Heading` theme component provided by Docusaurus [`theme-classic`](../../themes/theme-classic.mdx) is used instead of `<hn>` tags for headings. + +## Rule Details {#details} + +Examples of **incorrect** code for this rule: + +```html +<h1>This is heading 1</h1> + +<h2>This is heading 2</h2> + +<h3>This is heading 3</h3> +``` + +Examples of **correct** code for this rule: + +```javascript +import Heading from '@theme/Heading' + +<Heading as='h1'>This is heading 1</Heading> + +<Heading as='h2'>This is heading 2</Heading> + +<Heading as='h3'>This is heading 3</Heading> +``` diff --git a/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/string-literal-i18n-messages.mdx b/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/string-literal-i18n-messages.mdx new file mode 100644 index 0000000000..0d5fb2f53d --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/misc/eslint-plugin/string-literal-i18n-messages.mdx @@ -0,0 +1,50 @@ +--- +slug: /api/misc/@docusaurus/eslint-plugin/string-literal-i18n-messages +--- + +# string-literal-i18n-messages + +Enforce translate APIs to be called on plain text labels. + +Docusaurus offers the [`docusaurus write-translations`](../../../cli.mdx#docusaurus-write-translations-sitedir) API, which statically extracts the text labels marked as translatable. Dynamic values used in `<Translate>` or `translate()` calls will fail to be extracted. This rule will ensure that all translate calls are statically extractable. + +## Rule Details {#details} + +Examples of **incorrect** code for this rule: + +```js +const text = 'Some text to be translated' + +// Invalid <Translate> child +<Translate>{text}</Translate> + +// Invalid message attribute +translate({message: text}) +``` + +Examples of **correct** code for this rule: + +```js +// Valid <Translate> child +<Translate>Some text to be translated</Translate> + +// Valid message attribute +translate({message: 'Some text to be translated'}) + +// Valid <Translate> child using values object as prop +<Translate values={{firstName: 'Sébastien'}}> + {'Welcome, {firstName}! How are you?'} +</Translate> + +// Valid message attribute using values object as second argument +translate({message: 'The logo of site {siteName}'}, {siteName: 'Docusaurus'}) +``` + +## When Not To Use It {#when-not-to-use} + +If you're not using the [i18n feature](../../../i18n/i18n-introduction.mdx), you can disable this rule. + +## Further Reading {#further-reading} + +- https://docusaurus.io/docs/docusaurus-core#translate +- https://docusaurus.io/docs/docusaurus-core#translate-imperative diff --git a/website/versioned_docs/version-3.9.0/api/misc/logger/demo.png b/website/versioned_docs/version-3.9.0/api/misc/logger/demo.png new file mode 100644 index 0000000000000000000000000000000000000000..f3877552104f4c8c3500610950cc0c3de15e2012 GIT binary patch literal 94456 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ୁRTJ-PJJDGHzzb~`Nw&r=(m8g*LI{j22AG1;OwXSj;k$pKqR6-b z4N1{lvnAuh8r1-QS)$)eZhR>Q8&lu=asKsI`>k`B)pFDtI5s2QEF?Gz#qD%TbkBc< z<I>@qjQ`(E_C0YzQNR;D^WV&c5Bl;5J!3gvwz}#>jyS3QDuMh!BG+^Y+n83txu5Jl zvmZbDEN*eQm#!h<lylJexTFWlLN2)P7Rh)RUHsOkRJ7Jf<l_A8-a%uLMhbV<0U}p^ z0PVB)CT`OWj3Ea&oe1uh=WQG$6}ymzLGE7Fn5$Vxs}wS9+B68p)Vhn-pb5>mksYV_ zbwL|jSJ$QhsIA-)ONNj3AB8+d@dk81$*>w&)p-y<M<r(j(~W!pQu$K2zUk*+F7|wz z0Nhnw`=z?whc#)DGZ=DZ_#^=V{dV-r_kbUC@+3M?K00jOb4887+<9*%{|NV?W*_eW zVVNOTCk{M_(WZ6To8F{I)u*3fg<yXH#^Kszjd|d2;Dzy4J{?hFu-<tJ7}8oU`MfPn zdGqH7Uvym&+d?uuMs0<5w9t^NAt06(ggY2^)r6XsAqxN<Op3ee$b8iu>vrtGaW}mO zpinGZ8B;kNd}oD*b1`EnE5X#XdHbpVP#^q3xHCrrH+X#A)CIO&Fh18(DVXS4t7=%{ z7=q<sSN18zk3m=}8}M-c*Vn0G3tPSBDGQB4>F0+nPs7{UDB!V)K^(asZ`Sk<v&Z;Z zy%KVTnF-U}J(i@Ojo@zSXD7M^byQ&0r@L^)9vwPOSujey>1{M)ZPMV+F`(jcwgm)L z#Q5-1%$F9}AedV7bl>q~abb2$nb|x8*cU|rL^$FlBymBY=|4vt9t3*Sbi0ey=|dwW z0NOS5O@JkWI@L!LR5zw7G>kN!cBTF1i+*_zSKuyZ&$oa2lz8f((FVn}J1l~R`V2{q zx4w}7?KJj9qzDin$%;SThP<7;w|{J6m@S2`CBLIi*0c2aLno7FM%oHk6L4!NG%T^? zb0m}wmL4++C<LA*&-=W_w<-p!@?WHjSlWDj918q-`?20}?B>V~bK)qd!@jB7yg4!* z(Cm2lorYN1KU{L7Wyu}sJv~)M?%z8|V_<s6>K?X%Hzdaq106ltT4tgn+k&tey;@OF z3_o2O+lGMBB%qESIc6gmx>b~d5G9qtrob*r{u?E}es*vS|Bt+T9YZX|C<3I$6=n=d zHfQ(S7*7Kgjs_iV|2h1|mLcb@noXq{3P4*vh;;HL6rJ~HL<^cp&E3wOb=&&~3u!QF zVkFTN%KBx>j8`jNFsbM2Y?_FbBG~Eg#A}%lPrfg*4HLCR-@C#fX<84-z@BTQ`$>^S zxdhui@OX(1=nw1A+g;<s>d1uOs;EarMm2<Q-#CE1AoMkjZVmr>GC~Ik&qn>LML>(K zdMX#b@A74U%9k-3sP*|+Xa^Gy%p6A!;bWT`pWE8r%%V<ADp0j{t8Fs-z{vH2Ex=f~ z(sV|G3JdW<YiG)k#7h{x`;OClZ<iccNCnJ!RU7;6heu-}?#p<5#-)japA?l9v1c?s zx2dgKex6q+m^-w^t6C6IKpbz^hcG3bAl(LE+ZC!DQ)>cj8A2Hj@PK)FC*wj;sN`LG z=6i@X`e`E~3!)zG)ynz)_=hQakf-*urb8Wj)bITkTp9(QpWusVfv3;AG<=)|5hMu> zKlG=%3zCaLqI{dOpSG6;>?t?^LU2`K-cJG7LKdMDOa??hwvbiJ`>_9meoQ!}N{5Z3 z?rs?ed;;cCd1W1w%bRSjxNPVtj9E%w<1%liNm1q_#d|@L>GBYgs;1x2oHmW6%$Ry> zIo5lBU!LwlJ8M@EgAtWoKkT#kdYX}d{t=IE&ixpYh%i)SGZ;GHjtZiWvO(l;1Fl1E zw!nE>i0Bd~#hd%nu-8l@cLU1e^mevQ6BIFoChu2yh&xy(NUU3m!tx(M9IaJA$?=Dl zYtsgVS1VlQ?d3lqtqkF*z^fD*+*4Beq=yAP*6@1Am*-Rjmm_USXH#E(TZt{Q+`u+L z?@>BbBTH;ywcGdf+3^n32&1}(z=8#uW$!wcCl<-Y?fOCq#e&rPPvqJjk4nCtS#b{? zp2vYqhagy1@{=o~u(0q`%h+rX9w!!pTzd54CsTM8mpJI?Jd&d5p4z=k`)uLIB<*); z#%8<uU(Oqv`}Q;BPYoU*-Fme|`gR<Qt%odBSMnkFFQpFA%VCu3psm`FIKU@Fnh4%~ z&&moAJfyUr*UDim*F4Tij|UMx$$4T5BKjhMrF;k~zxxV1FeY1d0l$_#WWdyK!UW<P zKLAsAx++%!`ep3k(QWf7vurUjv1VJAb22&~v&weRJNlbvO_Qv(DC!d{_49gZajJ}g z6ycpey`z3Xo%A6+4wW|pDDV+H>6<U!7X=Is^A>l<Wm|XpcMMYi@x?kD7YkHAspN|H z#gi&+m~I436qApaDf2`?0z7NGR=_x{+{D(&!SBg<^Jdj8j&U<Icm$*=g%JfF)^_Nr zYp2fmm>2fuy$jqJ-t^lf0X#SQHAk!zik>%3R1c<7NP3;`&FIm=unirJPMSTpkZd1t zrZ3E)^WR-~#>Pr5ci?<Z?)v0RxUcnYOC--6`ay4<mnVBhXL+JolBe4-w5x1i$lyW9 zu<uMBqaDgJj-fLxAPHQ)3*|aKKIZMgsRbn9%F4=45R?#=mrU%0eH>J1gi6fn$*f(1 z254p4pt!&kjsTm+3XbK5Oc-pfvMeO=x%_L<`_@f8?Y}SHGq42gIF*SVb^?9THji9r zQK!8y3pih&<stiXHe5x9gaQ#pFXRD6;pjtSnA;T;kOQeWFsnt{Q3b^Nf(KR44w%OK zl++#Hy4e>84wxjE-v!00y?vN8;BgAEAT{4wDtV7BqjEBj<$PqV_#q~ccZ%X}-Uz#+ z)+g^o5-KHb-nf3+Zo&%xX&Vta(Dt&~+h}_ImQu&5#%*B!HB)bx%b_V|DbVeka42Ua z4<qi+$U(E$NE%mkx+UnZSygfh$AP|%DRp0Sxi)kKc!)3A5+(PhuU(-%Y#qLKaJ{3L z0=&^v6$Z-AUxor#a@Nbf?oC(PJxpME*G#A=VA>jMOx!%7D^L}<Q~BbT30MKn!RN#m zsRndldPJv;%yG=PZvYDb|G8F`0^<R6ak&`y*Hg;>7Xv8)NZWuyE%_-Sr4fQ0YUGy$ z=p%P~xs-dAM1&FBOm&=;Wj~wa-8=$d+f$#V(~B}KQ_ds(nva>e{f$eqAn?}TBN`O2 z$y+(9nW=>m>t$f$-+iLm5(-?&TQJ9>=YsOX9-;wbR)86h$N6DkyYq<aXOKtvoxr{h z1GzYPpL6&e$B@^{u~5~gr5RfQNpZl)v`|;H_&?YP;_IUw(G!!Xw^M|#$%R9et>T_@ z++I97!5vB68YmXec1a<gy()0mBe=dNOtds*S<5=bSvZtUBwhLWbmCrY-lX;=S%%&L zj9S3lR>^nFFPtA1#-9M<-z?zs^sJ+38$gKY`e_c=mv$ij+`3>j<phw28}XdQ^H(yB z8oTTa#H>_e&zr5YR5P+YyaL>klD>zdd$b=2Icarn73)4k@0lk9)spET$u-%PLXL}N zn3a!1zD1U>YA5MZ`XobxQG_v@t9uB3+`ig@D<xo52|mpAs4#K4^Y8v|ROC^O7w|e* zg;F$P@hQsvLgc*gXAaKr6iiq&9goDp^xf~juY)N?etuFtztr0UeE|egIZ6Hd$gX5x zr6`m@?Vagiz@x4tLf`UjR(8>!-9tvwb#PqIFp*x1qw3X>^EhNtVQ)rk(Cx(!9+7K5 zQ9j(C)7J|k3oqM3LTf$NMoMn~|BRWN%YxAe&gc3K^&wJ##Ga6P8J|r+7m&rOVTsi& zp8D7KVw&B{AK3gTdYyD>L;n{lH3b`~-3%mKs(r)Dq3)97B6G<c<@z;2i1STrtOdn} zdBlIPVaoT3=cFm=p9SSWrV(6=-SWS#72{!?`vrZs&exmRwS7GwUzz{mGDDDOA{Gv& zv#}jRKrYaZf}ZTdP7abb>3QXaW{$*>6QT+RB}6Cwr?is#j#XdvvsAA5U+e6uiif`8 z?c%sCvm&0NxLI#HZOEMwrWaN4UtTHCw?>o5nPdI6A3BP0A(^|J+XtOt7sCLOWNY2f zYiwuWIybS&LoW?f*NI?}U+BU$JWfS4qyNV%$pf7$Sjt`XiH4Tvt|TSoQS>j;GH*Qn z;$%`}fuBlarak8!CeHujwyK<$vV}WQ4<E~;#bybSB^0sHX+KU5`58Q0uEDAQQA-pV z|3jp#X=JV@w0Cl`I&#~zAn*b5LPL<Dpls^=Co7vvkrZeAGC<fVf*A@J@v@UQmr$|p z{x#HMB{}Q$!sB_J6`CXHJic62a$Edk%h8*^9v0)YU6zO4YlnDv9{PixD`V}_sqA-k zZvQNR@Y(+8IcBr(R*%b%NP)Pk-PnewYE`A2*=kU~vxavK!#E22a&Y)UgIk}Pw}DhG zCUw<gL+Yn*gEimEVg1B*U<U}>BF+$;z}XHn%fjh6;7q)3gYg4pUxZx7XE(AZ08@6? z-1VqlV@c8<eJ+-$=3oIVfY&&J@0?NnRZVhofIFhAGyaS_zI1W$zLSYqYY&Po7Q4Lm z+($O20++Go0#jXu$c*z(Fh9KcxQC&mbMn^abE4Gvjv2W2uNw2w*`n???<lTJ66qX_ zzvAN!Q{UtzROBhi`*^Vv@ue&R#SJ!$Zmyh0A2rv@<JI3M!wYUsL*eet%YmPc^+K0n zwVj8ftu3j-&ot>^rwz@hX-l<1n1_eQc>X(i?<c9v(th6rQ9C_r9WWkwte!6l!g{7x z`ONa7akuELu<yS;!|l$Of7mR51H>*}QpayD=X2^9OI(9<lwCd$PmE)ZJT(GJa$i_d z{F%U)le-UcC>=nt(|z%%bQ*ii&S*_Rs-|YLo9H+2m$N~wBsd;MI0iUvRReE#kZhNW zd(;Uy@dHsJ%isir8aoUniKG7zm*RWR^rpc*)5Tl?tqj~PD;bY{c=H7;>Vk!<%vb}3 z-ur#hy>M8n<R>-@^N1j|335xgAbR;P@UUMGg7bbd3lAtl@c$IOl76UY_0#8&VuL<0 z7jcl-9!6Z&x)Nf?EsrXP>G@*4#0H>+I0(bK2&4!2bHujM@-B)(PWqkSzh5V7dJqP4 znf6UM>H+W#cvd;lKbV5e@bqPwgX!s&_G!lix{2*4zMQI1vxU9nq>EJk7ot*P=d?w# z45&lav^APmxf8Y&uzF}rz1eEIpv*po1F;WZQ@|0depKgH93`r!WKV$gEZ|~gfU@UJ z)TT*}YNe*J&mBbk`*2rBou0?P=>?4T1lH}r0*~xhl-%RFbcunMO9Ff{eaV_)XN%3^ zPNkvl`H~cbaMEo0*JHny<G7=O@!;kq+<Hl$KAD+cOo)M=j2WiMup=?|{S|?vIm5U2 z8V=qZm65?YOHC@X#$l)FakXHz95p_m&Vh+M2PW6csF|2R?y@o&OeuC1*i?rfMyi~@ zumUX68Qq0`UA;-YiF{xIWBTzL_h;c5K=V?0bm>;6+RS~*tKNS;xd|tmQn9%07iA_b za>3&EpsrdAV?$#_RDje0rv7%=Quz;_=J^-4)0O%jjTm}i;1?U5H~AB94RkmK$x!v> z`Agi02s)}0GIkE#-H`5Y&$bjWPtDuQ2=ghu->VU@h0r$_6BKx?pw<pED%MSt*)2*N z)%wdS>4S!KA|Z$s;@`slYs9Wc9A%!Xh=SjcTT=chcZ2)wr8WCu{|GU+HT)ZR)@?Fp z`~*Yxcz4(c_WrIv!<~=??-Y)U1+Cw@Ys6yOoj|#2ns~+&%+J3Z>OA$??*VA6{HERi zm&k0ZItJo1Z`_b!vgc3MDz&<qcB4k`8iEGKi?jx!sW|F$eS;vh*rp|ehTUgLkdR}? zlp5t|t4~-D_GLK1f<31T{n-PT?P8tmd8+K2c?}8LdSyW@qyT0WMhwi3LP%rH4hF>= z+@`GN5zs3@B@Hs*+m7h*$7sE8PAF^+0~|&|72M9hxjeoX^tA?2i**{Kz>#+X#&wW= zq~FmAQ|t>0MU8v&%C^&;6f1;i6-EGqh7=7;Ci@;QakbpsEGKyyiz#AG{AB-;YcoZb z`d2_4h&ac7mK)}Mrn{H0*kZ(aaNiJ5!10$D@wew~()QZEMnv{4$Ct|yu#D8r+`9Gz za|u1_VmrlS`duLP=Zxn3(`{lIO0JsH2ZUd4+l^7yu#F^r655Wc-t%98+bjn-J8(@* zSoIj)co+)!1Ajtp7`D7^Say=uuKO3QZ*}@~I`s)rYV+yvX000=5&o&8e^>crI+>DE zG4t|kDq8(0&REtpDoIIE(r_ALTu<P1Movye<O*nuU#K>cN19hvk6y!D!iznzc$KGX zj|8i-Qt6>@4R#<d&b8W^a=-WZ#=AWk+&n0Y9{P|nJ9*U9Qb)dPRAZBrJsAZeR}Bn{ zy_0V@MoJMaf?B!2;hi5Vsl7)B@(W_vK!PK3hpg$G4_IiKEg=JD^`mCUx>KK6fEfBO z$JZi{LR{maE)kjy>Bpq;yDhf~)<_%hJy!)ZR`BunMJ=5p307v(W}hBvb;RcP&+y3O zlFq6gJod$S6~HcmEkzB)?XySKYSeHSfw3!Jwi?V<BSt6lwi@FZH48<;qj_@2tcN^7 z7+FS48KBFJqdWw#?t&#stS<qpUS&&?&%oIiT=-+~OIuH`CoqG|c%;p98^}<mf?9VR z8?o-KIX1$-fZSp$GWok3|C@XeGujTxpurhE<lc)aPZL<V|Ic^)2<jAjm}BOZ^GPx= zUHe`Fr9HZfwf7qg1O|9T$Rk<a$7jFV`GT5D`H}jVCld4UB#rIHTx}R1-*^QBvy<pg z*&X>DZ21qBHb@E1bW^7N$N`>rdkyvjCr=Bo#N+M?7>DFyl1=h2sMpi6Ro-nwWs87D z(X#rfqV?eWMHb4IKwdPQ^kOUjXvFPm>*Xo}3q-P%`J!0)Zp(9$UZC>VMQB2$i5dNj zx8in9`<Y&jh`>S{28w#C|IMAbS&UKFUe=8De>|>&h}0~-i%g#Dfh)JG-M}O0Ql5qF z{MOW(pUdz+dMJ!3iBoynqYkFAk0+o8$l|FAL12X~0XL#j543aVa-Me#)Qv$`3Y5Pb zhbkOTv2vP8p&*MF4s<9oxpBdn#CNl0_v&MYK*JPX`W#rOoT^i}Xr=p#itN?CSCWwO z1>3C1Kycv<y@)<tXkvvD`tmSAT|5@2O@T;Ek0Gb~Qr(uPT52WRHsja(q^F{z(dtpe zlf9eU%Mp^VN<_c#ajT}cCr#JUGduM#wEl(&=o0;2K77~(sDweOi1t5D=i8FcDlb<> zDxlq_7*z`uoYm8#aE(YFPEPepRx{SnTCdH)_VK&IC8yt%+juCiP*5%A8$m+!>rQ0I z$xt_z(n3h?f?R&xOXSB<_?Yz7!dX&mop5?vR*~UL|HIEXa0C1M?%`Oc>9<*trJgoo zwfTqRuyio|vmD=BqDjRu`(7+9sEv>ORR1z9l-AM7Dn6w8*7Y2y>3}e-Y2IdbDmR&p zmLT=JINmaA7jeXR;lqD=9kwKBsK$NdB0bUfCqPra%Q)!g!3})G*gJI^wCVA7c|^od z^2Q3(t?#+D_SwQ{y#aVA<vo$PV>&j`;$?i*?*mZ~$eS__mj)I$z4&912M-K>J`j@# z*+}qq^b9Jo$)>@^g^gWR<8Q63ulMzI;RZ>9(-n`#Aj#P5@Jb=o_*W`f>fn;s$(9gu z$7V30z>WFzJy7Nddsaap&k%35JNi-uqSxM^_4ywGTh8t^Rh#Hqzx8l^IKWP79cwwt zzjb_RTn(X&K=d#0$pQEOT^$|>?MT{0RYbCg{i)+f<3*B8AOhL8c^IaK$IjY@52!zG z*KO+v_z0xef8EmTUvf+Rq*Ko2QMv+&<`uRBitOBGu`S)DrQFSm>R%97lg;1F@dOs` z5<!=UuSlg8fsd^p?*qTCY$LRSzH|xV9#fYbcQ$(nZuB5in2>aUJ1{WTwiF0KuMB$K z1=`?<FKmm6+vLS;<4M6sADFn%TT_Ogu*+jhlyIk>3EbHL8~ZrFv#I!*0u770!`-V? z)5mayge;Bmj1su-&*qbp0nNj^0;cMh{}i;<*b#Y(PMIBIcn?OW${*P>LxW7rUNW{0 z;|F<Gz8`(7<7Ce{nfAyfOQomdTIy_hYu!@c!5OlKkNA8H8CwoRRQC|yCKz2(;nw*r zB*ztnE8#HC(0|BIt|c#yVn}Ck6*)lWfM*(bT5Uj>Zah}fnO5)Wn|I3GzEVDixt@*W zuLJ&<5X2Wz0$FjPXSNS#Hwj>uG;37F&sA(&t$8o1nNh&YPUzi-!4<e65?H_dDeE^t z{P9Sv_*ZrnMV+01FTH@VwyW*&hUZ-tis;m5lC(A$SqqHb1ukRuNwUceY(^H*n%B@n zHkg+HtZ4(0l8Zx%@`v5Iq07>D>!{2<wJatr48z575)ofNRX*LzA-9-Slh)~?d$AN# z2=gk3@tfFoQF5%|e;$xf>DE)^zHkWcg)|l|kL!*D_t#6ECb*~34|DB|%Vw(PjZnp4 zjENheL>n~<JW~SJByq-H%@}-7tT!~69->T>5o?t&y}MW9jp#%F3AkN&Jk6bA<v7T? zM_NNr7GQ}QiH&>_{Pr11VM#k*WKoE0ENmz3bwBR=NJwn->U^#4YScyQcGxR<0s$Dq z(+^s2&rfygGZ}*!CREP;j~755qw2(j$B%YJx$(rjkm&j!hnsuYnr;}S;-CXK#|BMv z^!(!`M#op-OGo0Xt4~)+R|bY}#AwQXI=pauo96X$DNIk`;7jATnFFOSl>5KE9C2`i zLITCw0=8DHpc)bkU+YgC(tVT3&Tg@8IAI?Ira1W9zbBF0B_sLsYV%B7HzQ+3eXYTk zkj3fj&fCEvzl$izdrGp0f4nxXjp@HW6VS?ka(puI-Q}mj;h?#=<QrL$qXwJ&uR@|a zo1T&PMA#3~Os&#DiyVVt!Z(_yCwB!lhNQQ8L9I}tippK;;r%#Q#4}A=kp}}AA{m5a zbdKd%WMgxAk=%AG+BQkh{HID%OC2iLuuz?9?tP2;qJLP)kog;zlx2y>t1T|`>bIqM zxG@QeXf`YM+yJ4ZQ+2??VI~>ueyq!XpShWU!erTW05luvBdy2ANiU_w-u6zm%BPd; zRAl<Cm6{4Rap8x)J5R&xq4$b(bAKBC)OMQtX`kJUx?nmvU)7(a%bs4<4O`l*%-$H1 zb>mMVZe%$5TD<)IMzBGf8<+n|XM$ofSP)H3_0i!q*#~+7?sMFQbSYobIm8VQA^P@V zI3&X!Q+qITAJ_@M8>x`ttGHN_@O;E~x}3v4xxaVX#j=3~x_1Blt*-RC*Hg)IK70Jn zPnBgdPv$VF+Tg!(e`>}Gb#4V431;&eFngO5{S-uNu1q~;`IBO^VA6)KKo6^vAp>4Z zvf^TAU*b+S2EyVkU#@Jy2YT3Gf;w5FNb=tID0rVmo75aw&MlIdM~ph{l=jbpR%x^r z>XT9~JNmEbfIXso_`uXO2Gzq>`}UkMQ|evT{-0wtDWp!Dh~Vj30;K=T?~m(H07H+? z|CXv0-Ex7yoy^rwslQjS^csc68lK5lokM_F^}M_0+mOI%!MX1T^i^!i$P~E7M4j_w z;t7bhv%T4xpAu6D__>d?b8yTKyW>n+00Oy&h3+;en?CBarMh7`E&Fw_YO^y(QD?fs zO32QNN#K_s5QE9bL9EVZLPhd<*~d3E|6CbyVc!pMHp~<1-(;X}@y+ZKL}`EVvq>O4 zto{1nE^55y*lBQ@94Qy}Zua)oTkp;vkyrw;2Z3X=Df|~RabFt^oo9MxzIJ?p&IDT& zN-}yL&zOYN!mj9TiwZcM2Z;8$Zsfi)ZrE%*Lf!cWbfQGgbKWMK*WR8_fABE+2ieQQ z*DUR-t9&i<sAQ{FvDYb|+#r$zQbLK3b`kDKR?&&H3nhTDf`*1><KM4;hPZ6$Lj_RO zs_YBAg&fMi`tYPt<OXC2Dg#X}v3|ZXuB%db9>Dx|2RftmVpnfFrZO)NNo4S_Ld-kj zlSI{tL$+$Gu3$2+7R>B}uV5nMRND;sx0KUih~BtppA~s)Fi0D;&HSocc3Y1=38q_b z$w~5CRv<Ufl=piQKibQ|0;_kw)o}mkT*?!^&3FVu^4sAe_T>!iH|qmM!#6PGGqAGd zjKPz%`hVMpib>lof$Z@RrR5(aN_A!Vv=B^lKWwP(wPuUlvWM|%1_A{i%J3OIxFA&` zD>5$kEe0(e%>F}Gf1vC1r4O|4iDx+>?2e&?U~UCk7wNavuDD&nC0TTF`~F(Urw<o# zLleIs%7^2Mb}zb_$$JH7EfJU#t!ltWZ~T*tN=Q|zV#|<!cE<6@?jB=a>mtd!mRIE6 zcY{X%G|{Ym;Gv3?!bqak;6lkwT?p>|ytfSxTkERJ?ntwrf*;s|G_ry>(#~z7CdcVg z@m_#HE$~1=IXIH#iRJGRpl&lnm^q<&Kq?L?*<6-C`KY`&RUqN`mfc2HgYTc)JFn?} z6_|_jnKb_Zt0ptX@h;4##LN34;WGo<5A8T_5Z|i*vFAGb#-R=Or_><qm#@uEofIRa z^%x#lI9HTge*pSKBo|<976#rqW`~UQhm3rn6Z)W_aoKk$@7uox7YQFiB^7?jQ@;SY zmWqkhs!PQygt^_U7MBhE@)0+pMMXh9Fy_LcSNPWXtwZN&IVQUk$<Inp8-yrW!~cH3 z?t%%~{0j%7^AJBO#T|3zGmPyR{rK`cktg@doh=`T9WxupG0Cx~>BnD_MBEBZyEc^G z_Xi@r;Vsif{q-uCB!Hzy{5|bqlQ#zRh++Tm-g$OFSOpmWz5loI6txhl%vL;-lk^nV z8DhT%fut~M9!Ylrrq6H4qnKy=mH}I?5B*ERk{8q)zOu-arT{A3erBEhLRF%r(IYd- zEvcF3UU9~i7SC2|9snkT<&JejIWYlg)SddA)Ikv73Z-YW+C#ZC3^+r*W1f3#+?}UK zxBxn>$W^ic0DC#LC=`z0+6t@?qi|P;=7hq7<&1wn1gMdi$29d}2+5M@I^ai#t^ti* zVC>S3F-*tcF?Ic#b)G++e7b^m!`<w?Li<E&xZJ=DQC>}$s3DV%C`%ASBZ$cEB%_WU zy+zIN7ngr8m-;q!EZ4iUnfjZyas<j|X_Djux%bzg`6U4nYkH4`{y9I0Fvz<g*($I1 zEAtwTXvroDoS7x8_Z#x%pbIAH#XoqR7F9dy0DA(jjC>)A?|WmT{a43vRq!hxr$2=? zsY2vf!-~@V&c$r`;H4Yblcrtz-7<9~Tf*_kcUkJ70ZuRg#4RlRW9Tcr%@B^$VIEcb z0{dGy6|v@qf@9&no3fjBB4YN|lvR^^gHiFbhxF>He^Yc`lc*0~!ZjxIAPV!<cOwBK zn*s+qenEq5)6NSkzMapn=jYBjTc&@D4pM5;ve&HAwUU)gg+^oDOn(qusw)qvy+`nc zC$}C)>44Qhusy}($Xke65rDXdB?vMX`c$3NUd#_O#1GKn7BBP)*qo{AIVrmG*|&)| zH}A#(9C#lSQv;Dvol8pqDX($EcLNqD&aCsR%u8m^o%gq1jBY#z{WsRmChU6$l#j&l zwuUr!#?}nhH{_pZC7e6OzUKx}sCT=ct>0M*PeufCj+U-ly;{hZ*bg)kb3hi~wQ@D4 z#q+a7dUtiTQJo6p2p4H)jM?YK)*I;wWk>ZbwuRzvoQfdyk#Fw5wv}l>i47>Yvnt8g zb--oqxEXKv+)71~jX<hq$ywxX6L|)t>SkQy<bfCaeUT6rE6PVlAssN-;v)trZ(b#$ z<C#FrdO8k^R^ZxdGgo5dlk7YK@Vf;vByi{fsddrG@5m(Kz3Feywk-P!4b6`nhC$e- zZ;(N}-gOn=pYPYWw=+Yny8N#tFlk`Yc?C+0U*fWGCF#R@#Dw0}X8-{k!%FA7(YIeK zk+5NPK0ZNC;GvNzdhd~SY_@j{e)t~9xj66%dW~w0P0g?S)O(?0chtM<D1mqx^Mn-A z3mVi&2Rs5q>#e;E6Ksp+Xt@CM;2Q6hTGEf%H}=Qu<+fLkA(m8x#3}%8#5Qbp7mt1w zvWf;@@BkM*wDicK{WI8}^-F%3lLs9#$oiM(0x;-Ox@@!7xn%staW4ab0M^*Xsd!kQ zcD4`JHtTC2Z+(`(1$}}r`yr~%w(52{Y`%A_RhGO>%!V5jcN*UlvqKNw$Bifpe>E;k zj>9FPVWMB~6|qQ~2|5flpf6u={L=EP`J_{u!VFzUW}9@o;>i&_>yZx2He^Mj1ls79 zQEt6Ihig1?dinkJf{8#q@^r;)0)Eb<#@Kql5@RwhkjIr7t;+!%8zMjH_fYO})i9az zxtaj`|HLUCZ2soFD5vBKW`tP1JOKWV44a^PR#U$`c_c)YcF<B)^>TGUNA>Mb+MRbL z1cogl>bx#xS#PHaJwNL}-)GFq7I50MFU(VDS&~7;mwT!J7uHJhaP5|DG1<}PkFVnL zfbX2m4>dPNcHxt?cQ+nqWYh--yJ#~1VF(zL55^>Qs9E}1EnjUUq*c3NF>GY`Fn)G7 zGhl1kYZn0TJ2%slv~y%gnx2AehEW`?XrOerl1Sy4hP6hHw<8EYl|dXz^Lj}kT{BG? zkdKJD(+L%`l&UHMs3oI05`n3G%KBzOcR`C2@F3i1X;FFbUiTDz<|enEn?y+_+OBAI zMtNSov-JOPbk<=_zHb}1=<Wsq0Rg2;YSJwtB9ar4lI~`7rzoIENq<2J=^CBV4azpU zVdNOwp5Na0zy0|f&#~>kuj@R|&q?p{Js3VQK?<_(QJ@7md|<?8n>XD<*~MR(&b{dq zHDYeYqGc^{Pir*x0T0xpxgvCduLW9Cbm$A(V>J2zy8QOlu$qetAX&o|cAJ{F`5*ey zn;pn{zrIAom9*4VJPn9;h&})BwbE?37Wj7_4u9~1dJ*-LhGJ{xm^2>@Zwd~XChXy5 zueD?lt@+|UniE5=zDue42;KW+BXJKh9(NeH1*MeB=nTUO|3(7ray^54oK7xxa9aOd zro(r@>5^4%#xrnXC^ba|^(~D$lHGv0yBqwVKlRoSp!^<4b4AqhG_V%<lJ$p86C&Rl zm?&q+DfOE6#&zh#3)bnXP5N^M29&<b#q%+BVS6(#LgwCEc&`I5@>a&aT-HeVYV1P7 zEZ4PkG*rA<SZ|QmeN;OT#=27$#4y8sAO5WFxaC)TnUN?-u3N~=LCx5cB?p!K=jd51 zdQVFx3AzP(8dYHB(S26(N}lRT2<NG4uB9j!_PTeXEM=JL?9c_j0?3&=j}pmfzykhf z0!R6~j+^3F9We!o+FzK6C@9Yy<ZvcJrWs6x6cV+_;L~muC%+*)?*46EN}(=w*T6g# ztjw%!6<Yn-HN*yf{^|?H>ErwQGp$-T198w_*okejMi}ZE283gN_gpUTrah1gfedy0 zmn}c;ioFtbCNIZ3ZNjiam_vYQwK3DVrjy^9&1gCegnPL2Jve^`m0JVN5D?d@+o<_M zBJanE<Y~p8&LiTYClTbV#J3q(+uH&GyTuxC!SdI5&75ZMcaz@kx}}V83v6)1Re5Pz z%%nrG8SZ)(#NM^7!9BCEKH2cH(_HnpK~#u3?@BBeLN{Cd{B;-J08?732O3WH)s5}j zA)@xKSo2!$3T6AAd)a7R1tEb5E0Z_GbUGs}6r#~jI)I;6&u<^I1K$ThN%++|Oz%WF zO*rJ<ZxmMza`Fnw{hSzw*c6ql%Q=h*H9+^ftUgQ-^&y=B(E|AAf~UsWoZ~o3r!16l zydfYg2`GZb?ZBh=3G6HFAO80IAgg<xB(%3TmKk|a-4zPV6x%+eH_aTE@+dX%)p^`C z@T+Ts=AJ1%*DpNWoA3>h(1Q<`)3CCbed){Jy{9<Pcg%_VKep5cJ?gtdr6tij^Q^Hz zMz`S*#vZyzHN8T`5s@;zn5Y=mi<~q>^>2EhxG1|sjy|*~G<|zHlWwMp$Wo8GeF0~Z z-eXR=ot@9Ps`ul-w@Y=;yf9{kbc{(+f*-lHn;f?kx0cN`)_vUi_$-{x3FTX<O_Pro zU+|{MjNntdNIS3l1z!UH?P42UK3>_r(uk0aZ%oI7n-+(2@nBa2q1TF0cRnv$G`q#r z7(+f9upS!@M5_ez(JN=upS{ONrOfat;k#2YFHx_Tq9JsOx7Q6HV?vh7)npsE%K1=z z*MHC4Pm`ib-Vf-0TSKqC;m2Q_Rhc(qa8cqdroSxBWQ(?#x}RD!@1c6>AfwN@&tGkj zfzKPx4NfZi9?PT>7WE_=k+8|QJbz^JOpwgs;VsxOKC&)7fkaMpeepjN=ehKR`1WTK zeur{t{M_i-RwEtcSo(ro<(JDdG7JHeb>W35J(qw<Ret3q(iy(+^Qx+*2QpWYk@Ni* z)ftRloqlkdd0-&xtm-PL;k;pXX~OH<V2zAH1XtdVGREycbHpY1qQu(A$<?Z_Xu!%N z-tq{9AV`z-qH`cT)`q-m*a8Q;8|B8^MJ&;qOk?CSpdyFoUKf8Y*+{A^%HK_>Z4_-) zM@UM1SgtRa+pRMDU8cEXG&KT|w0}YMVwAVXLE&r$U<`{7UQ&&M#^K?b!DleLY@opB z*yTHWG;ofls3$0Q%zA3N@cmemRHa+N_pq?M!|bN`u6oqh#>`R3L)K*Qnc;n_xz<Ek zr=GBf4f;pdWTG9^*M*P}ZaHI5Z4%wzRLwmJTSEodF1LR{n^GuX<0N~mFHeDJs{m}b z{6cfmB<5Ek#g~kXN=g;Y@Ys!l?=CM6{*gJj+o+di;BK$rRV<rO4+M{D++hvWEy{RR zZpH<$Ks5nRas540^6j{db`KPPjQbzEJwuFHW|&GZle#d(h|N^@VwCGqafpVFS~MlX zp}R%&FH=ShvD3B&s{J-OJGnRh!!2uSL#0}WObq-a$c=I4p4@RT54)3(NHN%h9Mu&Z z^cWa0VB_%wV-07q7chSZ)09M8gP7pvmpLm*ty4ht6LtXG-26pKeF&+`eEwNo6fnOL zy<gvPongxNTir?O@F69Qqrfx-mtPudI|5|kHU?ArvgdemDqI(-*uuzr5sT1u(!FRM zg*^~;X5NjM$WsVQemBv>-PV*Te4A{+_8y74xeAq3l=XY{+9QDX3uq>z_7mb^YGT5I zHh)-;Ju7I5TA5c&PY4VMQLWoj)QpKj+0Q7S^+M)A2N3HxW76h|KX0lil@3!N9B{|g zdOKlVb_=ZSUQNpR9t{8R=O{kob*<~n76x!JU;5oA6#o_(Vp&mqcRF)XmI@@{V9XWK z0qG7X^T*4Jp&5_>3dh=e3;K&|-EMQ<DgayxH$cV8%p?=&@n|<ibaZF$=P47W>2{?y z&#@%(d5bx-gM}K60){W6Z^LvPMrKMux_IszM<dRCrX>N-r@XntnI537Z1Qt-B(MzA zdTyv+*5ugMM1H{~?bX1f;qW-1WCLag|1C1=5Y5`X1mBQU*P>B|t~Z@bO>9WY+!s^2 z<rTeXzS?PAv?dygV1ey@UMD<Sq4M6HVlRKZ!c`_qU?p-oyY)wi6rdWWEdFoVt0@W# zvcGto!rqK7@KVR*#LaZr^i9U2Vb%2$yP^w*v5r()<8KU8<?PLes0^*2Sd=}XeDUL{ znp`BwiD+$L63MkY-(Nh}5*&8x8jLrr3YopqOkpi8ef8>9sW^vIVO}HDj0y33q3v>C z=i1GZW*z^`JD#QLTe@F*9Qc%!4^r+u_NBiN2)XT9?uA9vg>GmrWz>FgWIC<CVv*6& zR2WCe#``&c(IsxuHrct$LEOPy_lk9znH>nIRW+8ca!iLy)Yi^%HM%U<v)qgl7v~4i z;I6<Bjn587I{jgR{jjNX*{;}s-mN|{|7;OeN_BRbD{VoEifhzd`#s~i&4fpI`*=g0 zlk+OhQ024sY*}q(;}tcQf+J_N9q)Er0W)@WkrYF0zpRoq0CY4qrlmrgj2kCh#3F^A zAKtOx*bH!%?IOg`Y1d{Q@0I;(W)NOzpUQMhV7tx#3~LV-RX%NgPFOQ<b7~;J=YhI` z9W~4LF8ReR^dnQMo;X5&kN-Ujzi<eJy_*~^&kxdF)xfky%QLP@SDO!XYKYg6Za}}r zpYdWQkrAI$rSu@L%V^$EuwsmFL7Z2cEDo<<q7+O0*$)HteD}F%BhFKK8$oG}SgjDu znJkB}%8wtYo~0?kaB0yp##`RUoZwGQU`E$dYTs6-^DU2?ol)Uqf-a&fH=3p95+GkG z*cYd9o6Uu8nq3Gy4eKCdZZ90`Q$Yim^PowQ$HERg%+HSuiPeMUM4MIpkvt{`^X;!W z5!Rmr;F!27H)gEG+e@;cx<@zDY(ov{*WQXl_;(wIYR!N)BuamP#5sHcNJABkNjnv| z$p9M2E0t%f<q%_$7Ixt$aJj)%^26ZoVbh=h0iy#`?TdxWmPKomTj8sXJ=(_E-A54M zB+QGJUnhZfsY^#f*YqWt2(JF=s8H$3YOMRyY>o*`Z+*CH8U7n*6^gt|RU5eUoF~hV z_6IOZfh&vi765Kn75SZ($mAKl6CU`MEYD!{blIO_=18SC-wo|F#O9<q==3V&RBenV z;6k(<8TY4q@nv>o+4%Kc#ON2{h)-o3jZWYC#>#SXf<rEh_<8%jd!kv+&V<GMkRJ!U z<YuVv4g^O%BV#EYO?fAP7*p=6l|<wQcDQp{1u+a%pAJIBn4^TRrg$(meQ_iBwCIV^ zaMcqcl&)NdaZXmDHO&jf_wVWN(a-9B$1IH(2i!@`f8(Xr7rXK&hFFsG6!YBfU9W8J zu_~hGf?nDC20p32NkPZ>1Vc{aB)Y4x-aQ_2<C|=Qeu^NMiXq2oBr;}r`Y1<GvO(4! z<#Fy;kasWC9kCl%bf2jL+vB-5UndIACfZLbB2s5o^cNQQieALOtw{S!&Y~2Q+<~1~ zHJ6pt&m$ioE2doD%pFKVHg4=a#0a33BhueJfoR~z8uH#(!-kjnMyB}4@q#E<JFvv( z5A#l2aNRQ`(x8S?urYLTL3&FilY%p~31y7(WK8&ZB{pB8a)+sGLqu>vb&6OYkSp0u z%?X|1d!5;56^us@PD1eHlmI6DV&_Q+s}--uC>71ZMm^25Zld**I1mNpYu0-qznS$c z3J9%UBZ}$;@<UW7&UYnHf!%$yv@=Zsb?av<ON;c3(AP7}w@0#aM0cQ!S)vyQ*Cl7N z1uP?So-^v<_8awmlg<ELS1IHXUT!@Xy>Y{|Aek@VZzD06!DzvM?5peGb~lc_`QLFf zj!J|J051Ff)9EvOa`1BsNy(U`VFox}EmpA->ydvZMzMKQ5SnFx+f!T!(+d5|mR8QW z9SuSvm^9Cf`IFt7&U4+nq$}<yXFv3QH5y$YTb&uV{6cCV4aB?qI4&e3E9(bkx(3+B ztazRGRpaPaG17h2iE@05+ExeBG~Els$^|@(pj38|4)1xa%z~ynApzcXLPmQu2jL09 zkVJa)yTtXLGyDlYZ(wN4v>e}1jfLKt$<3sT{=dmfO}(Uux;2@`<8S8ETF(@EmU~+N zr2!9aISvN}e^9$5SfNWFrJmH-ksF!CXi3dE)13YvjyRi!LpYe)mtUvchTr#2IiJ#F zqjvvM+^RyijaTC+r1!1d5+2;T1xf-Xynl564uj7cLRi!>_{R34rT~|Ay(i3M>Cq)} zjt?E>-grj>usE(6N46~Y$Src8bOQpwOSQXE+VUQ7A(>7jL$^q0_}mblq<BuH`nk`c zAT)BWI1}`f{Bn<*=zGN-zOYh!<AirxNn$NA6dzvj66BvX_E@PKRp9X^WqL8?k1bSS z;qLBGZ^F-h@o$cc(m*wU8D|g*8psJ*O4r6h<j}Wx{)S=LGDTQ|P)fX;ej!~!C-{dS z7J(cy(S=6WVLdJ|rm<Pwu>Ar|IHUpxq6e}?QXGqDmWVl}@}!+*UZkD#`*4o2zIV{h z7O@il3MEfrWRZ8N_!A7=_lvBTMS|$YaJtz~dGVk;)$>gzplWSkNTI23*J_ux2EgK} z##$0Mjh<r`kWGh(!H=$Od=_R)@=lfU4((F35`)OiAr$`m6u%EidkuK$B_jH?9v}VD z`hz4i)R1Y%m?}nX&|DSXv-6=6T5^3h0-92Ts;0`hz28%EEp=yt&~1W5_KqVwGv%nE zaS>c6zF(jC^be+h`e=Z35dynt<=h4eF6z~$(3b**$*B%%nzjk+3hvO-YXr82>#LCn zMTR@kJKN0?NW0G-Pqx+e#_zz*-_*GIZU?(=2XF|EZ$=H{Uvg1EI;8!5U!{kUyJ0e4 z=8zyHxl=vPEp|HU+@^p#kL4T8vpg(0_%_e~p|vB?%u}oaw^!yE!B@|Vis@Pl6}rD{ zL4)D>xtm3lc_mMj*C{wYzNlD@WniLGUV4+K`B|kG@oBPoEr@Ny#=ZiW%P-`NRze`a z%`Z5xC_@w*;vx1#Z5Ooq($$?``HiU&+boZV2Q)={j0?LnR8S}kPfus^ToE~O5-=_h zw(0b{xh*)8-MiFb&Ct3zSiSbVi5TOFpvsesB2;o$UfT#n)gsQ;ZcmD=6$?dv5M52E zLil6xvvOU07V&UDlFnpJQet+q&N|IzZ_n#zG5%|JcKCbpeIUP!=w|u9t2txCLUztm zXx&br_T)$3l9;{%C9-p&M_#Sl=ig1m)gIhNStOF1cIFnvCA|dFV>_1gJ9ko)?H=P= z8$l%J9;n;B0<Mk82B%rR@Ee9puIuwM<>{v4r>?6?@x#!A3(vKV>z?zz`Vo+Cu#{6O z#tC&t!K3@RQSf3P^rOjAd-j4cy2?r{3;l$q%XQaTy=_{g_RO^0kHcGxZIm?>o9;xm zf^W@m*v%d@DXrx=R}P?RJ-r8HZu|Vr(zr9UQ(()k_U%Tn1v%Nf2z8-asW?jP28d`( zvJ!^_wiDD|hp_+HFbJzjU$;HRZ?!Id@Yw;jwx1c1nc!~akLP#A@S=Gn^dMoeZpbXM z4tjNzfuae0WPiT$5R*)6_vq*T@{;$FvBpDo+_3=sB58<}$+rZd);M6Cp`;kH-He@- z;Y<atn^o1#Db!1z#%{Q+2<sZhIE@6;pBjsFlg4c4%oZKR*r$DJiO~eu!Xy~tHt@V8 z0+1|z<W|NzAB0&VVys6M9QmO4z6OhOv`Rd@{9cBvjo?-jD^x-J3|Bphjc<7TclLKV zlc&}ibUGL7X!>(+s8kPm+2~&@5%#nCrMS-zUMO6gTtW7f!Sk~~h&AE&h#Ebcig#k> ziXO20Z?^|tdNPELSAi)IFLej9#gFfA>3mICQhh)P{XTWWm<l|RQ;!E!g+kN?sZD!N zA`*05$^Z02^|G~mAk;M~ZR}^;5Ln4+pj=-ZS6GEB{CSbH+hqbXn<6Se3MKIFhce9= zvDrVSq^{39XiyTVAkX%rhha~*7E2T?q?lL<2|wPMDERh~nnw9rrpSA0ovWYfs{#le zUv2f<{6GMA{nxwsZ^&;vdEGR27{FcARMm3aiyfhNJ5yjLyoV&sUkf0{jGJ1y&?i*1 zFg`twrU`srrA|{Bfqj%;WJ_^9vLxv|`g!q^gY!3%OF)qKojNsyGyCUY)i&NF*@aE4 z_UY-;CSu4(K#r%Mt7TkHhDYJAQH#UC(-XIZ&THIHtYJ{6GK)ZX(Tgzvo4+sMP!Qa- zKl?TQ!}mK5^?Rl@ca>3PLnJ+xTC)ISmke{q$|+cuxcK2Ra5A1J%&Ylsy=RQ5ATvWE z=d;+O8<~);ehSHoK1s^dhKE*HT*RZ0pWhnATDuAHZQ!)HXmFhbzletrHDk7wmy^}$ zS&u+<EXDN1!q3Y~%Z5xklQBpW`K<(rk<V$v2tM;Yo3;>kQ$V>P$(reH{ZX;^4mUv4 z1;$CMF^BZkq6ZJk)eb=G4qFAK+Tsu(n8XZTWlIK54`4V>A{INoDKR`m>dXBZL}-YU z9NwrUDo+c=Lk)IjCRCSl!!hMRFxuhTTM`+s{rOrz=P%K0qh=Rq=~P6g^^9=<R0l-S zc5X18Q$hu^t$77gRwQ#Dk)J#jcYYTgyf}RdHm{uh;LfBzt}*Zq)+kMTi_m|z^dqTB z)DLIz_UswH-sKJ&xZTc078RHFmKVG9p(zp}_(me>pfBLoRu~x)!jK88kN*Y7@igg6 z@XJictapd)^>&J1t3k|hRU}H&z}K)*y3cVVHHHhw6UWWTGmtNT_6KjWq#~5qDK6Oi z_XUXNJ?InQ)`HOF)zZ$nRo)C`-c(8k;;6V%6MUWK4U#{;^ju_pOIJFLF-M_?ede5o zAoi2OKyFayN(atRPsklbu;EKD^B{G=6hW`9ThCy04*RS=COSl{yk{>a<A0Ul^b7$m zle(&joOpy&Y|P9I$fC@~3lo>wtn<!~5iN&V!M%i{Q~+-Tmk3ZjO9eKp>XQ�sUPx zl$|HSYt55h_|sClqllYl{=@`Vpm1%K2anwVv3HpBlWdSaUfyk59T8Kx7}3{q1|IQ! z={eI%J_#3dzG9Q`?0tJgNARBblLqkSZ26nd>nU+JbM?{amBI2@iq0>D0q}r+Ps#5< zoJ!NEYU-{dZ`fvzV4<vQHNkn^M;q$z_n0Bf8I&=Plj=l|BqtS%$9XYtlTBtF{!AUw z^dh(tf!<pv1aPP=c>DuC-A%;h;=lvtg%=nDbZ@NT0)2$*aYGju`b!Su^U9KNiBkLV z-zgjk(N2<uL;@;QKdj=|Ab~u^D?c4avOS)Ft`F~g0kL5Rl?q$PKcOA?v-&e~nVy;_ z|CG*u6C@!oAR=R4wqYxqy_gBIXpT^dxY_)BO%93OF#I>n=eux>09*5epC2*NW!P6_ zk~-LDZYK|`D&tO4pilZfAuwstPcTfBpzpx%??Pn3P7=!RZpTnJX~C7gN28C6^wrr! zGKOlKi@3VNIyigN79&jvbE&0AN?&!6ZS^8noB6?SutPTnqJNOu03RqM&8|1ip$C9c z`DY2^JinGXsjp-jW;{&9BkTxS`w?Pv-r8xs$ex{<7uJWizb+CU6r5D*#o933-vhC6 zi47w9S~wuQ(;(5S@;wz*l1s=7Gzf}@3^uU5Bzrm2f(NJbQHib_Iy~N?uS1D-Pz7_W zB?Klwfe{aUVL;!l<K~1q^(b*j#n-9}2M$g(!kZJq-QU5XSC_=Q<EJ>&_U_EM)uPFn zqQxb=h<AGsHqZd#be!~bsan9V$we!WqO`bYdj<DRVf=!NvWq-OIzsJ3S{MH!L$jL# z9mGX5YBr;ZDOG9|T%;5AC*naYchp7N1IQ$u+##Vr_<17NO-nxyI@#0>anc)ibLY+D z{̪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 literal 0 HcmV?d00001 diff --git a/website/versioned_docs/version-3.9.0/api/misc/logger/logger.mdx b/website/versioned_docs/version-3.9.0/api/misc/logger/logger.mdx new file mode 100644 index 0000000000..4c0b37371e --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/misc/logger/logger.mdx @@ -0,0 +1,71 @@ +--- +sidebar_position: 2 +slug: /api/misc/@docusaurus/logger +--- + +# 📦 logger + +An encapsulated logger for semantically formatting console messages. + +Authors of packages in the Docusaurus ecosystem are encouraged to use this package to provide unified log formats. + +## APIs + +It exports a single object as default export: `logger`. `logger` has the following properties: + +- Some useful colors. + - `red` + - `yellow` + - `green` + - `bold` + - `dim` +- Formatters. These functions all have the signature `(msg: unknown) => string`. Note that their implementations are not guaranteed. You should only care about their semantics. + - `path`: formats a file path. + - `url`: formats a URL. + - `name`: formats an identifier. + - `code`: formats a code snippet. + - `subdue`: subdues the text. + - `num`: formats a number. +- The `interpolate` function. It is a template literal tag. The syntax can be found below. +- Logging functions. All logging functions can both be used as normal functions (similar to the `console.log` family, but only accepts one parameter) or template literal tags. + - `info`: prints information. + - `warn`: prints a warning that should be paid attention to. + - `error`: prints an error (not necessarily halting the program) that signals significant problems. + - `success`: prints a success message. +- The `report` function. It takes a `ReportingSeverity` value (`ignore`, `log`, `warn`, `throw`) and reports a message according to the severity. + +:::warning A word on the `error` formatter + +Beware that an `error` message, even when it doesn't hang the program, is likely going to cause confusion. When users inspect logs and find an `[ERROR]`, even when the build succeeds, they will assume something is going wrong. Use it sparingly. + +Docusaurus only uses `logger.error` when printing messages immediately before throwing an error, or when user has set the reporting severity of `onBrokenLink`, etc. to `"error"`. + +In addition, `warn` and `error` will color the **entire** message for better attention. If you are printing large blocks of help text about an error, better use `logger.info`. + +::: + +### Using the template literal tag + +The template literal tag evaluates the template and expressions embedded. `interpolate` returns a new string, while other logging functions prints it. Below is a typical usage: + +```js +import logger from '@docusaurus/logger'; + +logger.info`Hello name=${name}! You have number=${money} dollars. Here are the ${ + items.length > 1 ? 'items' : 'item' +} on the shelf: ${items} +To buy anything, enter code=${'buy x'} where code=${'x'} is the item's name; to quit, press code=${'Ctrl + C'}.`; +``` + +An embedded expression is optionally preceded by a flag in the form `[a-z]+=` (a few lowercase letters, followed by an equals sign, directly preceding the embedded expression). If the expression is not preceded by any flag, it's printed out as-is. Otherwise, it's formatted with one of the formatters: + +- `path=`: `path` +- `url=`: `url` +- `name=`: `name` +- `code=`: `code` +- `subdue=`: `subdue` +- `number=`: `num` + +If the expression is an array, it's formatted by `` `\n- ${array.join('\n- ')}\n` `` (note it automatically gets a leading line end). Each member is formatted by itself and the bullet is not formatted. So you would see the above message printed as: + +![Some text output in the terminal, containing array, code, name, and number formatting](./demo.png) diff --git a/website/versioned_docs/version-3.9.0/api/plugin-methods/README.mdx b/website/versioned_docs/version-3.9.0/api/plugin-methods/README.mdx new file mode 100644 index 0000000000..e25bc9246e --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugin-methods/README.mdx @@ -0,0 +1,144 @@ +# Plugin Method References + +:::warning + +This section is a work in progress. Anchor links or even URLs are not guaranteed to be stable. + +::: + +Plugin APIs are shared by themes and plugins—themes are loaded just like plugins. + +## Plugin module {#plugin-module} + +Every plugin is imported as a module. The module is expected to have the following members: + +- A **default export**: the constructor function for the plugin. +- **Named exports**: the [static methods](./static-methods.mdx) called before plugins are initialized. + +## Plugin constructor {#plugin-constructor} + +The plugin module's default export is a constructor function with the signature `(context: LoadContext, options: PluginOptions) => Plugin | Promise<Plugin>`. + +### `context` {#context} + +`context` is plugin-agnostic, and the same object will be passed into all plugins used for a Docusaurus website. The `context` object contains the following fields: + +```ts +type LoadContext = { + siteDir: string; + generatedFilesDir: string; + siteConfig: DocusaurusConfig; + outDir: string; + baseUrl: string; +}; +``` + +### `options` {#options} + +`options` are the [second optional parameter when the plugins are used](../../using-plugins.mdx#configuring-plugins). `options` are plugin-specific and are specified by users when they use them in `docusaurus.config.js`. If there's a [`validateOptions`](./static-methods.mdx#validateOptions) function exported, the `options` will be validated and normalized beforehand. + +Alternatively, if a preset contains the plugin, the preset will then be in charge of passing the correct options into the plugin. It is up to the individual plugin to define what options it takes. + +## Example {#example} + +Here's a mental model for a presumptuous plugin implementation. + +```js +// A JavaScript function that returns an object. +// `context` is provided by Docusaurus. Example: siteConfig can be accessed from context. +// `opts` is the user-defined options. +export default async function myPlugin(context, opts) { + return { + // A compulsory field used as the namespace for directories to cache + // the intermediate data for each plugin. + // If you're writing your own local plugin, you will want it to + // be unique in order not to potentially conflict with imported plugins. + // A good way will be to add your own project name within. + name: 'docusaurus-my-project-cool-plugin', + + async loadContent() { + // The loadContent hook is executed after siteConfig and env has been loaded. + // You can return a JavaScript object that will be passed to contentLoaded hook. + }, + + async contentLoaded({content, actions}) { + // The contentLoaded hook is done after loadContent hook is done. + // `actions` are set of functional API provided by Docusaurus (e.g. addRoute) + }, + + async postBuild(props) { + // After docusaurus <build> finish. + }, + + // TODO + async postStart(props) { + // docusaurus <start> finish + }, + + // TODO + afterDevServer(app, server) { + // https://webpack.js.org/configuration/dev-server/#devserverbefore + }, + + // TODO + beforeDevServer(app, server) { + // https://webpack.js.org/configuration/dev-server/#devserverafter + }, + + configureWebpack(config, isServer, utils, content) { + // Modify internal webpack config. If returned value is an Object, it + // will be merged into the final config using webpack-merge; + // If the returned value is a function, it will receive the config as the 1st argument and an isServer flag as the 2nd argument. + }, + + getPathsToWatch() { + // Paths to watch. + }, + + getThemePath() { + // Returns the path to the directory where the theme components can + // be found. + }, + + getClientModules() { + // Return an array of paths to the modules that are to be imported + // in the client bundle. These modules are imported globally before + // React even renders the initial UI. + }, + + extendCli(cli) { + // Register an extra command to enhance the CLI of Docusaurus + }, + + injectHtmlTags({content}) { + // Inject head and/or body HTML tags. + }, + + async getTranslationFiles({content}) { + // Return translation files + }, + + translateContent({content, translationFiles}) { + // translate the plugin content here + }, + + translateThemeConfig({themeConfig, translationFiles}) { + // translate the site themeConfig here + }, + + async getDefaultCodeTranslationMessages() { + // return default theme translations here + }, + }; +} + +export function validateOptions({options, validate}) { + const validatedOptions = validate(myValidationSchema, options); + return validatedOptions; +} + +export function validateThemeConfig({themeConfig, validate}) { + const validatedThemeConfig = validate(myValidationSchema, options); + return validatedThemeConfig; +} +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugin-methods/_category_.yml b/website/versioned_docs/version-3.9.0/api/plugin-methods/_category_.yml new file mode 100644 index 0000000000..86cb36c246 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugin-methods/_category_.yml @@ -0,0 +1,2 @@ +label: Plugin method references +position: 1 diff --git a/website/versioned_docs/version-3.9.0/api/plugin-methods/extend-infrastructure.mdx b/website/versioned_docs/version-3.9.0/api/plugin-methods/extend-infrastructure.mdx new file mode 100644 index 0000000000..ec0b0542cf --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugin-methods/extend-infrastructure.mdx @@ -0,0 +1,132 @@ +--- +sidebar_position: 2 +--- + +# Extending infrastructure + +Docusaurus has some infrastructure like hot reloading, CLI, and swizzling, that can be extended by external plugins. + +## `getPathsToWatch()` {#getPathsToWatch} + +Specifies the paths to watch for plugins and themes. The paths are watched by the dev server so that the plugin lifecycles are reloaded when contents in the watched paths change. Note that the plugins and themes modules are initially called with `context` and `options` from Node, which you may use to find the necessary directory information about the site. + +Use this for files that are consumed server-side, because theme files are automatically watched by Webpack dev server. + +Example: + +```js title="docusaurus-plugin/src/index.js" +import path from 'path'; + +export default function (context, options) { + return { + name: 'docusaurus-plugin', + // highlight-start + getPathsToWatch() { + const contentPath = path.resolve(context.siteDir, options.path); + return [`${contentPath}/**/*.{ts,tsx}`]; + }, + // highlight-end + }; +} +``` + +## `extendCli(cli)` {#extendCli} + +Register an extra command to enhance the CLI of Docusaurus. `cli` is a [commander](https://www.npmjs.com/package/commander/v/5.1.0) object. + +:::warning + +The commander version matters! We use commander v5, and make sure you are referring to the right version documentation for available APIs. + +::: + +Example: + +```js title="docusaurus-plugin/src/index.js" +export default function (context, options) { + return { + name: 'docusaurus-plugin', + // highlight-start + extendCli(cli) { + cli + .command('roll') + .description('Roll a random number between 1 and 1000') + .action(() => { + console.log(Math.floor(Math.random() * 1000 + 1)); + }); + }, + // highlight-end + }; +} +``` + +## `getThemePath()` {#getThemePath} + +Returns the path to the directory where the theme components can be found. When your users call `swizzle`, `getThemePath` is called and its returned path is used to find your theme components. Relative paths are resolved against the folder containing the entry point. + +For example, your `getThemePath` can be: + +```js title="my-theme/src/index.js" +export default function (context, options) { + return { + name: 'my-theme', + // highlight-start + getThemePath() { + return './theme'; + }, + // highlight-end + }; +} +``` + +## `getTypeScriptThemePath()` {#getTypeScriptThemePath} + +Similar to `getThemePath()`, it should return the path to the directory where the source code of TypeScript theme components can be found. This path is purely for swizzling TypeScript theme components, and theme components under this path will **not** be resolved by Webpack. Therefore, it is not a replacement for `getThemePath()`. Typically, you can make the path returned by `getTypeScriptThemePath()` be your source directory, and make the path returned by `getThemePath()` be the compiled JavaScript output. + +:::tip + +For TypeScript theme authors: you are strongly advised to make your compiled output as human-readable as possible. Only strip type annotations and don't transpile any syntaxes, because they will be handled by Webpack's Babel loader based on the targeted browser versions. + +You should also format these files with Prettier. Remember—JS files can and will be directly consumed by your users. + +::: + +Example: + +```js title="my-theme/src/index.js" +export default function (context, options) { + return { + name: 'my-theme', + // highlight-start + getThemePath() { + // Where compiled JavaScript output lives + return '../lib/theme'; + }, + getTypeScriptThemePath() { + // Where TypeScript source code lives + return '../src/theme'; + }, + // highlight-end + }; +} +``` + +## `getSwizzleComponentList()` {#getSwizzleComponentList} + +**This is a static method, not attached to any plugin instance.** + +Returns a list of stable components that are considered safe for swizzling. These components will be swizzlable without `--danger`. All components are considered unstable by default. If an empty array is returned, all components are considered unstable. If `undefined` is returned, all components are considered stable. + +```js title="my-theme/src/index.js" +export function getSwizzleComponentList() { + return [ + 'CodeBlock', + 'DocSidebar', + 'Footer', + 'NotFound', + 'SearchBar', + 'hooks/useTheme', + 'prism-include-languages', + ]; +} +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugin-methods/i18n-lifecycles.mdx b/website/versioned_docs/version-3.9.0/api/plugin-methods/i18n-lifecycles.mdx new file mode 100644 index 0000000000..d9a6297569 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugin-methods/i18n-lifecycles.mdx @@ -0,0 +1,121 @@ +--- +sidebar_position: 3 +--- + +# I18n lifecycles + +Plugins use these lifecycles to load i18n-related data. + +## `getTranslationFiles({content})` {#getTranslationFiles} + +Plugins declare the JSON translation files they want to use. + +Returns translation files `{path: string, content: ChromeI18nJSON}`: + +- `path`: relative to the plugin localized folder `i18n/[locale]/[pluginName]`. Extension `.json` should be omitted to remain generic. +- `content`: using the Chrome i18n JSON format. + +These files will be written by the [`write-translations` CLI](../../cli.mdx#docusaurus-write-translations-sitedir) to the plugin i18n subfolder, and will be read in the appropriate locale before calling [`translateContent()`](#translateContent) and [`translateThemeConfig()`](#translateThemeConfig) + +Example: + +```js title="my-plugin.js" +export default function (context, options) { + return { + name: 'my-plugin', + // highlight-start + async getTranslationFiles({content}) { + return [ + { + path: 'sidebar-labels', + content: { + someSidebarLabel: { + message: 'Some Sidebar Label', + description: 'A label used in my plugin in the sidebar', + }, + someLabelFromContent: content.myLabel, + }, + }, + ]; + }, + // highlight-end + }; +} +``` + +## `translateContent({content,translationFiles})` {#translateContent} + +Translate the plugin content, using the localized translation files. + +Returns the localized plugin content. + +The `contentLoaded()` lifecycle will be called with the localized plugin content returned by `translateContent()`. + +Example: + +```js title="my-plugin.js" +export default function (context, options) { + return { + name: 'my-plugin', + // highlight-start + translateContent({content, translationFiles}) { + const myTranslationFile = translationFiles.find( + (f) => f.path === 'myTranslationFile', + ); + return { + ...content, + someContentLabel: myTranslationFile.someContentLabel.message, + }; + }, + // highlight-end + }; +} +``` + +## `translateThemeConfig({themeConfig,translationFiles})` {#translateThemeConfig} + +Translate the site `themeConfig` labels, using the localized translation files. + +Returns the localized `themeConfig`. + +Example: + +```js title="my-plugin.js" +export default function (context, options) { + return { + name: 'my-theme', + // highlight-start + translateThemeConfig({themeConfig, translationFiles}) { + const myTranslationFile = translationFiles.find( + (f) => f.path === 'myTranslationFile', + ); + return { + ...themeConfig, + someThemeConfigLabel: myTranslationFile.someThemeConfigLabel.message, + }; + }, + // highlight-end + }; +} +``` + +## `async getDefaultCodeTranslationMessages()` {#getDefaultCodeTranslationMessages} + +Themes using the `<Translate>` API can provide default code translation messages. + +It should return messages in `Record<string, string>`, where keys are translation IDs and values are messages (without the description) localized using the site's current locale. + +Example: + +```js title="my-plugin.js" +export default function (context, options) { + return { + name: 'my-theme', + // highlight-start + async getDefaultCodeTranslationMessages() { + return readJsonFile(`${context.i18n.currentLocale}.json`); + }, + // highlight-end + }; +} +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugin-methods/lifecycle-apis.mdx b/website/versioned_docs/version-3.9.0/api/plugin-methods/lifecycle-apis.mdx new file mode 100644 index 0000000000..bc6c1f77aa --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugin-methods/lifecycle-apis.mdx @@ -0,0 +1,493 @@ +--- +sidebar_position: 1 +toc_max_heading_level: 4 +--- + +# Lifecycle APIs + +During the build, plugins are loaded in parallel to fetch their own contents and render them to routes. Plugins may also configure webpack or post-process the generated files. + +## `async loadContent()` {#loadContent} + +Plugins should use this lifecycle to fetch from data sources (filesystem, remote API, headless CMS, etc.) or do some server processing. The return value is the content it needs. + +For example, this plugin below returns a random integer between 1 and 10 as content. + +```js title="docusaurus-plugin/src/index.js" +export default function (context, options) { + return { + name: 'docusaurus-plugin', + // highlight-start + async loadContent() { + return 1 + Math.floor(Math.random() * 10); + }, + // highlight-end + }; +} +``` + +## `async contentLoaded({content, actions})` {#contentLoaded} + +The data that was loaded in `loadContent` will be consumed in `contentLoaded`. It can be rendered to routes, registered as global data, etc. + +### `content` {#content} + +`contentLoaded` will be called _after_ `loadContent` is done. The return value of `loadContent()` will be passed to `contentLoaded` as `content`. + +### `actions` {#actions} + +`actions` contain three functions: + +#### `addRoute(config: RouteConfig): void` {#addRoute} + +Create a route to add to the website. + +```ts +export type RouteConfig = { + /** + * With leading slash. Trailing slash will be normalized by config. + */ + path: string; + /** + * Component used to render this route, a path that the bundler can `require`. + */ + component: string; + /** + * Props. Each entry should be `[propName]: pathToPropModule` (created with + * `createData`) + */ + modules?: RouteModules; + /** + * The route context will wrap the `component`. Use `useRouteContext` to + * retrieve what's declared here. Note that all custom route context declared + * here will be namespaced under {@link RouteContext.data}. + */ + context?: RouteModules; + /** + * Nested routes config, useful for "layout routes" having subroutes. + */ + routes?: RouteConfig[]; + /** + * React router config option: `exact` routes would not match subroutes. + */ + exact?: boolean; + /** + * React router config option: `strict` routes are sensitive to the presence + * of a trailing slash. + */ + strict?: boolean; + /** + * Used to sort routes. + * Higher-priority routes will be matched first. + */ + priority?: number; + /** + * Optional route metadata + */ + metadata?: RouteMetadata; + /** + * Extra props; will be available on the client side. + */ + [propName: string]: unknown; +}; + +/** + * Plugin authors can assign extra metadata to the created routes + * It is only available on the Node.js side, and not sent to the browser + * Optional: plugin authors are encouraged but not required to provide it + * + * Some plugins might use this data to provide additional features. + * This is the case of the sitemap plugin to provide support for "lastmod". + * See also: https://github.com/facebook/docusaurus/pull/9954 + */ +export type RouteMetadata = { + /** + * The source code file path that led to the creation of the current route + * In official content plugins, this is usually a Markdown or React file + * This path is expected to be relative to the site directory + */ + sourceFilePath?: string; + /** + * The last updated date of this route + * This is generally read from the Git history of the sourceFilePath + * but can also be provided through other means (usually front matter) + * + * This has notably been introduced for adding "lastmod" support to the + * sitemap plugin, see https://github.com/facebook/docusaurus/pull/9954 + */ + lastUpdatedAt?: number; +}; + +type RouteModules = { + [module: string]: Module | RouteModules | RouteModules[]; +}; + +type Module = + | { + path: string; + __import?: boolean; + query?: ParsedUrlQueryInput; + } + | string; +``` + +#### `createData(name: string, data: any): Promise<string>` {#createData} + +A declarative callback to create static data (generally JSON or string) which can later be provided to your routes as props. Takes the file name and data to be stored, and returns the actual data file's path. + +For example, this plugin below creates a `/friends` page which displays `Your friends are: Yangshun, Sebastien`: + +```jsx title="website/src/components/Friends.js" +import React from 'react'; + +export default function FriendsComponent({friends}) { + return <div>Your friends are {friends.join(',')}</div>; +} +``` + +```js title="docusaurus-friends-plugin/src/index.js" +export default function friendsPlugin(context, options) { + return { + name: 'docusaurus-friends-plugin', + // highlight-start + async contentLoaded({content, actions}) { + const {createData, addRoute} = actions; + // Create friends.json + const friends = ['Yangshun', 'Sebastien']; + const friendsJsonPath = await createData( + 'friends.json', + JSON.stringify(friends), + ); + + // Add the '/friends' routes, and ensure it receives the friends props + addRoute({ + path: '/friends', + component: '@site/src/components/Friends.js', + modules: { + // propName -> JSON file path + friends: friendsJsonPath, + }, + exact: true, + }); + }, + // highlight-end + }; +} +``` + +#### `setGlobalData(data: any): void` {#setGlobalData} + +This function permits one to create some global plugin data that can be read from any page, including the pages created by other plugins, and your theme layout. + +This data becomes accessible to your client-side/theme code through the [`useGlobalData`](../../docusaurus-core.mdx#useGlobalData) and [`usePluginData`](../../docusaurus-core.mdx#usePluginData) hooks. + +:::warning + +Global data is... global: its size affects the loading time of all pages of your site, so try to keep it small. Prefer `createData` and page-specific data whenever possible. + +::: + +For example, this plugin below creates a `/friends` page which displays `Your friends are: Yangshun, Sebastien`: + +```jsx title="website/src/components/Friends.js" +import React from 'react'; +import {usePluginData} from '@docusaurus/useGlobalData'; + +export default function FriendsComponent() { + const {friends} = usePluginData('docusaurus-friends-plugin'); + return <div>Your friends are {friends.join(',')}</div>; +} +``` + +```js title="docusaurus-friends-plugin/src/index.js" +export default function friendsPlugin(context, options) { + return { + name: 'docusaurus-friends-plugin', + // highlight-start + async contentLoaded({content, actions}) { + const {setGlobalData, addRoute} = actions; + // Create friends global data + setGlobalData({friends: ['Yangshun', 'Sebastien']}); + + // Add the '/friends' routes + addRoute({ + path: '/friends', + component: '@site/src/components/Friends.js', + exact: true, + }); + }, + // highlight-end + }; +} +``` + +## `configureWebpack(config, isServer, utils, content)` {#configureWebpack} + +Modifies the internal webpack config. If the return value is a JavaScript object, it will be merged into the final config using [`webpack-merge`](https://github.com/survivejs/webpack-merge). If it is a function, it will be called and receive `config` as the first argument and an `isServer` flag as the second argument. + +:::warning + +The API of `configureWebpack` will be modified in the future to accept an object (`configureWebpack({config, isServer, utils, content})`) + +::: + +### `config` {#config} + +`configureWebpack` is called with `config` generated according to client/server build. You may treat this as the base config to be merged with. + +### `isServer` {#isServer} + +`configureWebpack` will be called both in server build and in client build. The server build receives `true` and the client build receives `false` as `isServer`. + +### `utils` {#utils} + +`configureWebpack` also receives an util object: + +- `getStyleLoaders(isServer: boolean, cssOptions: {[key: string]: any}): Loader[]` +- `getJSLoader(isServer: boolean, cacheOptions?: {}): Loader | null` + +You may use them to return your webpack configuration conditionally. + +For example, this plugin below modify the webpack config to transpile `.foo` files. + +```js title="docusaurus-plugin/src/index.js" +export default function (context, options) { + return { + name: 'custom-docusaurus-plugin', + // highlight-start + configureWebpack(config, isServer, utils) { + const {getJSLoader} = utils; + return { + module: { + rules: [ + { + test: /\.foo$/, + use: [getJSLoader(isServer), 'my-custom-webpack-loader'], + }, + ], + }, + }; + }, + // highlight-end + }; +} +``` + +### `content` {#content-1} + +`configureWebpack` will be called both with the content loaded by the plugin. + +### Merge strategy {#merge-strategy} + +We merge the Webpack configuration parts of plugins into the global Webpack config using [webpack-merge](https://github.com/survivejs/webpack-merge). + +It is possible to specify the merge strategy. For example, if you want a webpack rule to be prepended instead of appended: + +```js title="docusaurus-plugin/src/index.js" +export default function (context, options) { + return { + name: 'custom-docusaurus-plugin', + configureWebpack(config, isServer, utils) { + return { + // highlight-start + mergeStrategy: {'module.rules': 'prepend'}, + module: {rules: [myRuleToPrepend]}, + // highlight-end + }; + }, + }; +} +``` + +Read the [webpack-merge strategy doc](https://github.com/survivejs/webpack-merge#merging-with-strategies) for more details. + +### Configuring dev server {#configuring-dev-server} + +The dev server can be configured through returning a `devServer` field. + +```js title="docusaurus-plugin/src/index.js" +export default function (context, options) { + return { + name: 'custom-docusaurus-plugin', + configureWebpack(config, isServer, utils) { + return { + // highlight-start + devServer: { + open: '/docs', // Opens localhost:3000/docs instead of localhost:3000/ + }, + // highlight-end + }; + }, + }; +} +``` + +## `configurePostCss(options)` {#configurePostCss} + +Modifies [`postcssOptions` of `postcss-loader`](https://webpack.js.org/loaders/postcss-loader/#postcssoptions) during the generation of the client bundle. + +Should return the mutated `postcssOptions`. + +By default, `postcssOptions` looks like this: + +```js +const postcssOptions = { + ident: 'postcss', + plugins: [require('autoprefixer')], +}; +``` + +Example: + +```js title="docusaurus-plugin/src/index.js" +export default function (context, options) { + return { + name: 'docusaurus-plugin', + // highlight-start + configurePostCss(postcssOptions) { + // Appends new PostCSS plugin. + postcssOptions.plugins.push(require('postcss-import')); + return postcssOptions; + }, + // highlight-end + }; +} +``` + +## `postBuild(props)` {#postBuild} + +Called when a (production) build finishes. + +```ts +interface Props { + siteDir: string; + generatedFilesDir: string; + siteConfig: DocusaurusConfig; + outDir: string; + baseUrl: string; + headTags: string; + preBodyTags: string; + postBodyTags: string; + routesPaths: string[]; + routesBuildMetadata: {[location: string]: {noIndex: boolean}}; + plugins: Plugin<any>[]; + content: Content; +} +``` + +Example: + +```js title="docusaurus-plugin/src/index.js" +export default function (context, options) { + return { + name: 'docusaurus-plugin', + // highlight-start + async postBuild({siteConfig = {}, routesPaths = [], outDir}) { + // Print out to console all the rendered routes. + routesPaths.map((route) => { + console.log(route); + }); + }, + // highlight-end + }; +} +``` + +## `injectHtmlTags({content})` {#injectHtmlTags} + +Inject head and/or body HTML tags to Docusaurus generated HTML. + +`injectHtmlTags` will be called both with the content loaded by the plugin. + +```ts +function injectHtmlTags(): { + headTags?: HtmlTags; + preBodyTags?: HtmlTags; + postBodyTags?: HtmlTags; +}; + +type HtmlTags = string | HtmlTagObject | (string | HtmlTagObject)[]; + +type HtmlTagObject = { + /** + * Attributes of the HTML tag + * E.g. `{'disabled': true, 'value': 'demo', 'rel': 'preconnect'}` + */ + attributes?: { + [attributeName: string]: string | boolean; + }; + /** + * The tag name e.g. `div`, `script`, `link`, `meta` + */ + tagName: string; + /** + * The inner HTML + */ + innerHTML?: string; +}; +``` + +Example: + +```js title="docusaurus-plugin/src/index.js" +export default function (context, options) { + return { + name: 'docusaurus-plugin', + loadContent: async () => { + return {remoteHeadTags: await fetchHeadTagsFromAPI()}; + }, + // highlight-start + injectHtmlTags({content}) { + return { + headTags: [ + { + tagName: 'link', + attributes: { + rel: 'preconnect', + href: 'https://www.github.com', + }, + }, + ...content.remoteHeadTags, + ], + preBodyTags: [ + { + tagName: 'script', + attributes: { + charset: 'utf-8', + src: '/noflash.js', + }, + }, + ], + postBodyTags: [`<div> This is post body </div>`], + }; + }, + // highlight-end + }; +} +``` + +Tags will be added as follows: + +- `headTags` will be inserted before the closing `</head>` tag after scripts added by config. +- `preBodyTags` will be inserted after the opening `<body>` tag before any child elements. +- `postBodyTags` will be inserted before the closing `</body>` tag after all child elements. + +## `getClientModules()` {#getClientModules} + +Returns an array of paths to the [client modules](../../advanced/client.mdx#client-modules) that are to be imported into the client bundle. + +As an example, to make your theme load a `customCss` or `customJs` file path from `options` passed in by the user: + +```js title="my-theme/src/index.js" +export default function (context, options) { + const {customCss, customJs} = options || {}; + return { + name: 'name-of-my-theme', + // highlight-start + getClientModules() { + return [customCss, customJs]; + }, + // highlight-end + }; +} +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugin-methods/static-methods.mdx b/website/versioned_docs/version-3.9.0/api/plugin-methods/static-methods.mdx new file mode 100644 index 0000000000..1ae95185b3 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugin-methods/static-methods.mdx @@ -0,0 +1,83 @@ +--- +sidebar_position: 4 +--- + +# Static methods + +Static methods are not part of the plugin instance—they are attached to the constructor function. These methods are used to validate and normalize the plugin options and theme config, which are then used as constructor parameters to initialize the plugin instance. + +## `validateOptions({options, validate})` {#validateOptions} + +Returns validated and normalized options for the plugin. This method is called before the plugin is initialized. You must return the options since they will be passed to the plugin during initialization. + +### `options` {#options} + +`validateOptions` is called with `options` passed to plugin for validation and normalization. + +### `validate` {#validate} + +`validateOptions` is called with `validate` function which takes a **[Joi](https://www.npmjs.com/package/joi)** schema and options as the arguments, returns validated and normalized options. `validate` will automatically handle error and validation config. + +:::tip + +[Joi](https://www.npmjs.com/package/joi) is recommended for validation and normalization of options. + +To avoid mixing Joi versions, use `import {Joi} from '@docusaurus/utils-validation'` + +::: + +If you don't use **[Joi](https://www.npmjs.com/package/joi)** for validation you can throw an Error in case of invalid options and return options in case of success. + +```js title="my-plugin/src/index.js" +export default function myPlugin(context, options) { + return { + name: 'docusaurus-plugin', + // rest of methods + }; +} + +// highlight-start +export function validateOptions({options, validate}) { + const validatedOptions = validate(myValidationSchema, options); + return validatedOptions; +} +// highlight-end +``` + +## `validateThemeConfig({themeConfig, validate})` {#validateThemeConfig} + +Return validated and normalized configuration for the theme. + +### `themeConfig` {#themeConfig} + +`validateThemeConfig` is called with `themeConfig` provided in `docusaurus.config.js` for validation and normalization. + +### `validate` {#validate-1} + +`validateThemeConfig` is called with `validate` function which takes a **[Joi](https://www.npmjs.com/package/joi)** schema and `themeConfig` as the arguments, returns validated and normalized options. `validate` will automatically handle error and validation config. + +:::tip + +[Joi](https://www.npmjs.com/package/joi) is recommended for validation and normalization of theme config. + +To avoid mixing Joi versions, use `import {Joi} from '@docusaurus/utils-validation'` + +::: + +If you don't use **[Joi](https://www.npmjs.com/package/joi)** for validation you can throw an Error in case of invalid options. + +```js title="my-theme/src/index.js" +export default function myPlugin(context, options) { + return { + name: 'docusaurus-plugin', + // rest of methods + }; +} + +// highlight-start +export function validateThemeConfig({themeConfig, validate}) { + const validatedThemeConfig = validate(myValidationSchema, options); + return validatedThemeConfig; +} +// highlight-end +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/_category_.yml b/website/versioned_docs/version-3.9.0/api/plugins/_category_.yml new file mode 100644 index 0000000000..cffabddbd5 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/_category_.yml @@ -0,0 +1,5 @@ +label: Plugins +position: 2 +link: + type: doc + id: api/plugins/plugins-overview # Dogfood using a "qualified id" diff --git a/website/versioned_docs/version-3.9.0/api/plugins/_partial-tags-file-api-ref-section.mdx b/website/versioned_docs/version-3.9.0/api/plugins/_partial-tags-file-api-ref-section.mdx new file mode 100644 index 0000000000..f6d247c70f --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/_partial-tags-file-api-ref-section.mdx @@ -0,0 +1,54 @@ +## Tags File {#tags-file} + +Use the [`tags` plugin option](#tags) to configure the path of a YAML tags file. + +By convention, the plugin will look for a `tags.yml` file at the root of your content folder(s). + +This file can contain a list of predefined tags. You can reference these tags by their keys in Markdown files thanks to the [`tags` front matter](#markdown-front-matter). + +:::tip Keeping tags consistent + +Using a tags file, you can ensure that your tags usage is consistent across your plugin content set. Use the [`onInlineTags: 'throw'`](#onInlineTags) plugin option to enforce this consistency and prevent usage of inline tags declared on the fly. + +::: + +### Types {#tags-file-types} + +The YAML content of the provided tags file should respect the following shape: + +```tsx +type Tag = { + label?: string; // Tag display label + permalink?: string; // Tag URL pathname segment + description?: string; // Tag description displayed in the tag page +}; + +type TagsFileInput = Record<string, Partial<Tag> | null>; +``` + +### Example {#tags-file-example} + +```yml title="tags.yml" +releases: + label: 'Product releases' + permalink: '/product-releases' + description: 'Content related to product releases.' + +# A partial tag definition is also valid +announcements: + label: 'Announcements' + +# An empty tag definition is also valid +# Other attributes will be inferred from the key +emptyTag: +``` + +```md title="content.md" +--- +tags: [releases, announcements, emptyTag] +--- + +# Title + +Content +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/overview.mdx b/website/versioned_docs/version-3.9.0/api/plugins/overview.mdx new file mode 100644 index 0000000000..94ecbed65c --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/overview.mdx @@ -0,0 +1,34 @@ +--- +sidebar_position: 0 +id: plugins-overview +sidebar_label: Plugins overview +slug: /api/plugins +--- + +# Docusaurus plugins + +We provide official Docusaurus plugins. + +## Content plugins {#content-plugins} + +These plugins are responsible for loading your site's content, and creating pages for your theme to render. + +- [@docusaurus/plugin-content-docs](./plugin-content-docs.mdx) +- [@docusaurus/plugin-content-blog](./plugin-content-blog.mdx) +- [@docusaurus/plugin-content-pages](./plugin-content-pages.mdx) + +## Behavior plugins {#behavior-plugins} + +These plugins will add a useful behavior to your Docusaurus site. + +- [@docusaurus/plugin-debug](./plugin-debug.mdx) +- [@docusaurus/plugin-sitemap](./plugin-sitemap.mdx) +- [@docusaurus/plugin-svgr](./plugin-svgr.mdx) +- [@docusaurus/plugin-rsdoctor](./plugin-rsdoctor.mdx) +- [@docusaurus/plugin-pwa](./plugin-pwa.mdx) +- [@docusaurus/plugin-client-redirects](./plugin-client-redirects.mdx) +- [@docusaurus/plugin-ideal-image](./plugin-ideal-image.mdx) +- [@docusaurus/plugin-google-analytics](./plugin-google-analytics.mdx) +- [@docusaurus/plugin-google-gtag](./plugin-google-gtag.mdx) +- [@docusaurus/plugin-google-tag-manager](./plugin-google-tag-manager.mdx) +- [@docusaurus/plugin-css-cascade-layers](./plugin-css-cascade-layers.mdx) diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-client-redirects.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-client-redirects.mdx new file mode 100644 index 0000000000..baca3a6bb9 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-client-redirects.mdx @@ -0,0 +1,127 @@ +--- +sidebar_position: 4 +slug: /api/plugins/@docusaurus/plugin-client-redirects +--- + +# 📦 plugin-client-redirects + +import APITable from '@site/src/components/APITable'; + +Docusaurus Plugin to generate **client-side redirects**. + +This plugin will write additional HTML pages to your static site that redirect the user to your existing Docusaurus pages with JavaScript. + +:::warning production only + +This plugin is always inactive in development and **only active in production** because it works on the build output. + +::: + +:::warning + +It is better to use server-side redirects whenever possible. + +Before using this plugin, you should look if your hosting provider doesn't offer this feature. + +::: + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-client-redirects +``` + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Option | Type | Default | Description | +| --- | --- | --- | --- | +| `fromExtensions` | `string[]` | `[]` | The extensions to be removed from the route after redirecting. | +| `toExtensions` | `string[]` | `[]` | The extensions to be appended to the route after redirecting. | +| `redirects` | <code>[RedirectRule](#RedirectRule)[]</code> | `[]` | The list of redirect rules. | +| `createRedirects` | <code>[CreateRedirectsFn](#CreateRedirectsFn)</code> | `undefined` | A callback to create a redirect rule. Docusaurus query this callback against every path it has created, and use its return value to output more paths. | + +```mdx-code-block +</APITable> +``` + +:::note + +This plugin will also read the [`siteConfig.onDuplicateRoutes`](../docusaurus.config.js.mdx#onDuplicateRoutes) config to adjust its logging level when multiple files will be emitted to the same location. + +::: + +### Types {#types} + +#### `RedirectRule` {#RedirectRule} + +```ts +type RedirectRule = { + to: string; + from: string | string[]; +}; +``` + +:::note + +The idea of "from" and "to" is central in this plugin. "From" means a path that you want to _create_, i.e. an extra HTML file that will be written; "to" means a path to want to redirect _to_, usually a route that Docusaurus already knows about. + +This is why you can have multiple "from" for the same "to": we will create multiple HTML files that all redirect to the same destination. On the other hand, one "from" can never have more than one "to": the written HTML file needs to have a determinate destination. + +::: + +#### `CreateRedirectsFn` {#CreateRedirectsFn} + +```ts +// The parameter `path` is a route that Docusaurus has already created. It can +// be seen as the "to", and your return value is the "from". Returning a falsy +// value will not create any redirect pages for this particular path. +type CreateRedirectsFn = (path: string) => string[] | string | null | undefined; +``` + +### Example configuration {#ex-config} + +Here's an example configuration: + +```js title="docusaurus.config.js" +export default { + plugins: [ + [ + '@docusaurus/plugin-client-redirects', + // highlight-start + { + fromExtensions: ['html', 'htm'], // /myPage.html -> /myPage + toExtensions: ['exe', 'zip'], // /myAsset -> /myAsset.zip (if latter exists) + redirects: [ + // /docs/oldDoc -> /docs/newDoc + { + to: '/docs/newDoc', + from: '/docs/oldDoc', + }, + // Redirect from multiple old paths to the new path + { + to: '/docs/newDoc2', + from: ['/docs/oldDocFrom2019', '/docs/legacyDocFrom2016'], + }, + ], + createRedirects(existingPath) { + if (existingPath.includes('/community')) { + // Redirect from /docs/team/X to /community/X and /docs/support/X to /community/X + return [ + existingPath.replace('/community', '/docs/team'), + existingPath.replace('/community', '/docs/support'), + ]; + } + return undefined; // Return a falsy value: no redirect created + }, + }, + // highlight-end + ], + ], +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-content-blog.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-content-blog.mdx new file mode 100644 index 0000000000..f8a17e4347 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-content-blog.mdx @@ -0,0 +1,419 @@ +--- +sidebar_position: 2 +slug: /api/plugins/@docusaurus/plugin-content-blog +--- + +# 📦 plugin-content-blog + +import APITable from '@site/src/components/APITable'; + +Provides the [Blog](blog.mdx) feature and is the default blog plugin for Docusaurus. + +:::warning some features production only + +The [feed feature](../../blog.mdx#feed) works by extracting the build output, and is **only active in production**. + +::: + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-content-blog +``` + +:::tip + +If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency. + +You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic). + +::: + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `path` | `string` | `'blog'` | Path to the blog content directory on the file system, relative to site dir. | +| `editUrl` | <code>string \| [EditUrlFn](#EditUrlFn)</code> | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativePostPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. | +| `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. | +| `blogTitle` | `string` | `'Blog'` | Blog page title for better SEO. | +| `blogDescription` | `string` | `'Blog'` | Blog page meta description for better SEO. | +| `blogSidebarCount` | <code>number \| 'ALL'</code> | `5` | Number of blog post elements to show in the blog sidebar. `'ALL'` to show all blog posts; `0` to disable. | +| `blogSidebarTitle` | `string` | `'Recent posts'` | Title of the blog sidebar. | +| `routeBasePath` | `string` | `'blog'` | URL route for the blog section of your site. **DO NOT** include a trailing slash. Use `/` to put the blog at root path. | +| `tagsBasePath` | `string` | `'tags'` | URL route for the tags section of your blog. Will be appended to `routeBasePath`. | +| `pageBasePath` | `string` | `'page'` | URL route for the pages section of your blog. Will be appended to `routeBasePath`. | +| `archiveBasePath` | <code>string \| null</code> | `'archive'` | URL route for the archive section of your blog. Will be appended to `routeBasePath`. **DO NOT** include a trailing slash. Use `null` to disable generation of archive. | +| `authorsBasePath` | `string` | `'authors'` | URL route for the authors pages of your blog. Will be appended to `path`. | +| `include` | `string[]` | `['**/*.{md,mdx}']` | Array of glob patterns matching Markdown files to be built, relative to the content path. | +| `exclude` | `string[]` | _See example configuration_ | Array of glob patterns matching Markdown files to be excluded. Serves as refinement based on the `include` option. | +| `postsPerPage` | <code>number \| 'ALL'</code> | `10` | Number of posts to show per page in the listing page. Use `'ALL'` to display all posts on one listing page. | +| `blogListComponent` | `string` | `'@theme/BlogListPage'` | Root component of the blog listing page. | +| `blogPostComponent` | `string` | `'@theme/BlogPostPage'` | Root component of each blog post page. | +| `blogTagsListComponent` | `string` | `'@theme/BlogTagsListPage'` | Root component of the tags list page. | +| `blogTagsPostsComponent` | `string` | `'@theme/BlogTagsPostsPage'` | Root component of the "posts containing tag" page. | +| `blogArchiveComponent` | `string` | `'@theme/BlogArchivePage'` | Root component of the blog archive page. | +| `blogAuthorsPostsComponent` | `string` | `'@theme/Blog/Pages/BlogAuthorsPostsPage'` | Root component of the blog author page. | +| `blogAuthorsListComponent` | `string` | `'@theme/Blog/Pages/BlogAuthorsListPage'` | Root component of the blog authors page index. | +| `remarkPlugins` | `any[]` | `[]` | Remark plugins passed to MDX. | +| `rehypePlugins` | `any[]` | `[]` | Rehype plugins passed to MDX. | +| `rehypePlugins` | `any[]` | `[]` | Recma plugins passed to MDX. | +| `beforeDefaultRemarkPlugins` | `any[]` | `[]` | Custom Remark plugins passed to MDX before the default Docusaurus Remark plugins. | +| `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. | +| `truncateMarker` | `RegExp` | `/<!--\s*truncate\s*-->/` \| `\{\/\*\s*truncate\s*\*\/\}/` | Truncate marker marking where the summary ends. | +| `showReadingTime` | `boolean` | `true` | Show estimated reading time for the blog post. | +| `readingTime` | `ReadingTimeFn` | The default reading time | A callback to customize the reading time number displayed. | +| `authorsMapPath` | `string` | `'authors.yml'` | Path to the authors map file, relative to the blog content directory. | +| `feedOptions` | _See below_ | `{type: ['rss', 'atom']}` | Blog feed. | +| `feedOptions.type` | <code>[FeedType](#FeedType) \| [FeedType](#FeedType)[] \| 'all' \| null</code> | **Required** | Type of feed to be generated. Use `null` to disable generation. | +| `feedOptions.createFeedItems` | <code>[CreateFeedItemsFn](#CreateFeedItemsFn) \| undefined</code> | `undefined` | An optional function which can be used to transform and / or filter the items in the feed. | +| `feedOptions.limit` | `number \| null \| false` | `20` | Limits the feed to the specified number of posts, `false` or `null` for all entries. Defaults to `20`. | +| `feedOptions.title` | `string` | `siteConfig.title` | Title of the feed. | +| `feedOptions.description` | `string` | <code>\`$\{siteConfig.title} Blog\`</code> | Description of the feed. | +| `feedOptions.copyright` | `string` | `undefined` | Copyright message. | +| `feedOptions.xslt` | <code>boolean \| [FeedXSLTOptions](#FeedXSLTOptions)</code> | `undefined` | Permits to style the blog XML feeds with XSLT so that browsers render them nicely. | +| `feedOptions.language` | `string` (See [documentation](http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes) for possible values) | `undefined` | Language metadata of the feed. | +| `sortPosts` | <code>'descending' \| 'ascending' </code> | `'descending'` | Governs the direction of blog post sorting. | +| `processBlogPosts` | <code>[ProcessBlogPostsFn](#ProcessBlogPostsFn)</code> | `undefined` | An optional function which can be used to transform blog posts (filter, modify, delete, etc...). | +| `showLastUpdateAuthor` | `boolean` | `false` | Whether to display the author who last updated the blog post. | +| `showLastUpdateTime` | `boolean` | `false` | Whether to display the last date the blog post was updated. This requires access to git history during the build, so will not work correctly with shallow clones (a common default for CI systems). With GitHub `actions/checkout`, use`fetch-depth: 0`. | +| `tags` | `string \| false \| null \| undefined` | `tags.yml` | Path to the YAML tags file listing pre-defined tags. Relative to the blog content directory. | +| `onInlineTags` | `'ignore' \| 'log' \| 'warn' \| 'throw'` | `warn` | The plugin behavior when blog posts contain inline tags (not appearing in the list of pre-defined tags, usually `tags.yml`). | +| `onUntruncatedBlogPosts` | `'ignore' \| 'log' \| 'warn' \| 'throw'` | `warn` | The plugin behavior when blog posts do not contain a truncate marker. | + +```mdx-code-block +</APITable> +``` + +### Types {#types} + +#### `EditUrlFn` {#EditUrlFn} + +```ts +type EditUrlFunction = (params: { + blogDirPath: string; + blogPath: string; + permalink: string; + locale: string; +}) => string | undefined; +``` + +#### `ReadingTimeFn` {#ReadingTimeFn} + +```ts +type ReadingTimeOptions = { + wordsPerMinute: number; +}; + +type ReadingTimeCalculator = (params: { + content: string; + locale: string; + frontMatter?: BlogPostFrontMatter & Record<string, unknown>; + options?: ReadingTimeOptions; +}) => number; + +type ReadingTimeFn = (params: { + content: string; + locale: string; + frontMatter: BlogPostFrontMatter & Record<string, unknown>; + defaultReadingTime: ReadingTimeCalculator; +}) => number | undefined; +``` + +#### `FeedType` {#FeedType} + +```ts +type FeedType = 'rss' | 'atom' | 'json'; +``` + +#### `FeedXSLTOptions` {#FeedXSLTOptions} + +Permits to style the blog XML feeds so that browsers render them nicely with [XSLT](https://developer.mozilla.org/en-US/docs/Web/XSLT). + +- Use `true` to let the blog use its built-in `.xsl` and `.css` files to style the blog feed +- Use a falsy value (`undefined | null | false`) to disable the feature +- Use a `string` to provide a file path to a custom `.xsl` file relative to the blog content folder. By convention, you must provide a `.css` file with the exact same name. + +```ts +type FeedXSLTOptions = + | boolean + | undefined + | null + | { + rss?: string | boolean | null | undefined; + atom?: string | boolean | null | undefined; + }; +``` + +#### `CreateFeedItemsFn` {#CreateFeedItemsFn} + +```ts +type CreateFeedItemsFn = (params: { + blogPosts: BlogPost[]; + siteConfig: DocusaurusConfig; + outDir: string; + defaultCreateFeedItemsFn: CreateFeedItemsFn; +}) => Promise<BlogFeedItem[]>; +``` + +#### `ProcessBlogPostsFn` {#ProcessBlogPostsFn} + +```ts +type ProcessBlogPostsFn = (params: { + blogPosts: BlogPost[]; +}) => Promise<void | BlogPost[]>; +``` + +### Example configuration {#ex-config} + +You can configure this plugin through preset options or plugin options. + +:::tip + +Most Docusaurus users configure this plugin through the preset options. + +::: + +```js config-tabs +// Preset Options: blog +// Plugin Options: @docusaurus/plugin-content-blog + +const config = { + path: 'blog', + // Simple use-case: string editUrl + // editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/', + // Advanced use-case: functional editUrl + editUrl: ({locale, blogDirPath, blogPath, permalink}) => + `https://github.com/facebook/docusaurus/edit/main/website/${blogDirPath}/${blogPath}`, + editLocalizedFiles: false, + blogTitle: 'Blog title', + blogDescription: 'Blog', + blogSidebarCount: 5, + blogSidebarTitle: 'All our posts', + routeBasePath: 'blog', + include: ['**/*.{md,mdx}'], + exclude: [ + '**/_*.{js,jsx,ts,tsx,md,mdx}', + '**/_*/**', + '**/*.test.{js,jsx,ts,tsx}', + '**/__tests__/**', + ], + postsPerPage: 10, + blogListComponent: '@theme/BlogListPage', + blogPostComponent: '@theme/BlogPostPage', + blogTagsListComponent: '@theme/BlogTagsListPage', + blogTagsPostsComponent: '@theme/BlogTagsPostsPage', + remarkPlugins: [require('./my-remark-plugin')], + rehypePlugins: [], + beforeDefaultRemarkPlugins: [], + beforeDefaultRehypePlugins: [], + truncateMarker: /<!--\s*(truncate)\s*-->/, + showReadingTime: true, + feedOptions: { + type: '', + title: '', + description: '', + copyright: '', + language: undefined, + createFeedItems: async (params) => { + const {blogPosts, defaultCreateFeedItems, ...rest} = params; + return defaultCreateFeedItems({ + // keep only the 10 most recent blog posts in the feed + blogPosts: blogPosts.filter((item, index) => index < 10), + ...rest, + }); + }, + }, +}; +``` + +## Markdown front matter {#markdown-front-matter} + +Markdown documents can use the following Markdown [front matter](../../guides/markdown-features/markdown-features-intro.mdx#front-matter) metadata fields, enclosed by a line `---` on either side. + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `authors` | `Authors` | `undefined` | List of blog post authors (or unique author). Read the [`authors` guide](../../blog.mdx#blog-post-authors) for more explanations. Prefer `authors` over the `author_*` front matter fields, even for single author blog posts. | +| `author` | `string` | `undefined` | ⚠️ Prefer using `authors`. The blog post author's name. | +| `author_url` | `string` | `undefined` | ⚠️ Prefer using `authors`. The URL that the author's name will be linked to. This could be a GitHub, X, Facebook profile URL, etc. | +| `author_image_url` | `string` | `undefined` | ⚠️ Prefer using `authors`. The URL to the author's thumbnail image. | +| `author_title` | `string` | `undefined` | ⚠️ Prefer using `authors`. A description of the author. | +| `title` | `string` | Markdown title | The blog post title. | +| `title_meta` | `string` | `frontMatter.title` | The blog post SEO metadata title, used in `<head>` for `<title>` and `og:title`. Permits to override `title` when the displayed title and SEO title should be different. | +| `sidebar_label` | `string` | `title` | A custom label for the blog sidebar, replacing the default one (`title`). | +| `date` | `string` | File name or file creation time | The blog post creation date. If not specified, this can be extracted from the file or folder name, e.g, `2021-04-15-blog-post.mdx`, `2021-04-15-blog-post/index.mdx`, `2021/04/15/blog-post.mdx`. Otherwise, it is the Markdown file creation time. | +| `tags` | `Tag[]` | `undefined` | A list of strings or objects of two string fields `label` and `permalink` to tag to your post. Strings can be a reference to keys of a [tags file](#tags-file) (usually `tags.yml`) | +| `draft` | `boolean` | `false` | Draft blog posts will only be available during development. | +| `unlisted` | `boolean` | `false` | Unlisted blog posts will be available in both development and production. They will be "hidden" in production, not indexed, excluded from sitemaps, and can only be accessed by users having a direct link. | +| `hide_table_of_contents` | `boolean` | `false` | Whether to hide the table of contents to the right. | +| `toc_min_heading_level` | `number` | `2` | The minimum heading level shown in the table of contents. Must be between 2 and 6 and lower or equal to the max value. | +| `toc_max_heading_level` | `number` | `3` | The max heading level shown in the table of contents. Must be between 2 and 6. | +| `keywords` | `string[]` | `undefined` | Keywords meta tag, which will become the `<meta name="keywords" content="keyword1,keyword2,..."/>` in `<head>`, used by search engines. | +| `description` | `string` | The first line of Markdown content | The description of your document, which will become the `<meta name="description" content="..."/>` and `<meta property="og:description" content="..."/>` in `<head>`, used by search engines. | +| `image` | `string` | `undefined` | Cover or thumbnail image that will be used as the `<meta property="og:image" content="..."/>` in the `<head>`, enhancing link previews on social media and messaging platforms. | +| `slug` | `string` | File path | Allows to customize the blog post URL (`/<routeBasePath>/<slug>`). Support multiple patterns: `slug: my-blog-post`, `slug: /my/path/to/blog/post`, slug: `/`. | +| `last_update` | `FrontMatterLastUpdate` | `undefined` | Allows overriding the last update author/date. Date can be any [parsable date string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse). | + +```mdx-code-block +</APITable> +``` + +```ts +type FrontMatterLastUpdate = {date?: string; author?: string}; + +type Tag = string | {label: string; permalink: string}; + +// An author key references an author from the global plugin authors.yml file +type AuthorKey = string; + +// Social platform name -> Social platform link +// Example: {MyPlatform: 'https://myplatform.com/myusername'} +// Pre-defined platforms +// ("x", "github", "twitter", "linkedin", "stackoverflow", "instagram", "bluesky", "mastodon", "threads", "twitch", "youtube", "email") accept handles: +// Example: {github: 'slorber'} +type AuthorSocials = Record<string, string>; + +type Author = { + key?: AuthorKey; + name: string; + title?: string; + url?: string; + image_url?: string; + socials?: AuthorSocials; +}; + +// The front matter authors field allows various possible shapes +type Authors = AuthorKey | Author | (AuthorKey | Author)[]; +``` + +Example: + +```md +--- +title: Welcome Docusaurus +authors: + - slorber + - yangshun + - name: Joel Marcey + title: Co-creator of Docusaurus 1 + url: https://github.com/JoelMarcey + image_url: https://github.com/JoelMarcey.png + socials: + x: joelmarcey + github: JoelMarcey +tags: [docusaurus] +description: This is my first post on Docusaurus. +image: https://i.imgur.com/mErPwqL.png +hide_table_of_contents: false +--- + +A Markdown blog post +``` + +import TagsFileApiRefSection from './_partial-tags-file-api-ref-section.mdx'; + +<TagsFileApiRefSection /> + +## Authors File {#authors-file} + +Use the [`authors` plugin option](#authors) to configure the path of a YAML authors file. + +By convention, the plugin will look for a `authors.yml` file at the root of your blog content folder(s). + +This file can contain a list of predefined [global blog authors](../../blog.mdx#global-authors). You can reference these authors by their keys in Markdown files thanks to the [`authors` front matter](#markdown-front-matter). + +### Types {#authors-file-types} + +The YAML content of the provided authors file should respect the following shape: + +```tsx +type AuthorsMapInput = { + [authorKey: string]: AuthorInput; +}; + +type AuthorInput = { + name?: string; + title?: string; + description?: string; + imageURL?: string; + url?: string; + email?: string; + page?: boolean | {permalink: string}; + socials?: Record<string, string>; + [customAuthorAttribute: string]: unknown; +}; +``` + +### Example {#authors-file-example} + +```yml title="tags.yml" +slorber: + name: Sébastien Lorber + title: Docusaurus maintainer + url: https://sebastienlorber.com + image_url: https://github.com/slorber.png + page: true + socials: + x: sebastienlorber + github: slorber + email: seb@example.com + +jmarcey: + name: Joel Marcey + title: Co-creator of Docusaurus 1 + url: https://github.com/JoelMarcey + image_url: https://github.com/JoelMarcey.png + email: jimarcey@gmail.com + page: + permalink: '/joel-marcey' + socials: + x: joelmarcey + github: JoelMarcey +``` + +```md title="blog/my-blog-post.md" +--- +authors: [slorber, jmarcey] +--- + +# My Blog Post + +Content +``` + +## i18n {#i18n} + +Read the [i18n introduction](../../i18n/i18n-introduction.mdx) first. + +### Translation files location {#translation-files-location} + +- **Base path**: `website/i18n/[locale]/docusaurus-plugin-content-blog` +- **Multi-instance path**: `website/i18n/[locale]/docusaurus-plugin-content-blog-[pluginId]` +- **JSON files**: extracted with [`docusaurus write-translations`](../../cli.mdx#docusaurus-write-translations-sitedir) +- **Markdown files**: `website/i18n/[locale]/docusaurus-plugin-content-blog` + +### Example file-system structure {#example-file-system-structure} + +```bash +website/i18n/[locale]/docusaurus-plugin-content-blog +│ +│ # translations for website/blog +├── authors.yml +├── first-blog-post.md +├── second-blog-post.md +│ +│ # translations for the plugin options that will be rendered +└── options.json +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-content-docs.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-content-docs.mdx new file mode 100644 index 0000000000..fa9ddbf53e --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-content-docs.mdx @@ -0,0 +1,376 @@ +--- +sidebar_position: 1 +slug: /api/plugins/@docusaurus/plugin-content-docs +--- + +# 📦 plugin-content-docs + +import APITable from '@site/src/components/APITable'; + +Provides the [Docs](../../guides/docs/docs-introduction.mdx) functionality and is the default docs plugin for Docusaurus. + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-content-docs +``` + +:::tip + +If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency. + +You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic). + +::: + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `path` | `string` | `'docs'` | Path to the docs content directory on the file system, relative to site directory. | +| `editUrl` | <code>string \| [EditUrlFunction](#EditUrlFunction)</code> | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativeDocPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. | +| `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. | +| `editCurrentVersion` | `boolean` | `false` | The edit URL will always target the current version doc instead of older versions. Ignored when `editUrl` is a function. | +| `routeBasePath` | `string` | `'docs'` | URL route for the docs section of your site. **DO NOT** include a trailing slash. Use `/` for shipping docs without base path. | +| `tagsBasePath` | `string` | `'tags'` | URL route for the tags list page of your site. It is prepended to the `routeBasePath`. | +| `include` | `string[]` | `['**/*.{md,mdx}']` | Array of glob patterns matching Markdown files to be built, relative to the content path. | +| `exclude` | `string[]` | _See example configuration_ | Array of glob patterns matching Markdown files to be excluded. Serves as refinement based on the `include` option. | +| `sidebarPath` | <code>false \| string</code> | `undefined` | Path to a sidebars configuration file, loaded in a Node.js context. Use `false` to disable sidebars, or `undefined` to create a fully autogenerated sidebar. | +| `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. See also [Collapsible categories](/docs/sidebar/items#collapsible-categories) | +| `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. See also [Expanded categories by default](/docs/sidebar/items#expanded-categories-by-default) | +| `sidebarItemsGenerator` | <code>[SidebarGenerator](#SidebarGenerator)</code> | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar/autogenerated#customize-the-sidebar-items-generator) | +| `numberPrefixParser` | <code>boolean \| [PrefixParser](#PrefixParser)</code> | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar/autogenerated#using-number-prefixes) | +| `docsRootComponent` | `string` | `'@theme/DocsRoot'` | Parent component of all the docs plugin pages (including all versions). Stays mounted when navigation between docs pages and versions. | +| `docVersionRootComponent` | `string` | `'@theme/DocVersionLayout'` | Parent component of all docs pages of an individual version (doc pages with sidebars, tags pages). Stays mounted when navigation between pages of that specific version. | +| `docRootComponent` | `string` | `'@theme/DocRoot'` | Parent component of all doc pages with sidebars (regular docs pages, category generated index pages). Stays mounted when navigation between such pages. | +| `docItemComponent` | `string` | `'@theme/DocItem'` | Main doc container, with TOC, pagination, etc. | +| `docTagsListComponent` | `string` | `'@theme/DocTagsListPage'` | Root component of the tags list page | +| `docTagDocListComponent` | `string` | `'@theme/DocTagDocListPage'` | Root component of the "docs containing tag X" page. | +| `docCategoryGeneratedIndexComponent` | `string` | `'@theme/DocCategoryGeneratedIndexPage'` | Root component of the generated category index page. | +| `remarkPlugins` | `any[]` | `[]` | Remark plugins passed to MDX. | +| `rehypePlugins` | `any[]` | `[]` | Rehype plugins passed to MDX. | +| `rehypePlugins` | `any[]` | `[]` | Recma plugins passed to MDX. | +| `beforeDefaultRemarkPlugins` | `any[]` | `[]` | Custom Remark plugins passed to MDX before the default Docusaurus Remark plugins. | +| `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. | +| `showLastUpdateAuthor` | `boolean` | `false` | Whether to display the author who last updated the doc. | +| `showLastUpdateTime` | `boolean` | `false` | Whether to display the last date the doc was updated. This requires access to git history during the build, so will not work correctly with shallow clones (a common default for CI systems). With GitHub `actions/checkout`, use`fetch-depth: 0`. | +| `breadcrumbs` | `boolean` | `true` | Enable or disable the breadcrumbs on doc pages. | +| `disableVersioning` | `boolean` | `false` | Explicitly disable versioning even when multiple versions exist. This will make the site only include the current version. Will error if `includeCurrentVersion: false` and `disableVersioning: true`. | +| `includeCurrentVersion` | `boolean` | `true` | Include the current version of your docs. | +| `lastVersion` | `string` | First version in `versions.json` | The version navigated to in priority and displayed by default for docs navbar items. | +| `onlyIncludeVersions` | `string[]` | All versions available | Only include a subset of all available versions. | +| `versions` | <code>[VersionsConfig](#VersionsConfig)</code> | `{}` | Independent customization of each version's properties. | +| `tags` | `string \| false \| null \| undefined` | `tags.yml` | Path to a YAML file listing pre-defined tags. Relative to the docs version content directories. | +| `onInlineTags` | `'ignore' \| 'log' \| 'warn' \| 'throw'` | `warn` | The plugin behavior when docs contain inline tags (not appearing in the list of pre-defined tags, usually `docs/tags.yml`). | + +```mdx-code-block +</APITable> +``` + +### Types {#types} + +#### `EditUrlFunction` {#EditUrlFunction} + +```ts +type EditUrlFunction = (params: { + version: string; + versionDocsDirPath: string; + docPath: string; + permalink: string; + locale: string; +}) => string | undefined; +``` + +#### `PrefixParser` {#PrefixParser} + +```ts +type PrefixParser = (filename: string) => { + filename: string; + numberPrefix?: number; +}; +``` + +#### `SidebarGenerator` {#SidebarGenerator} + +```ts +type SidebarGenerator = (generatorArgs: { + /** The sidebar item with type "autogenerated" to be transformed. */ + item: {type: 'autogenerated'; dirName: string}; + /** Useful metadata for the version this sidebar belongs to. */ + version: {contentPath: string; versionName: string}; + /** All the docs of that version (unfiltered). */ + docs: { + id: string; + title: string; + frontMatter: DocFrontMatter & Record<string, unknown>; + source: string; + sourceDirName: string; + sidebarPosition?: number | undefined; + }[]; + /** Number prefix parser configured for this plugin. */ + numberPrefixParser: PrefixParser; + /** The default category index matcher which you can override. */ + isCategoryIndex: CategoryIndexMatcher; + /** + * key is the path relative to the doc content directory, value is the + * category metadata file's content. + */ + categoriesMetadata: {[filePath: string]: CategoryMetadata}; + /** + * Useful to re-use/enhance the default sidebar generation logic from + * Docusaurus. + */ + defaultSidebarItemsGenerator: SidebarGenerator; + // Returns an array of sidebar items — same as what you can declare in + // sidebars.js, except for shorthands. See https://docusaurus.io/docs/sidebar/items +}) => Promise<SidebarItem[]>; + +type CategoryIndexMatcher = (param: { + /** The file name, without extension */ + fileName: string; + /** + * The list of directories, from lowest level to highest. + * If there's no dir name, directories is ['.'] + */ + directories: string[]; + /** The extension, with a leading dot */ + extension: string; +}) => boolean; +``` + +#### `VersionsConfig` {#VersionsConfig} + +```ts +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 <html> element of each doc */ + className?: string; +}; + +type VersionsConfig = {[versionName: string]: VersionConfig}; +``` + +### Example configuration {#ex-config} + +You can configure this plugin through preset options or plugin options. + +:::tip + +Most Docusaurus users configure this plugin through the preset options. + +::: + +```js config-tabs +// Preset Options: docs +// Plugin Options: @docusaurus/plugin-content-docs + +const config = { + path: 'docs', + breadcrumbs: true, + // Simple use-case: string editUrl + // editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/', + // Advanced use-case: functional editUrl + editUrl: ({versionDocsDirPath, docPath}) => + `https://github.com/facebook/docusaurus/edit/main/website/${versionDocsDirPath}/${docPath}`, + editLocalizedFiles: false, + editCurrentVersion: false, + routeBasePath: 'docs', + include: ['**/*.md', '**/*.mdx'], + exclude: [ + '**/_*.{js,jsx,ts,tsx,md,mdx}', + '**/_*/**', + '**/*.test.{js,jsx,ts,tsx}', + '**/__tests__/**', + ], + sidebarPath: 'sidebars.js', + async sidebarItemsGenerator({ + defaultSidebarItemsGenerator, + numberPrefixParser, + item, + version, + docs, + isCategoryIndex, + }) { + // Use the provided data to generate a custom sidebar slice + return [ + {type: 'doc', id: 'intro'}, + { + type: 'category', + label: 'Tutorials', + items: [ + {type: 'doc', id: 'tutorial1'}, + {type: 'doc', id: 'tutorial2'}, + ], + }, + ]; + }, + numberPrefixParser(filename) { + // Implement your own logic to extract a potential number prefix + const numberPrefix = findNumberPrefix(filename); + // Prefix found: return it with the cleaned filename + if (numberPrefix) { + return { + numberPrefix, + filename: filename.replace(prefix, ''), + }; + } + // No number prefix found + return {numberPrefix: undefined, filename}; + }, + docsRootComponent: '@theme/DocsRoot', + docVersionRootComponent: '@theme/DocVersionRoot', + docRootComponent: '@theme/DocRoot', + docItemComponent: '@theme/DocItem', + remarkPlugins: [require('./my-remark-plugin')], + rehypePlugins: [], + beforeDefaultRemarkPlugins: [], + beforeDefaultRehypePlugins: [], + showLastUpdateAuthor: false, + showLastUpdateTime: false, + disableVersioning: false, + includeCurrentVersion: true, + lastVersion: undefined, + versions: { + current: { + label: 'Android SDK v2.0.0 (WIP)', + path: 'android-2.0.0', + banner: 'none', + }, + '1.0.0': { + label: 'Android SDK v1.0.0', + path: 'android-1.0.0', + banner: 'unmaintained', + }, + }, + onlyIncludeVersions: ['current', '1.0.0', '2.0.0'], +}; +``` + +## Markdown front matter {#markdown-front-matter} + +Markdown documents can use the following Markdown [front matter](../../guides/markdown-features/markdown-features-intro.mdx#front-matter) metadata fields, enclosed by a line `---` on either side. + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `id` | `string` | file path (including folders, without the extension) | A unique document ID. | +| `title` | `string` | Markdown title or `id` | The text title of your document. Used for the page metadata and as a fallback value in multiple places (sidebar, next/previous buttons...). Automatically added at the top of your doc if it does not contain any Markdown title. | +| `pagination_label` | `string` | `sidebar_label` or `title` | The text used in the document next/previous buttons for this document. | +| `sidebar_label` | `string` | `title` | The text shown in the document sidebar for this document. | +| `sidebar_position` | `number` | Default ordering | Controls the position of a doc inside the generated sidebar slice when using `autogenerated` sidebar items. See also [Autogenerated sidebar metadata](/docs/sidebar/autogenerated#autogenerated-sidebar-metadata). | +| `sidebar_class_name` | `string` | `undefined` | Gives the corresponding sidebar label a special class name when using autogenerated sidebars. | +| `sidebar_custom_props` | `object` | `undefined` | Assign [custom props](../../guides/docs/sidebar/index.mdx#passing-custom-props) to the sidebar item referencing this doc | +| `displayed_sidebar` | `string` | `undefined` | Force the display of a given sidebar when browsing the current document. Read the [multiple sidebars guide](../../guides/docs/sidebar/multiple-sidebars.mdx) for details. | +| `hide_title` | `boolean` | `false` | Whether to hide the title at the top of the doc. It only hides a title declared through the front matter, and have no effect on a Markdown title at the top of your document. | +| `hide_table_of_contents` | `boolean` | `false` | Whether to hide the table of contents to the right. | +| `toc_min_heading_level` | `number` | `2` | The minimum heading level shown in the table of contents. Must be between 2 and 6 and lower or equal to the max value. | +| `toc_max_heading_level` | `number` | `3` | The max heading level shown in the table of contents. Must be between 2 and 6. | +| `pagination_next` | <code>string \| null</code> | Next doc in the sidebar | The ID of the documentation you want the "Next" pagination to link to. Use `null` to disable showing "Next" for this page. | +| `pagination_prev` | <code>string \| null</code> | Previous doc in the sidebar | The ID of the documentation you want the "Previous" pagination to link to. Use `null` to disable showing "Previous" for this page. | +| `parse_number_prefixes` | `boolean` | `numberPrefixParser` plugin option | Whether number prefix parsing is disabled on this doc. See also [Using number prefixes](/docs/sidebar/autogenerated#using-number-prefixes). | +| `custom_edit_url` | <code>string \| null</code> | Computed using the `editUrl` plugin option | The URL for editing this document. Use `null` to disable showing "Edit this page" for this page. | +| `keywords` | `string[]` | `undefined` | Keywords meta tag for the document page, for search engines. | +| `description` | `string` | The first line of Markdown content | The description of your document, which will become the `<meta name="description" content="..."/>` and `<meta property="og:description" content="..."/>` in `<head>`, used by search engines. | +| `image` | `string` | `undefined` | Cover or thumbnail image that will be used as the `<meta property="og:image" content="..."/>` in the `<head>`, enhancing link previews on social media and messaging platforms. | +| `slug` | `string` | File path | Allows to customize the document URL (`/<routeBasePath>/<slug>`). Support multiple patterns: `slug: my-doc`, `slug: /my/path/myDoc`, `slug: /`. | +| `tags` | `Tag[]` | `undefined` | A list of strings or objects of two string fields `label` and `permalink` to tag to your docs. Strings can be a reference to keys of a [tags file](#tags-file) (usually `tags.yml`) | +| `draft` | `boolean` | `false` | Draft documents will only be available during development. | +| `unlisted` | `boolean` | `false` | Unlisted documents will be available in both development and production. They will be "hidden" in production, not indexed, excluded from sitemaps, and can only be accessed by users having a direct link. | +| `last_update` | `FrontMatterLastUpdate` | `undefined` | Allows overriding the last update author/date. Date can be any [parsable date string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse). | + +```mdx-code-block +</APITable> +``` + +```ts +type FrontMatterLastUpdate = {date?: string; author?: string}; + +type Tag = string | {label: string; permalink: string}; +``` + +Example: + +```md +--- +id: doc-markdown +title: Docs Markdown Features +hide_title: false +hide_table_of_contents: false +sidebar_label: Markdown +sidebar_position: 3 +pagination_label: Markdown features +custom_edit_url: https://github.com/facebook/docusaurus/edit/main/docs/api-doc-markdown.md +description: How do I find you when I cannot solve this problem +keywords: + - docs + - docusaurus +tags: [docusaurus] +image: https://i.imgur.com/mErPwqL.png +slug: /myDoc +last_update: + date: 1/1/2000 + author: custom author name +--- + +# Markdown Features + +My Document Markdown content +``` + +import TagsFileApiRefSection from './_partial-tags-file-api-ref-section.mdx'; + +<TagsFileApiRefSection /> + +## i18n {#i18n} + +Read the [i18n introduction](../../i18n/i18n-introduction.mdx) first. + +### Translation files location {#translation-files-location} + +- **Base path**: `website/i18n/[locale]/docusaurus-plugin-content-docs` +- **Multi-instance path**: `website/i18n/[locale]/docusaurus-plugin-content-docs-[pluginId]` +- **JSON files**: extracted with [`docusaurus write-translations`](../../cli.mdx#docusaurus-write-translations-sitedir) +- **Markdown files**: `website/i18n/[locale]/docusaurus-plugin-content-docs/[versionName]` + +### Example file-system structure {#example-file-system-structure} + +```bash +website/i18n/[locale]/docusaurus-plugin-content-docs +│ +│ # translations for website/docs +├── current +│ ├── api +│ │ └── config.md +│ └── getting-started.md +├── current.json +│ +│ # translations for website/versioned_docs/version-1.0.0 +├── version-1.0.0 +│ ├── api +│ │ └── config.md +│ └── getting-started.md +└── version-1.0.0.json +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-content-pages.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-content-pages.mdx new file mode 100644 index 0000000000..b71ef05500 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-content-pages.mdx @@ -0,0 +1,160 @@ +--- +sidebar_position: 3 +slug: /api/plugins/@docusaurus/plugin-content-pages +--- + +# 📦 plugin-content-pages + +import APITable from '@site/src/components/APITable'; + +The default pages plugin for Docusaurus. The classic template ships with this plugin with default configurations. This plugin provides [creating pages](guides/creating-pages.mdx) functionality. + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-content-pages +``` + +:::tip + +If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency. + +You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic). + +::: + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `path` | `string` | `'src/pages'` | Path to data on filesystem relative to site dir. Components in this directory will be automatically converted to pages. | +| `editUrl` | <code>string \| [EditUrlFn](#EditUrlFn)</code> | `undefined` | **Only for Markdown pages**. Base URL to edit your site. The final URL is computed by `editUrl + relativePostPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. | +| `editLocalizedFiles` | `boolean` | `false` | **Only for Markdown pages**. The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. | +| `routeBasePath` | `string` | `'/'` | URL route for the pages section of your site. **DO NOT** include a trailing slash. | +| `include` | `string[]` | `['**/*.{js,jsx,ts,tsx,md,mdx}']` | Matching files will be included and processed. | +| `exclude` | `string[]` | _See example configuration_ | No route will be created for matching files. | +| `mdxPageComponent` | `string` | `'@theme/MDXPage'` | Component used by each MDX page. | +| `remarkPlugins` | `[]` | `any[]` | Remark plugins passed to MDX. | +| `rehypePlugins` | `[]` | `any[]` | Rehype plugins passed to MDX. | +| `rehypePlugins` | `any[]` | `[]` | Recma plugins passed to MDX. | +| `beforeDefaultRemarkPlugins` | `any[]` | `[]` | Custom Remark plugins passed to MDX before the default Docusaurus Remark plugins. | +| `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. | +| `showLastUpdateAuthor` | `boolean` | `false` | **Only for Markdown pages**. Whether to display the author who last updated the page. | +| `showLastUpdateTime` | `boolean` | `false` | **Only for Markdown pages**. Whether to display the last date the page post was updated. This requires access to git history during the build, so will not work correctly with shallow clones (a common default for CI systems). With GitHub `actions/checkout`, use`fetch-depth: 0`. | + +```mdx-code-block +</APITable> +``` + +### Types {#types} + +#### `EditUrlFn` {#EditUrlFn} + +```ts +type EditUrlFunction = (params: { + blogDirPath: string; + blogPath: string; + permalink: string; + locale: string; +}) => string | undefined; +``` + +### Example configuration {#ex-config} + +You can configure this plugin through preset options or plugin options. + +:::tip + +Most Docusaurus users configure this plugin through the preset options. + +::: + +```js config-tabs +// Preset Options: pages +// Plugin Options: @docusaurus/plugin-content-pages + +const config = { + path: 'src/pages', + routeBasePath: '', + include: ['**/*.{js,jsx,ts,tsx,md,mdx}'], + exclude: [ + '**/_*.{js,jsx,ts,tsx,md,mdx}', + '**/_*/**', + '**/*.test.{js,jsx,ts,tsx}', + '**/__tests__/**', + ], + mdxPageComponent: '@theme/MDXPage', + remarkPlugins: [require('./my-remark-plugin')], + rehypePlugins: [], + beforeDefaultRemarkPlugins: [], + beforeDefaultRehypePlugins: [], +}; +``` + +## Markdown front matter {#markdown-front-matter} + +Markdown pages can use the following Markdown [front matter](../../guides/markdown-features/markdown-features-intro.mdx#front-matter) metadata fields, enclosed by a line `---` on either side. + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `title` | `string` | Markdown title | The blog post title. | +| `description` | `string` | The first line of Markdown content | The description of your page, which will become the `<meta name="description" content="..."/>` and `<meta property="og:description" content="..."/>` in `<head>`, used by search engines. | +| `keywords` | `string[]` | `undefined` | Keywords meta tag, which will become the `<meta name="keywords" content="keyword1,keyword2,..."/>` in `<head>`, used by search engines. | +| `image` | `string` | `undefined` | Cover or thumbnail image that will be used as the `<meta property="og:image" content="..."/>` in the `<head>`, enhancing link previews on social media and messaging platforms. | +| `slug` | `string` | File path | Allows to customize the page URL (`/<routeBasePath>/<slug>`). Support multiple patterns: `slug: my-page`, `slug: /my/page`, slug: `/`. | +| `wrapperClassName` | `string` | | Class name to be added to the wrapper element to allow targeting specific page content. | +| `hide_table_of_contents` | `boolean` | `false` | Whether to hide the table of contents to the right. | +| `draft` | `boolean` | `false` | Draft pages will only be available during development. | +| `unlisted` | `boolean` | `false` | Unlisted pages will be available in both development and production. They will be "hidden" in production, not indexed, excluded from sitemaps, and can only be accessed by users having a direct link. | + +```mdx-code-block +</APITable> +``` + +Example: + +```md +--- +title: Markdown Page +description: Markdown page SEO description +wrapperClassName: markdown-page +hide_table_of_contents: false +draft: true +slug: /markdown-page +--- + +Markdown page content +``` + +## i18n {#i18n} + +Read the [i18n introduction](../../i18n/i18n-introduction.mdx) first. + +### Translation files location {#translation-files-location} + +- **Base path**: `website/i18n/[locale]/docusaurus-plugin-content-pages` +- **Multi-instance path**: `website/i18n/[locale]/docusaurus-plugin-content-pages-[pluginId]` +- **JSON files**: extracted with [`docusaurus write-translations`](../../cli.mdx#docusaurus-write-translations-sitedir) +- **Markdown files**: `website/i18n/[locale]/docusaurus-plugin-content-pages` + +### Example file-system structure {#example-file-system-structure} + +```bash +website/i18n/[locale]/docusaurus-plugin-content-pages +│ +│ # translations for website/src/pages +├── first-markdown-page.md +└── second-markdown-page.md +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-css-cascade-layers.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-css-cascade-layers.mdx new file mode 100644 index 0000000000..a155a02260 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-css-cascade-layers.mdx @@ -0,0 +1,95 @@ +--- +sidebar_position: 9 +slug: /api/plugins/@docusaurus/plugin-css-cascade-layers +--- + +# 📦 plugin-css-cascade-layers + +import APITable from '@site/src/components/APITable'; + +:::caution Experimental + +This plugin is mostly designed to be used internally by the classic preset through the [Docusaurus `future.v4.useCssCascadeLayers` flag](../docusaurus.config.js.mdx#future), although it can also be used as a standalone plugin. Please [let us know here](https://github.com/facebook/docusaurus/pull/11142) if you have a use case for it and help us design an API that makes sense for the future of Docusaurus. + +::: + +A plugin for wrapping CSS modules of your Docusaurus site in [CSS Cascade Layers](https://css-tricks.com/css-cascade-layers/). This modern CSS feature is widely supported by all browsers. It allows grouping CSS rules in layers of specificity and gives you more control over the CSS cascade. + +Use this plugin to: + +- apply a top-level `@layer myLayer { ... }` block rule around any CSS module, including un-layered third-party CSS. +- define an explicit layer ordering + +:::caution + +To use this plugin properly, it's recommended to have a solid understanding of [CSS Cascade Layers](https://css-tricks.com/css-cascade-layers/), the [CSS Cascade](https://developer.mozilla.org/docs/Web/CSS/CSS_cascade/Cascade) and [specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascade/Specificity). + +::: + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-css-cascade-layers +``` + +:::tip + +If you use the preset `@docusaurus/preset-classic`, this plugin is automatically configured for you with the [`siteConfig.future.v4.useCssCascadeLayers`](../docusaurus.config.js.mdx#future) flag. + +::: + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `layers` | `Layers` | **Built-in layers** | An object representing all the CSS cascade layers you want to use, and whether the layer should be applied to a given file path. See examples and types below. | + +```mdx-code-block +</APITable> +``` + +### Types {#types} + +#### `Layers` {#EditUrlFunction} + +```ts +type Layers = Record< + string, // layer name + (filePath: string) => boolean // layer matcher +>; +``` + +The `layers` object is defined by: + +- key: the name of a layer +- value: a function to define if a given CSS module file should be in that layer + +:::caution Order matters + +The object order matters: + +- the keys order defines an explicit CSS layer order +- when multiple layers match a file path, only the first layer will apply + +::: + +### Example configuration {#ex-config} + +You can configure this plugin through plugin options. + +```js +const options = { + layers: { + 'docusaurus.infima': (filePath) => + filePath.includes('/node_modules/infima/dist'), + 'docusaurus.theme-classic': (filePath) => + filePath.includes('/node_modules/@docusaurus/theme-classic/lib'), + }, +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-debug.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-debug.mdx new file mode 100644 index 0000000000..d764e61930 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-debug.mdx @@ -0,0 +1,108 @@ +--- +sidebar_position: 5 +slug: /api/plugins/@docusaurus/plugin-debug +--- + +# 📦 plugin-debug + +```mdx-code-block +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +``` + +The debug plugin will display useful debug information at [`http://localhost:3000/__docusaurus/debug`](http://localhost:3000/__docusaurus/debug). + +It is mostly useful for plugin authors, that will be able to inspect more easily the content of the `.docusaurus` folder (like the creates routes), but also be able to inspect data structures that are never written to disk, like the plugin data loaded through the `contentLoaded` lifecycle. + +:::info + +If you use the plugin via the classic preset, the preset will **enable the plugin in development and disable it in production** by default (`debug: undefined`) to avoid exposing potentially sensitive information. You can use `debug: true` to always enable it or `debug: false` to always disable it. + +If you use a standalone plugin, you may need to achieve the same effect by checking the environment: + +```js title="docusaurus.config.js" +export default { + plugins: [ + // highlight-next-line + process.env.NODE_ENV !== 'production' && '@docusaurus/plugin-debug', + ].filter(Boolean), +}; +``` + +::: + +:::note + +If you report a bug, we will probably ask you to have this plugin turned on in the production, so that we can inspect your deployment config more easily. + +If you don't have any sensitive information, you can keep it on in production [like we do](/__docusaurus/debug). + +::: + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-debug +``` + +:::tip + +If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency. + +You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic). + +::: + +## Configuration {#configuration} + +This plugin currently has no options. + +### Example configuration {#ex-config} + +You can configure this plugin through preset options or plugin options. + +:::tip + +Most Docusaurus users configure this plugin through the preset options. + +::: + +```mdx-code-block +<Tabs groupId="api-config-ex"> +<TabItem value="preset" label="Preset options"> +``` + +If you use a preset, configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic): + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + // highlight-next-line + debug: true, // This will enable the plugin in production + }, + ], + ], +}; +``` + +```mdx-code-block +</TabItem> +<TabItem value="plugin" label="Plugin Options"> +``` + +If you are using a standalone plugin, provide options directly to the plugin: + +```js title="docusaurus.config.js" +export default { + // highlight-next-line + plugins: ['@docusaurus/plugin-debug'], +}; +``` + +```mdx-code-block +</TabItem> +</Tabs> +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-google-analytics.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-google-analytics.mdx new file mode 100644 index 0000000000..a914d122be --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-google-analytics.mdx @@ -0,0 +1,77 @@ +--- +sidebar_position: 6 +slug: /api/plugins/@docusaurus/plugin-google-analytics +--- + +# 📦 plugin-google-analytics + +import APITable from '@site/src/components/APITable'; + +The default [Google Analytics](https://developers.google.com/analytics/devguides/collection/analyticsjs/) plugin. It is a JavaScript library for measuring how users interact with your website **in the production build**. If you are using Google Analytics 4 you might need to consider using [plugin-google-gtag](./plugin-google-gtag.mdx) instead. + +:::danger Deprecated + +This plugin is **deprecated** and became useless on July 1, 2023. + +Google is [moving away from Universal Analytics](https://blog.google/products/marketingplatform/analytics/prepare-for-future-with-google-analytics-4/). + +If you are still using this plugin with a `UA-*` tracking id, you should create a Google Analytics 4 account as soon as possible, and use [`@docusaurus/plugin-google-gtag`](./plugin-google-gtag.mdx) instead of this plugin. More details [here](https://github.com/facebook/docusaurus/issues/7221). + +::: + +:::warning production only + +This plugin is always inactive in development and **only active in production** to avoid polluting the analytics statistics. + +::: + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-google-analytics +``` + +:::tip + +If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency. + +You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic). + +::: + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `trackingID` | `string` | **Required** | The tracking ID of your analytics service. | +| `anonymizeIP` | `boolean` | `false` | Whether the IP should be anonymized when sending requests. | + +```mdx-code-block +</APITable> +``` + +### Example configuration {#ex-config} + +You can configure this plugin through preset options or plugin options. + +:::tip + +Most Docusaurus users configure this plugin through the preset options. + +::: + +```js config-tabs +// Preset Options: googleAnalytics +// Plugin Options: @docusaurus/plugin-google-analytics + +const config = { + trackingID: 'UA-141789564-1', + anonymizeIP: true, +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-google-gtag.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-google-gtag.mdx new file mode 100644 index 0000000000..ee30a0f3b8 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-google-gtag.mdx @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +slug: /api/plugins/@docusaurus/plugin-google-gtag +--- + +# 📦 plugin-google-gtag + +import APITable from '@site/src/components/APITable'; + +The default [Global Site Tag (gtag.js)](https://developers.google.com/tag-platform/gtagjs) plugin. It is a JavaScript tagging framework and API that allows you to send event data to Google Analytics, Google Ads, and Google Marketing Platform. This section describes how to configure a Docusaurus site to enable global site tag for Google Analytics. + +:::tip + +You can use [Google's Tag Assistant](https://tagassistant.google.com/) tool to check if your gtag is set up correctly! + +::: + +:::warning production only + +This plugin is always inactive in development and **only active in production** to avoid polluting the analytics statistics. + +::: + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-google-gtag +``` + +:::tip + +If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency. + +You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic). + +::: + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `trackingID` | <code>string \| string[]</code> | **Required** | The tracking ID of your gtag service. It is possible to provide multiple ids. | +| `anonymizeIP` | `boolean` | `false` | Whether the IP should be anonymized when sending requests. | + +```mdx-code-block +</APITable> +``` + +### Example configuration {#ex-config} + +You can configure this plugin through preset options or plugin options. + +:::tip + +Most Docusaurus users configure this plugin through the preset options. + +::: + +```js config-tabs +// Preset Options: gtag +// Plugin Options: @docusaurus/plugin-google-gtag + +const config = { + trackingID: 'G-999X9XX9XX', + anonymizeIP: true, +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-google-tag-manager.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-google-tag-manager.mdx new file mode 100644 index 0000000000..e444a53877 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-google-tag-manager.mdx @@ -0,0 +1,71 @@ +--- +sidebar_position: 8 +slug: /api/plugins/@docusaurus/plugin-google-tag-manager +--- + +# 📦 plugin-google-tag-manager + +import APITable from '@site/src/components/APITable'; + +A plugin for adding [Google Tag Manager (gtm.js)](https://developers.google.com/tag-platform/tag-manager) to a Docusaurus site. Use this plugin in conjunction with the standard [gtag plugin](./plugin-google-gtag.mdx) for in-depth analysis of how users are using your site. + +:::tip + +You can use [Google's Tag Assistant](https://tagassistant.google.com/) tool to check if tag manager is set up correctly! + +::: + +:::warning production only + +This plugin is always inactive in development and **only active in production** to avoid polluting the analytics statistics. + +::: + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-google-tag-manager +``` + +:::tip + +If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency. + +You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic). + +::: + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `containerId` | `string` | **Required** | Your Tag Manager container Id (usually starts with `GTM-`). | + +```mdx-code-block +</APITable> +``` + +### Example configuration {#ex-config} + +You can configure this plugin through preset options or plugin options. + +:::tip + +Most Docusaurus users configure this plugin through the preset options. + +::: + +```js config-tabs +// Preset Options: googleTagManager +// Plugin Options: @docusaurus/plugin-google-tag-manager + +const config = { + containerId: 'GTM-12345', +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-ideal-image.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-ideal-image.mdx new file mode 100644 index 0000000000..c6793466db --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-ideal-image.mdx @@ -0,0 +1,106 @@ +--- +sidebar_position: 8 +slug: /api/plugins/@docusaurus/plugin-ideal-image +--- + +# 📦 plugin-ideal-image + +import APITable from '@site/src/components/APITable'; + +Docusaurus Plugin to generate an almost ideal image (responsive, lazy-loading, and low quality placeholder). + +:::info + +By default, the plugin is **inactive in development** so you could always view full-scale images. If you want to debug the ideal image behavior, you could set the [`disableInDev`](#disableInDev) option to `false`. + +::: + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-ideal-image +``` + +## Usage {#usage} + +This plugin supports the PNG and JPG formats only. + +```jsx +import Image from '@theme/IdealImage'; +import thumbnail from './path/to/img.png'; + +// your React code +<Image img={thumbnail} /> + +// or +<Image img={require('./path/to/img.png')} /> +``` + +:::warning + +This plugin registers a [Webpack loader](https://webpack.js.org/loaders/) that changes the type of imported/require images: + +- Before: `string` +- After: `{preSrc: string, src: import("@theme/IdealImage").SrcImage}` + +::: + +:::warning For pnpm users + +Starting with [pnpm 10](https://github.com/pnpm/pnpm/releases/tag/v10.0.0), running `pnpm install` won't run dependency install scripts by default. You'll need additional pnpm configuration ([issue](https://github.com/lovell/sharp/issues/4343)) for our `sharp` image resizing dependency to install correctly, such as: + +```json title="package.json" +{ + "pnpm": { + "onlyBuiltDependencies": ["fsevents"] + } +} +``` + +::: + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Option | Type | Default | Description | +| --- | --- | --- | --- | +| `name` | `string` | `ideal-img/[name].[hash:hex:7].[width].[ext]` | Filename template for output files. | +| `sizes` | `number[]` | _original size_ | Specify all widths you want to use. If a specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up). | +| `size` | `number` | _original size_ | Specify one width you want to use; if the specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up) | +| `min` | `number` | | As an alternative to manually specifying `sizes`, you can specify `min`, `max` and `steps`, and the sizes will be generated for you. | +| `max` | `number` | | See `min` above | +| `steps` | `number` | `4` | Configure the number of images generated between `min` and `max` (inclusive) | +| `quality` | `number` | `85` | JPEG compression quality | +| `disableInDev` | `boolean` | `true` | You can test ideal image behavior in dev mode by setting this to `false`. **Tip**: use [network throttling](https://www.browserstack.com/guide/how-to-perform-network-throttling-in-chrome) in your browser to simulate slow networks. | + +```mdx-code-block +</APITable> +``` + +### Example configuration {#ex-config} + +Here's an example configuration: + +```js title="docusaurus.config.js" +export default { + plugins: [ + [ + '@docusaurus/plugin-ideal-image', + // highlight-start + { + quality: 70, + max: 1030, // max resized image's size. + min: 640, // min resized image's size. if original is lower, use that size. + steps: 2, // the max number of images generated between min and max (inclusive) + disableInDev: false, + }, + // highlight-end + ], + ], +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-pwa.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-pwa.mdx new file mode 100644 index 0000000000..df16a0c864 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-pwa.mdx @@ -0,0 +1,303 @@ +--- +sidebar_position: 9 +slug: /api/plugins/@docusaurus/plugin-pwa +--- + +# 📦 plugin-pwa + +Docusaurus Plugin to add PWA support using [Workbox](https://developers.google.com/web/tools/workbox). This plugin generates a [Service Worker](https://developers.google.com/web/fundamentals/primers/service-workers) in production build only, and allows you to create fully PWA-compliant documentation site with offline and installation support. + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-pwa +``` + +## Configuration {#configuration} + +Create a [PWA manifest](https://web.dev/add-manifest/) at `./static/manifest.json`. + +Modify `docusaurus.config.js` with a minimal PWA config, like: + +```js title="docusaurus.config.js" +export default { + plugins: [ + [ + '@docusaurus/plugin-pwa', + { + debug: true, + offlineModeActivationStrategies: [ + 'appInstalled', + 'standalone', + 'queryString', + ], + pwaHead: [ + { + tagName: 'link', + rel: 'icon', + href: '/img/docusaurus.png', + }, + { + tagName: 'link', + rel: 'manifest', + href: '/manifest.json', // your PWA manifest + }, + { + tagName: 'meta', + name: 'theme-color', + content: 'rgb(37, 194, 160)', + }, + ], + }, + ], + ], +}; +``` + +## Progressive Web App {#progressive-web-app} + +Having a service worker installed is not enough to make your application a PWA. You'll need to at least include a [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) and have the correct tags in `<head>` ([Options > pwaHead](#pwahead)). + +After deployment, you can use [Lighthouse](https://developers.google.com/web/tools/lighthouse) to run an audit on your site. + +For a more exhaustive list of what it takes for your site to be a PWA, refer to the [PWA Checklist](https://developers.google.com/web/progressive-web-apps/checklist) + +## App installation support {#app-installation-support} + +If your browser supports it, you should be able to install a Docusaurus site as an app. + +![A screen recording of the installation process. A button appears in the address bar of the browser, which displays a dialog asking "install this application?" when clicked. After clicking the "Install" button, a new application is opened in the operating system, opening to the Docusaurus homepage.](/img/pwa_install.gif) + +:::note + +App installation requires the HTTPS protocol and a valid manifest. + +::: + +## Offline mode (precaching) {#offline-mode-precaching} + +We enable users to browse a Docusaurus site offline, by using service-worker precaching. + +The [workbox-precaching](https://developers.google.com/web/tools/workbox/modules/workbox-precaching) page explains the idea: + +> One feature of service workers is the ability to save a set of files to the cache when the service worker is installing. This is often referred to as "precaching", since you are caching content ahead of the service worker being used. +> +> The main reason for doing this is that it gives developers control over the cache, meaning they can determine when and how long a file is cached as well as serve it to the browser without going to the network, meaning it can be used to create web apps that work offline. +> +> Workbox takes a lot of the heavy lifting out of precaching by simplifying the API and ensuring assets are downloaded efficiently. + +By default, offline mode is enabled when the site is installed as an app. See the `offlineModeActivationStrategies` option for details. + +After the site has been precached, the service worker will serve cached responses for later visits. When a new build is deployed along with a new service worker, the new one will begin installing and eventually move to a waiting state. During this waiting state, a reload popup will show and ask the user to reload the page for new content. Until the user either clears the application cache or clicks the `reload` button on the popup, the service worker will continue serving the old content. + +:::warning + +Offline mode / precaching requires downloading all the static assets of the site ahead of time, and can consume unnecessary bandwidth. It may not be a good idea to activate it for all kind of sites. + +::: + +## Options {#options} + +### `debug` {#debug} + +- Type: `boolean` +- Default: `false` + +Turn debug mode on: + +- Workbox logs +- Additional Docusaurus logs +- Unoptimized SW file output +- Source maps + +### `offlineModeActivationStrategies` {#offlinemodeactivationstrategies} + +- Type: `('appInstalled' | 'mobile' | 'saveData'| 'queryString' | 'always')[]` +- Default: `['appInstalled', 'queryString', 'standalone']` + +Strategies used to turn the offline mode on: + +- `appInstalled`: activates for users having installed the site as an app (not 100% reliable) +- `standalone`: activates for users running the app as standalone (often the case once a PWA is installed) +- `queryString`: activates if queryString contains `offlineMode=true` (convenient for PWA debugging) +- `mobile`: activates for mobile users (`width <= 996px`) +- `saveData`: activates for users with `navigator.connection.saveData === true` +- `always`: activates for all users + +:::warning + +Use this carefully: some users may not like to be forced to use the offline mode. + +::: + +:::danger + +It is not possible to detect if a page is rendered as a PWA in a reliable manner. + +The `appinstalled` event has been [removed from the specification](https://github.com/w3c/manifest/pull/836), and the [`navigator.getInstalledRelatedApps()`](https://web.dev/get-installed-related-apps/) API is only supported in recent Chrome versions and require `related_applications` declared in the manifest. + +The [`standalone` strategy](https://petelepage.com/blog/2019/07/is-my-pwa-installed/) is a nice fallback to activate the offline mode (at least when running the installed app). + +::: + +### `injectManifestConfig` {#injectmanifestconfig} + +[Workbox options](https://developer.chrome.com/docs/workbox/reference/workbox-build/#type-InjectManifestOptions) to pass to `workbox.injectManifest()`. This gives you control over which assets will be precached, and be available offline. + +- Type: `InjectManifestOptions` +- Default: `{}` + +```js title="docusaurus.config.js" +export default { + plugins: [ + [ + '@docusaurus/plugin-pwa', + { + injectManifestConfig: { + manifestTransforms: [ + //... + ], + modifyURLPrefix: { + //... + }, + // We already add regular static assets (HTML, images...) to be available offline + // You can add more files according to your needs + globPatterns: ['**/*.{pdf,docx,xlsx}'], + // ... + }, + }, + ], + ], +}; +``` + +### `pwaHead` {#pwahead} + +- Type: `({ tagName: string; [attributeName: string]: string })[]` +- Default: `[]` + +Array of objects containing `tagName` and key-value pairs for attributes to inject into the `<head>` tag. Technically you can inject any head tag through this, but it's ideally used for tags to make your site PWA compliant. Here's a list of tag to make your app fully compliant: + +```js +export default { + plugins: [ + [ + '@docusaurus/plugin-pwa', + { + pwaHead: [ + { + tagName: 'link', + rel: 'icon', + href: '/img/docusaurus.png', + }, + { + tagName: 'link', + rel: 'manifest', + href: '/manifest.json', + }, + { + tagName: 'meta', + name: 'theme-color', + content: 'rgb(37, 194, 160)', + }, + { + tagName: 'meta', + name: 'apple-mobile-web-app-capable', + content: 'yes', + }, + { + tagName: 'meta', + name: 'apple-mobile-web-app-status-bar-style', + content: '#000', + }, + { + tagName: 'link', + rel: 'apple-touch-icon', + href: '/img/docusaurus.png', + }, + { + tagName: 'link', + rel: 'mask-icon', + href: '/img/docusaurus.svg', + color: 'rgb(37, 194, 160)', + }, + { + tagName: 'meta', + name: 'msapplication-TileImage', + content: '/img/docusaurus.png', + }, + { + tagName: 'meta', + name: 'msapplication-TileColor', + content: '#000', + }, + ], + }, + ], + ], +}; +``` + +### `swCustom` {#swcustom} + +- Type: `string | undefined` +- Default: `undefined` + +Useful for additional Workbox rules. You can do whatever a service worker can do here, and use the full power of workbox libraries. The code is transpiled, so you can use modern ES6+ syntax here. + +For example, to cache files from external routes: + +```js +import {registerRoute} from 'workbox-routing'; +import {StaleWhileRevalidate} from 'workbox-strategies'; + +// default fn export receiving some useful params +export default function swCustom(params) { + const { + debug, // :boolean + offlineMode, // :boolean + } = params; + + // Cache responses from external resources + registerRoute((context) => { + return [ + /graph\.facebook\.com\/.*\/picture/, + /netlify\.com\/img/, + /avatars1\.githubusercontent/, + ].some((regex) => context.url.href.match(regex)); + }, new StaleWhileRevalidate()); +} +``` + +The module should have a `default` function export, and receives some params. + +### `swRegister` {#swregister} + +- Type: `string | false` +- Default: `'docusaurus-plugin-pwa/src/registerSW.js'` + +Adds an entry before the Docusaurus app so that registration can happen before the app runs. The default `registerSW.js` file is enough for simple registration. + +Passing `false` will disable registration entirely. + +## Manifest example {#manifest-example} + +The Docusaurus site manifest can serve as an inspiration: + +```mdx-code-block +import CodeBlock from '@theme/CodeBlock'; + +<CodeBlock className="language-json"> + {JSON.stringify(require('@site/static/manifest.json'),null,2)} +</CodeBlock> +``` + +## Customizing reload popup {#customizing-reload-popup} + +The `@theme/PwaReloadPopup` component is rendered when a new service worker is waiting to be installed, and we suggest a reload to the user. You can [swizzle](../../swizzling.mdx) this component and implement your own UI. It will receive an `onReload` callback as props, which should be called when the `reload` button is clicked. This will tell the service worker to install the waiting service worker and reload the page. + +The default theme includes an implementation for the reload popup and uses [Infima Alerts](https://infima.dev/docs/components/alert). + +![A screen recording of the reload process. An alert box shows in the bottom right of the window, saying "New content available". After clicking the "Refresh" button, the page's main heading changes from "Introduction" to "PWA :))".](/img/pwa_reload.gif) + +Your component can render `null`, but this is not recommended: users won't have a way to get up-to-date content. diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-rsdoctor.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-rsdoctor.mdx new file mode 100644 index 0000000000..100d714893 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-rsdoctor.mdx @@ -0,0 +1,57 @@ +--- +sidebar_position: 7 +slug: /api/plugins/@docusaurus/plugin-rsdoctor +--- + +# 📦 plugin-rsdoctor + +import APITable from '@site/src/components/APITable'; + +A [Rsdoctor](https://rsdoctor.dev/) plugin can help you troubleshoot the bundling phase of your Docusaurus site, supporting both Webpack and Rspack. + +:::tip + +Use it to figure out which plugin or loader is slowing down the bundler, and focus your efforts on optimizing the bottleneck. + +::: + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-rsdoctor +``` + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `rsdoctorOptions` | `object` | `{}` | The [Rsdoctor bundler plugin options](https://rsdoctor.dev/config/options/options), forwarded as is | + +```mdx-code-block +</APITable> +``` + +### Example configuration {#ex-config} + +You can configure this plugin through plugin options. + +```js title="docusaurus.config.js" +export default { + plugins: [ + [ + 'rsdoctor', + { + rsdoctorOptions: { + mode: 'lite', + }, + }, + ], + ], +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-sitemap.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-sitemap.mdx new file mode 100644 index 0000000000..75ca74ef8b --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-sitemap.mdx @@ -0,0 +1,110 @@ +--- +sidebar_position: 10 +slug: /api/plugins/@docusaurus/plugin-sitemap +--- + +# 📦 plugin-sitemap + +import APITable from '@site/src/components/APITable'; + +This plugin creates sitemaps for your site so that search engine crawlers can crawl your site more accurately. + +:::warning production only + +This plugin is always inactive in development and **only active in production** because it works on the build output. + +::: + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-sitemap +``` + +:::tip + +If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency. + +You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic). + +::: + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `lastmod` | `'date' \| 'datetime' \| null` | `null` | `date` is YYYY-MM-DD. `datetime` is a ISO 8601 datetime. `null` is disabled. See [sitemap docs](https://www.sitemaps.org/protocol.html#xmlTagDefinitions). | +| `changefreq` | `string \| null` | `'weekly'` | See [sitemap docs](https://www.sitemaps.org/protocol.html#xmlTagDefinitions) | +| `priority` | `number \| null` | `0.5` | See [sitemap docs](https://www.sitemaps.org/protocol.html#xmlTagDefinitions) | +| `ignorePatterns` | `string[]` | `[]` | A list of glob patterns; matching route paths will be filtered from the sitemap. Note that you may need to include the base URL in here. | +| `filename` | `string` | `sitemap.xml` | The path to the created sitemap file, relative to the output directory. Useful if you have two plugin instances outputting two files. | +| `createSitemapItems` | <code>[CreateSitemapItemsFn](#CreateSitemapItemsFn) \| undefined</code> | `undefined` | An optional function which can be used to transform and / or filter the items in the sitemap. | + +```mdx-code-block +</APITable> +``` + +### Types {#types} + +#### `CreateSitemapItemsFn` {#CreateSitemapItemsFn} + +```ts +type CreateSitemapItemsFn = (params: { + siteConfig: DocusaurusConfig; + routes: RouteConfig[]; + defaultCreateSitemapItems: CreateSitemapItemsFn; +}) => Promise<SitemapItem[]>; +``` + +:::info + +This plugin also respects some site config: + +- [`noIndex`](../docusaurus.config.js.mdx#noIndex): results in no sitemap generated +- [`trailingSlash`](../docusaurus.config.js.mdx#trailingSlash): determines if the URLs in the sitemap have trailing slashes + +::: + +:::note About `lastmod` + +The `lastmod` option will only output a sitemap `<lastmod>` tag if plugins provide [route metadata](../plugin-methods/lifecycle-apis.mdx#addRoute) attributes `sourceFilePath` and/or `lastUpdatedAt`. + +All the official content plugins provide the metadata for routes backed by a content file (Markdown, MDX or React page components), but it is possible third-party plugin authors do not provide this information, and the plugin will not be able to output a `<lastmod>` tag for their routes. + +::: + +### Example configuration {#ex-config} + +You can configure this plugin through preset options or plugin options. + +:::tip + +Most Docusaurus users configure this plugin through the preset options. + +::: + +```js config-tabs +// Preset Options: sitemap +// Plugin Options: @docusaurus/plugin-sitemap + +const config = { + lastmod: 'date', + changefreq: 'weekly', + priority: 0.5, + ignorePatterns: ['/tags/**'], + filename: 'sitemap.xml', + createSitemapItems: async (params) => { + const {defaultCreateSitemapItems, ...rest} = params; + const items = await defaultCreateSitemapItems(rest); + return items.filter((item) => !item.url.includes('/page/')); + }, +}; +``` + +You can find your sitemap at `/sitemap.xml`. diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-svgr.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-svgr.mdx new file mode 100644 index 0000000000..bd5bef1eab --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-svgr.mdx @@ -0,0 +1,55 @@ +--- +sidebar_position: 7 +slug: /api/plugins/@docusaurus/plugin-svgr +--- + +# 📦 plugin-svgr + +import APITable from '@site/src/components/APITable'; + +An [SVGR](https://react-svgr.com/) plugin to transform SVG files into React components automatically at build time. + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-svgr +``` + +:::tip + +If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency. + +You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic). + +::: + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `svgrConfig` | `object` | `{}` | The [SVGR config options](https://react-svgr.com/docs/options/), forwarded as is | + +```mdx-code-block +</APITable> +``` + +### Example configuration {#ex-config} + +You can configure this plugin through plugin options. + +```js config-tabs +// Preset Options: svgr +// Plugin Options: @docusaurus/plugin-svgr + +const config = { + svgrConfig: { + /* SVGR config */ + }, +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/plugins/plugin-vercel-analytics.mdx b/website/versioned_docs/version-3.9.0/api/plugins/plugin-vercel-analytics.mdx new file mode 100644 index 0000000000..4c1e966843 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/plugins/plugin-vercel-analytics.mdx @@ -0,0 +1,57 @@ +--- +sidebar_position: 11 +slug: /api/plugins/@docusaurus/plugin-vercel-analytics +--- + +# 📦 plugin-vercel-analytics + +import APITable from '@site/src/components/APITable'; + +[Vercel Analytics](https://vercel.com/docs/analytics) provides comprehensive insights into your website's visitors, tracking top pages, referrers, and demographics like location, operating systems, and browser info. + +:::warning production only + +This plugin is always inactive in development and **only active in production** (`docusaurus build`) to avoid polluting the analytics statistics. + +::: + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-vercel-analytics +``` + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `mode` | `string` | `'auto'` | Override the automatic environment detection. Read the [official docs](https://vercel.com/docs/analytics/package#mode) for details. | +| `debug` | `boolean` | `undefined` | Enable browser console logging of analytics events. Read the [official docs](https://vercel.com/docs/analytics/package#debug) for details. | + +```mdx-code-block +</APITable> +``` + +### Example configuration {#ex-config} + +You can configure this plugin through plugin options. + +```js title="docusaurus.config.js" +export default { + plugins: [ + [ + 'vercel-analytics', + { + debug: true, + mode: 'auto', + }, + ], + ], +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/themes/_category_.yml b/website/versioned_docs/version-3.9.0/api/themes/_category_.yml new file mode 100644 index 0000000000..a0ceda5d59 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/themes/_category_.yml @@ -0,0 +1,5 @@ +label: Themes +position: 3 +link: + type: doc + id: themes-overview # Dogfood using a "local id" diff --git a/website/versioned_docs/version-3.9.0/api/themes/overview.mdx b/website/versioned_docs/version-3.9.0/api/themes/overview.mdx new file mode 100644 index 0000000000..98084d7418 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/themes/overview.mdx @@ -0,0 +1,34 @@ +--- +sidebar_position: 0 +id: themes-overview +sidebar_label: Themes overview +slug: /api/themes +--- + +# Docusaurus themes + +We provide official Docusaurus themes. + +## Main themes {#main-themes} + +The main themes implement the user interface for the [docs](../plugins/plugin-content-docs.mdx), [blog](../plugins/plugin-content-blog.mdx) and [pages](../plugins/plugin-content-pages.mdx) plugins. + +- [@docusaurus/theme-classic](./theme-classic.mdx) +- 🚧 other themes are planned + +:::warning + +The goal is to have all themes share the exact same features, user-experience and configuration. + +Only the UI design and underlying styling framework should change, and you should be able to change theme easily. + +We are not there yet: only the classic theme is production ready. + +::: + +## Enhancement themes {#enhancement-themes} + +These themes will enhance the existing main themes with additional user-interface related features. + +- [@docusaurus/theme-live-codeblock](./theme-live-codeblock.mdx) +- [@docusaurus/theme-search-algolia](./theme-search-algolia.mdx) diff --git a/website/versioned_docs/version-3.9.0/api/themes/theme-classic.mdx b/website/versioned_docs/version-3.9.0/api/themes/theme-classic.mdx new file mode 100644 index 0000000000..5073013923 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/themes/theme-classic.mdx @@ -0,0 +1,63 @@ +--- +sidebar_position: 2 +slug: /api/themes/@docusaurus/theme-classic +--- + +# 📦 theme-classic + +import APITable from '@site/src/components/APITable'; + +The classic theme for Docusaurus. + +You can refer to the [theme configuration page](theme-configuration.mdx) for more details on the configuration. + +```bash npm2yarn +npm install --save @docusaurus/theme-classic +``` + +:::tip + +If you have installed `@docusaurus/preset-classic`, you don't need to install it as a dependency. + +::: + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Option | Type | Default | Description | +| --- | --- | --- | --- | +| `customCss` | <code>string[] \| string</code> | `[]` | Stylesheets to be imported globally as [client modules](../../advanced/client.mdx#client-modules). Relative paths are resolved against the site directory. | + +```mdx-code-block +</APITable> +``` + +:::note + +Most configuration for the theme is done in `themeConfig`, which can be found in [theme configuration](./theme-configuration.mdx). + +::: + +### Example configuration {#ex-config} + +You can configure this theme through preset options or plugin options. + +:::tip + +Most Docusaurus users configure this plugin through the preset options. + +::: + +```js config-tabs +// Preset Options: theme +// Plugin Options: @docusaurus/theme-classic + +const config = { + customCss: './src/css/custom.css', +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/themes/theme-configuration.mdx b/website/versioned_docs/version-3.9.0/api/themes/theme-configuration.mdx new file mode 100644 index 0000000000..cca32b058d --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/themes/theme-configuration.mdx @@ -0,0 +1,1239 @@ +--- +sidebar_position: 1 +sidebar_label: Configuration +slug: /api/themes/configuration +toc_max_heading_level: 4 +--- + +# Theme configuration + +import APITable from '@site/src/components/APITable'; + +This configuration applies to all [main themes](./overview.mdx). + +## Common {#common} + +### Color mode {#color-mode---dark-mode} + +The classic theme provides by default light and dark mode support, with a navbar switch for the user. + +It is possible to customize the color mode support within the `colorMode` object. + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `defaultMode` | <code>'light' \| 'dark'</code> | `'light'` | The color mode when user first visits the site. | +| `disableSwitch` | `boolean` | `false` | Hides the switch in the navbar. Useful if you want to support a single color mode. | +| `respectPrefersColorScheme` | `boolean` | `false` | Whether to use the `prefers-color-scheme` media-query, using user system preferences, instead of the hardcoded `defaultMode`. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + // highlight-start + colorMode: { + defaultMode: 'light', + disableSwitch: false, + respectPrefersColorScheme: false, + }, + // highlight-end + }, +}; +``` + +:::warning + +With `respectPrefersColorScheme: true`, the `defaultMode` is overridden by user system preferences. + +If you only want to support one color mode, you likely want to ignore user system preferences. + +::: + +### Meta image {#meta-image} + +You can configure a default image that will be used for your meta tag, in particular `og:image` and `twitter:image`. + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `image` | `string` | `undefined` | The meta image URL for the site. Relative to your site's "static" directory. Cannot be SVGs. Can be external URLs too. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + // highlight-next-line + image: 'img/docusaurus.png', + }, +}; +``` + +### Metadata {#metadata} + +You can configure additional HTML metadata (and override existing ones). + +Accepted fields: + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `metadata` | `Metadata[]` | `[]` | Any field will be directly passed to the `<meta />` tag. Possible fields include `id`, `name`, `property`, `content`, `itemprop`, etc. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + // highlight-next-line + metadata: [{name: 'twitter:card', content: 'summary'}], + }, +}; +``` + +### Announcement bar {#announcement-bar} + +Sometimes you want to announce something in your website. Just for such a case, you can add an announcement bar. This is a non-fixed and optionally dismissible panel above the navbar. All configuration are in the `announcementBar` object. + +Accepted fields: + +```mdx-code-block +<APITable name="announcement-bar"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `id` | `string` | `'announcement-bar'` | Any value that will identify this message. | +| `content` | `string` | `''` | The text content of the announcement. HTML will be interpolated. | +| `backgroundColor` | `string` | `'#fff'` | Background color of the entire bar. | +| `textColor` | `string` | `'#000'` | Announcement text color. | +| `isCloseable` | `boolean` | `true` | Whether this announcement can be dismissed with a '×' button. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + // highlight-start + announcementBar: { + id: 'support_us', + content: + 'We are looking to revamp our docs, please fill <a target="_blank" rel="noopener noreferrer" href="#">this survey</a>', + backgroundColor: '#fafbfc', + textColor: '#091E42', + isCloseable: false, + }, + // highlight-end + }, +}; +``` + +## Plugins + +Our [main themes](./overview.mdx) offer additional theme configuration options for Docusaurus core content plugins. + +### Docs + +```mdx-code-block +<APITable name="navbar-overview"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `versionPersistence` | `'localStorage' \| 'none'` | `undefined` | Defines the browser persistence of the preferred docs version. | +| `sidebar.hideable` | `boolean` | `false` | Show a hide button at the bottom of the sidebar. | +| `sidebar.autoCollapseCategories` | `boolean` | `false` | Automatically collapse all sibling categories of the one you navigate to. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + docs: { + // highlight-start + versionPersistence: 'localStorage', + sidebar: { + hideable: false, + autoCollapseCategories: false, + }, + // highlight-end + }, + }, +}; +``` + +### Blog + +```mdx-code-block +<APITable name="navbar-overview"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `sidebar.groupByYear` | `boolean` | `true` | Group sidebar blog posts by years. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + blog: { + // highlight-start + sidebar: { + groupByYear: true, + }, + // highlight-end + }, + }, +}; +``` + +## Navbar {#navbar} + +Accepted fields: + +```mdx-code-block +<APITable name="navbar-overview"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `title` | `string` | `undefined` | Title for the navbar. | +| `logo` | _See below_ | `undefined` | Customization of the logo object. | +| `items` | `NavbarItem[]` | `[]` | A list of navbar items. See specification below. | +| `hideOnScroll` | `boolean` | `false` | Whether the navbar is hidden when the user scrolls down. | +| `style` | <code>'primary' \| 'dark'</code> | Same as theme | Sets the navbar style, ignoring the dark/light theme. | + +```mdx-code-block +</APITable> +``` + +### Navbar logo {#navbar-logo} + +The logo can be placed in [static folder](static-assets.mdx). Logo URL is set to base URL of your site by default. Although you can specify your own URL for the logo, if it is an external link, it will open in a new tab. In addition, you can override a value for the target attribute of logo link, it can come in handy if you are hosting docs website in a subdirectory of your main website, and in which case you probably do not need a link in the logo to the main website will open in a new tab. + +To improve dark mode support, you can also set a different logo for this mode. + +Accepted fields: + +```mdx-code-block +<APITable name="navbar-logo"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `alt` | `string` | `undefined` | Alt tag for the logo image. | +| `src` | `string` | **Required** | URL to the logo image. Base URL is appended by default. | +| `srcDark` | `string` | `logo.src` | An alternative image URL to use in dark mode. | +| `href` | `string` | `siteConfig.baseUrl` | Link to navigate to when the logo is clicked. | +| `width` | <code>string \| number</code> | `undefined` | Specifies the `width` attribute. | +| `height` | <code>string \| number</code> | `undefined` | Specifies the `height` attribute. | +| `target` | `string` | Calculated based on `href` (external links will open in a new tab, all others in the current one). | The `target` attribute of the link; controls whether the link is opened in a new tab, the current one, or otherwise. | +| `className` | `string` | `undefined` | CSS class applied to the image. | +| `style` | `object` | `undefined` | CSS inline style object. React/JSX flavor, using camelCase properties. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + title: 'Site Title', + // highlight-start + logo: { + alt: 'Site Logo', + src: 'img/logo.svg', + srcDark: 'img/logo_dark.svg', + href: 'https://docusaurus.io/', + target: '_self', + width: 32, + height: 32, + className: 'custom-navbar-logo-class', + style: {border: 'solid red'}, + }, + // highlight-end + }, + }, +}; +``` + +### Navbar items {#navbar-items} + +You can add items to the navbar via `themeConfig.navbar.items`. + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + // highlight-start + items: [ + { + type: 'doc', + position: 'left', + docId: 'introduction', + label: 'Docs', + }, + {to: 'blog', label: 'Blog', position: 'left'}, + { + type: 'docsVersionDropdown', + position: 'right', + }, + { + type: 'localeDropdown', + position: 'right', + }, + { + href: 'https://github.com/facebook/docusaurus', + position: 'right', + className: 'header-github-link', + 'aria-label': 'GitHub repository', + }, + ], + // highlight-end + }, + }, +}; +``` + +The items can have different behaviors based on the `type` field. The sections below will introduce you to all the types of navbar items available. + +#### Navbar link {#navbar-link} + +By default, Navbar items are regular links (internal or external). + +React Router should automatically apply active link styling to links, but you can use `activeBasePath` in edge cases. For cases in which a link should be active on several different paths (such as when you have multiple doc folders under the same sidebar), you can use `activeBaseRegex`. `activeBaseRegex` is a more flexible alternative to `activeBasePath` and takes precedence over it -- Docusaurus parses it into a regular expression that is tested against the current URL. + +Outbound (external) links automatically get `target="_blank" rel="noopener noreferrer"` attributes. + +Accepted fields: + +```mdx-code-block +<APITable name="navbar-link"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `type` | `'default'` | Optional | Sets the type of this item to a link. | +| `label` | `string` | **Required** | The name to be shown for this item. | +| `html` | `string` | Optional | Same as `label`, but renders pure HTML instead of text content. | +| `to` | `string` | **Required** | Client-side routing, used for navigating within the website. The baseUrl will be automatically prepended to this value. | +| `href` | `string` | **Required** | A full-page navigation, used for navigating outside of the website. **Only one of `to` or `href` should be used.** | +| `prependBaseUrlToHref` | `boolean` | `false` | Prepends the baseUrl to `href` values. | +| `position` | <code>'left' \| 'right'</code> | `'left'` | The side of the navbar this item should appear on. | +| `activeBasePath` | `string` | `to` / `href` | To apply the active class styling on all routes starting with this path. This usually isn't necessary. | +| `activeBaseRegex` | `string` | `undefined` | Alternative to `activeBasePath` if required. | +| `className` | `string` | `''` | Custom CSS class (for styling any item). | + +```mdx-code-block +</APITable> +``` + +:::note + +In addition to the fields above, you can specify other arbitrary attributes that can be applied to a HTML link. + +::: + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + items: [ + // highlight-start + { + to: 'docs/introduction', + // Only one of "to" or "href" should be used + // href: 'https://www.facebook.com', + label: 'Introduction', + // Only one of "label" or "html" should be used + // html: '<b>Introduction</b>' + position: 'left', + activeBaseRegex: 'docs/(next|v8)', + target: '_blank', + }, + // highlight-end + ], + }, + }, +}; +``` + +#### Navbar dropdown {#navbar-dropdown} + +Navbar items of the type `dropdown` has the additional `items` field, an inner array of navbar items. + +Navbar dropdown items only accept the following **"link-like" item types**: + +- [Navbar link](#navbar-link) +- [Navbar doc link](#navbar-doc-link) +- [Navbar docs version](#navbar-docs-version) +- [Navbar doc sidebar](#navbar-doc-sidebar) +- [Navbar with custom HTML](#navbar-with-custom-html) + +Note that the dropdown base item is a clickable link as well, so this item can receive any of the props of a [plain navbar link](#navbar-link). + +Accepted fields: + +```mdx-code-block +<APITable name="navbar-dropdown"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `type` | `'dropdown'` | Optional | Sets the type of this item to a dropdown. | +| `label` | `string` | **Required** | The name to be shown for this item. | +| `items` | <code>[LinkLikeItem](#navbar-dropdown)[]</code> | **Required** | The items to be contained in the dropdown. | +| `position` | <code>'left' \| 'right'</code> | `'left'` | The side of the navbar this item should appear on. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + items: [ + // highlight-start + { + type: 'dropdown', + label: 'Community', + position: 'left', + items: [ + { + label: 'Facebook', + href: 'https://www.facebook.com', + }, + { + type: 'doc', + label: 'Social', + docId: 'social', + }, + // ... more items + ], + }, + // highlight-end + ], + }, + }, +}; +``` + +#### Navbar doc link {#navbar-doc-link} + +If you want to link to a specific doc, this special navbar item type will render the link to the doc of the provided `docId`. It will get the class `navbar__link--active` as long as you browse a doc of the same sidebar. + +Accepted fields: + +```mdx-code-block +<APITable name="navbar-doc-link"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `type` | `'doc'` | **Required** | Sets the type of this item to a doc link. | +| `docId` | `string` | **Required** | The ID of the doc that this item links to. | +| `label` | `string` | `docId` | The name to be shown for this item. | +| `position` | <code>'left' \| 'right'</code> | `'left'` | The side of the navbar this item should appear on. | +| `docsPluginId` | `string` | `'default'` | The ID of the docs plugin that the doc belongs to. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + items: [ + // highlight-start + { + type: 'doc', + position: 'left', + docId: 'introduction', + label: 'Docs', + }, + // highlight-end + ], + }, + }, +}; +``` + +#### Navbar linked to a sidebar {#navbar-doc-sidebar} + +You can link a navbar item to the first document link (which can be a doc link or a generated category index) of a given sidebar without having to hardcode a doc ID. + +Accepted fields: + +```mdx-code-block +<APITable name="navbar-doc-sidebar"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `type` | `'docSidebar'` | **Required** | Sets the type of this navbar item to a sidebar's first document. | +| `sidebarId` | `string` | **Required** | The ID of the sidebar that this item is linked to. | +| `label` | `string` | First document link's sidebar label | The name to be shown for this item. | +| `position` | <code>'left' \| 'right'</code> | `'left'` | The side of the navbar this item should appear on. | +| `docsPluginId` | `string` | `'default'` | The ID of the docs plugin that the sidebar belongs to. | + +```mdx-code-block +</APITable> +``` + +:::tip + +Use this navbar item type if your sidebar is updated often and the order is not stable. + +::: + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + items: [ + // highlight-start + { + type: 'docSidebar', + position: 'left', + sidebarId: 'api', + label: 'API', + }, + // highlight-end + ], + }, + }, +}; +``` + +```js title="sidebars.js" +export default { + tutorial: [ + { + type: 'autogenerated', + dirName: 'guides', + }, + ], + api: [ + // highlight-next-line + 'cli', // The navbar item will be linking to this doc + 'docusaurus-core', + { + type: 'autogenerated', + dirName: 'api', + }, + ], +}; +``` + +#### Navbar docs version dropdown {#navbar-docs-version-dropdown} + +If you use docs with versioning, this special navbar item type that will render a dropdown with all your site's available versions. + +The user will be able to switch from one version to another, while staying on the same doc (as long as the doc ID is constant across versions). + +Accepted fields: + +```mdx-code-block +<APITable name="navbar-docs-version-dropdown"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `type` | `'docsVersionDropdown'` | **Required** | Sets the type of this item to a docs version dropdown. | +| `position` | <code>'left' \| 'right'</code> | `'left'` | The side of the navbar this item should appear on. | +| `dropdownItemsBefore` | <code>[LinkLikeItem](#navbar-dropdown)[]</code> | `[]` | Add additional dropdown items at the beginning of the dropdown. | +| `dropdownItemsAfter` | <code>[LinkLikeItem](#navbar-dropdown)[]</code> | `[]` | Add additional dropdown items at the end of the dropdown. | +| `docsPluginId` | `string` | `'default'` | The ID of the docs plugin that the doc versioning belongs to. | +| `dropdownActiveClassDisabled` | `boolean` | `false` | Do not add the link active class when browsing docs. | +| `versions` | `DropdownVersions` | `undefined` | Specify a custom list of versions to include in the dropdown. See [the versioning guide](../../guides/docs/versioning.mdx#docsVersionDropdown) for details. | + +```mdx-code-block +</APITable> +``` + +Types: + +```ts +type DropdownVersion = { + /** Allows you to provide a custom display label for each version. */ + label?: string; +}; + +type DropdownVersions = string[] | {[versionName: string]: DropdownVersion}; +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + items: [ + // highlight-start + { + type: 'docsVersionDropdown', + position: 'left', + dropdownItemsAfter: [{to: '/versions', label: 'All versions'}], + dropdownActiveClassDisabled: true, + }, + // highlight-end + ], + }, + }, +}; +``` + +#### Navbar docs version {#navbar-docs-version} + +If you use docs with versioning, this special navbar item type will link to the active/browsed version of your doc (depends on the current URL), and fallback to the latest version. + +Accepted fields: + +```mdx-code-block +<APITable name="navbar-docs-version"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `type` | `'docsVersion'` | **Required** | Sets the type of this item to a doc version link. | +| `label` | `string` | The active/latest version label. | The name to be shown for this item. | +| `to` | `string` | The active/latest version. | The internal link that this item points to. | +| `position` | <code>'left' \| 'right'</code> | `'left'` | The side of the navbar this item should appear on. | +| `docsPluginId` | `string` | `'default'` | The ID of the docs plugin that the doc versioning belongs to. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + items: [ + // highlight-start + { + type: 'docsVersion', + position: 'left', + to: '/path', + label: 'label', + }, + // highlight-end + ], + }, + }, +}; +``` + +#### Navbar locale dropdown {#navbar-locale-dropdown} + +If you use the [i18n feature](../../i18n/i18n-introduction.mdx), this special navbar item type will render a dropdown with all your site's available locales. + +The user will be able to switch from one locale to another, while staying on the same page. + +Accepted fields: + +```mdx-code-block +<APITable name="navbar-locale-dropdown"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `type` | `'localeDropdown'` | **Required** | Sets the type of this item to a locale dropdown. | +| `position` | <code>'left' \| 'right'</code> | `'left'` | The side of the navbar this item should appear on. | +| `dropdownItemsBefore` | <code>[LinkLikeItem](#navbar-dropdown)[]</code> | `[]` | Add additional dropdown items at the beginning of the dropdown. | +| `dropdownItemsAfter` | <code>[LinkLikeItem](#navbar-dropdown)[]</code> | `[]` | Add additional dropdown items at the end of the dropdown. | +| `queryString` | `string` | `undefined` | The query string to be appended to the URL. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + items: [ + // highlight-start + { + type: 'localeDropdown', + position: 'left', + dropdownItemsAfter: [ + { + to: 'https://my-site.com/help-us-translate', + label: 'Help us translate', + }, + ], + }, + // highlight-end + ], + }, + }, +}; +``` + +#### Navbar search {#navbar-search} + +If you use the [search](../../search.mdx), the search bar will be the rightmost element in the navbar. + +However, with this special navbar item type, you can change the default location. + +```mdx-code-block +<APITable name="navbar-search"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `type` | `'search'` | **Required** | Sets the type of this item to a search bar. | +| `position` | <code>'left' \| 'right'</code> | `'left'` | The side of the navbar this item should appear on. | +| `className` | `string` | / | Custom CSS class for this navbar item. | + +```mdx-code-block +</APITable> +``` + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + items: [ + // highlight-start + { + type: 'search', + position: 'right', + }, + // highlight-end + ], + }, + }, +}; +``` + +#### Navbar with custom HTML {#navbar-with-custom-html} + +You can also render your own HTML markup inside a navbar item using this navbar item type. + +```mdx-code-block +<APITable name="navbar-html"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `type` | `'html'` | **Required** | Sets the type of this item to a HTML element. | +| `position` | <code>'left' \| 'right'</code> | `'left'` | The side of the navbar this item should appear on. | +| `className` | `string` | `''` | Custom CSS class for this navbar item. | +| `value` | `string` | `''` | Custom HTML to be rendered inside this navbar item. | + +```mdx-code-block +</APITable> +``` + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + items: [ + // highlight-start + { + type: 'html', + position: 'right', + value: '<button>Give feedback</button>', + }, + // highlight-end + ], + }, + }, +}; +``` + +### Auto-hide sticky navbar {#auto-hide-sticky-navbar} + +You can enable this cool UI feature that automatically hides the navbar when a user starts scrolling down the page, and show it again when the user scrolls up. + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + // highlight-next-line + hideOnScroll: true, + }, + }, +}; +``` + +### Navbar style {#navbar-style} + +You can set the static Navbar style without disabling the theme switching ability. The selected style will always apply no matter which theme user have selected. + +Currently, there are two possible style options: `dark` and `primary` (based on the `--ifm-color-primary` color). You can see the styles preview in the [Infima documentation](https://infima.dev/docs/components/navbar/). + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + // highlight-next-line + style: 'primary', + }, + }, +}; +``` + +## CodeBlock {#codeblock} + +Docusaurus uses [Prism React Renderer](https://github.com/FormidableLabs/prism-react-renderer) to highlight code blocks. All configuration are in the `prism` object. + +Accepted fields: + +```mdx-code-block +<APITable name="codeblock"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `theme` | `PrismTheme` | `palenight` | The Prism theme to use for light-theme code blocks. | +| `darkTheme` | `PrismTheme` | `palenight` | The Prism theme to use for dark-theme code blocks. | +| `defaultLanguage` | `string` | `undefined` | The default language to use for code blocks not declaring any explicit language. | +| `magicComments` | `MagicCommentConfig[]` | _see below_ | The list of [magic comments](../../guides/markdown-features/markdown-features-code-blocks.mdx#custom-magic-comments). | + +```mdx-code-block +</APITable> +``` + +```ts +type MagicCommentConfig = { + className: string; + line?: string; + block?: {start: string; end: string}; +}; +``` + +```js +const defaultMagicComments = [ + { + className: 'theme-code-block-highlighted-line', + line: 'highlight-next-line', + block: {start: 'highlight-start', end: 'highlight-end'}, + }, +]; +``` + +### Theme {#theme} + +By default, we use [Palenight](https://github.com/FormidableLabs/prism-react-renderer/blob/master/packages/prism-react-renderer/src/themes/palenight.ts) as syntax highlighting theme. You can specify a custom theme from the [list of available themes](https://github.com/FormidableLabs/prism-react-renderer/tree/master/packages/prism-react-renderer/src/themes). You may also use a different syntax highlighting theme when the site is in dark mode. + +Example configuration: + +```js title="docusaurus.config.js" +import {themes as prismThemes} from 'prism-react-renderer'; + +export default { + themeConfig: { + prism: { + // highlight-start + theme: prismThemes.github, + darkTheme: prismThemes.dracula, + // highlight-end + }, + }, +}; +``` + +:::note + +If you use the line highlighting Markdown syntax, you might need to specify a different highlight background color for the dark mode syntax highlighting theme. Refer to the [docs for guidance](../../guides/markdown-features/markdown-features-code-blocks.mdx#line-highlighting). + +::: + +### Default language {#default-language} + +You can set a default language for code blocks if no language is added after the opening triple backticks (i.e. ```). Note that a valid [language name](https://prismjs.com/#supported-languages) must be passed. + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + prism: { + // highlight-next-line + defaultLanguage: 'javascript', + }, + }, +}; +``` + +## Footer {#footer-1} + +You can add logo and a copyright to the footer via `themeConfig.footer`. Logo can be placed in [static folder](static-assets.mdx). Logo URL works in the same way of the navbar logo. + +Accepted fields: + +```mdx-code-block +<APITable name="footer"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `logo` | `Logo` | `undefined` | Customization of the logo object. See [Navbar logo](#navbar-logo) for details. | +| `copyright` | `string` | `undefined` | The copyright message to be displayed at the bottom, also supports custom HTML. | +| `style` | <code>'dark' \| 'light'</code> | `'light'` | The color theme of the footer component. | +| `links` | <code>(Column \| FooterLink)[]</code> | `[]` | The link groups to be present. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + // highlight-start + footer: { + logo: { + alt: 'Meta Open Source Logo', + src: 'img/meta_oss_logo.png', + href: 'https://opensource.fb.com', + width: 160, + height: 51, + }, + copyright: `Copyright © ${new Date().getFullYear()} My Project, Inc. Built with Docusaurus.`, + }, + // highlight-end + }, +}; +``` + +### Footer Links {#footer-links} + +You can add links to the footer via `themeConfig.footer.links`. There are two types of footer configurations: **multi-column footers** and **simple footers**. + +Multi-column footer links have a `title` and a list of `FooterItem`s for each column. + +```mdx-code-block +<APITable name="footer-links"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `title` | `string` | `undefined` | Label of the section of these links. | +| `items` | `FooterItem[]` | `[]` | Links in this section. | + +```mdx-code-block +</APITable> +``` + +Accepted fields of each `FooterItem`: + +```mdx-code-block +<APITable name="footer-items"> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `label` | `string` | **Required** | Text to be displayed for this link. | +| `to` | `string` | **Required** | Client-side routing, used for navigating within the website. The baseUrl will be automatically prepended to this value. | +| `href` | `string` | **Required** | A full-page navigation, used for navigating outside of the website. **Only one of `to` or `href` should be used.** | +| `html` | `string` | `undefined` | Renders the HTML pass-through instead of a simple link. In case `html` is used, no other options should be provided. | + +```mdx-code-block +</APITable> +``` + +Example multi-column configuration: + +```js title="docusaurus.config.js" +export default { + footer: { + // highlight-start + links: [ + { + title: 'Docs', + items: [ + { + label: 'Style Guide', + to: 'docs/', + }, + { + label: 'Second Doc', + to: 'docs/doc2/', + }, + ], + }, + { + title: 'Community', + items: [ + { + label: 'Stack Overflow', + href: 'https://stackoverflow.com/questions/tagged/docusaurus', + }, + { + label: 'Discord', + href: 'https://discordapp.com/invite/docusaurus', + }, + { + label: 'X', + href: 'https://x.com/docusaurus', + }, + { + html: ` + <a href="https://www.netlify.com" target="_blank" rel="noreferrer noopener" aria-label="Deploys by Netlify"> + <img src="https://www.netlify.com/img/global/badges/netlify-color-accent.svg" alt="Deploys by Netlify" width="114" height="51" /> + </a> + `, + }, + ], + }, + ], + // highlight-end + }, +}; +``` + +A simple footer just has a list of `FooterItem`s displayed in a row. + +Example simple configuration: + +```js title="docusaurus.config.js" +export default { + footer: { + // highlight-start + links: [ + { + label: 'Stack Overflow', + href: 'https://stackoverflow.com/questions/tagged/docusaurus', + }, + { + label: 'Discord', + href: 'https://discordapp.com/invite/docusaurus', + }, + { + label: 'X', + href: 'https://x.com/docusaurus', + }, + { + html: ` + <a href="https://www.netlify.com" target="_blank" rel="noreferrer noopener" aria-label="Deploys by Netlify"> + <img src="https://www.netlify.com/img/global/badges/netlify-color-accent.svg" alt="Deploys by Netlify" width="114" height="51" /> + </a> + `, + }, + ], + // highlight-end + }, +}; +``` + +## Table of Contents {#table-of-contents} + +You can adjust the default table of contents via `themeConfig.tableOfContents`. + +```mdx-code-block +<APITable> +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `minHeadingLevel` | `number` | `2` | The minimum heading level shown in the table of contents. Must be between 2 and 6 and lower or equal to the max value. | +| `maxHeadingLevel` | `number` | `3` | Max heading level displayed in the TOC. Should be an integer between 2 and 6. | + +```mdx-code-block +</APITable> +``` + +Example configuration: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + // highlight-start + tableOfContents: { + minHeadingLevel: 2, + maxHeadingLevel: 5, + }, + // highlight-end + }, +}; +``` + +## Hooks {#hooks} + +### `useColorMode` {#use-color-mode} + +A React hook to access the color context. This context contains functions for selecting light/dark/system mode and exposes the current color mode and the choice from the user. The color mode values **should not be used for dynamic content rendering** (see below). + +Usage example: + +```jsx +// highlight-next-line +import {useColorMode} from '@docusaurus/theme-common'; + +const MyColorModeButton = () => { + // highlight-start + const { + colorMode, // the "effective" color mode, never null + colorModeChoice, // the color mode chosen by the user, can be null + setColorMode, // set the color mode chosen by the user + } = useColorMode(); + // highlight-end + + return ( + <button + onClick={() => { + const nextColorMode = colorModeChoice === 'dark' ? 'light' : 'dark'; + setColorMode(nextColorMode); + }}> + Toggle color mode + </button> + ); +}; +``` + +Attributes: + +- `colorMode: 'light' | 'dark'`: The effective color mode currently applied to the UI. It cannot be `null`. +- `colorModeChoice: 'light' | 'dark' | null`: The color mode explicitly chosen by the user. It can be `null` if user has not made any choice yet, or if they reset their choice to the system/default value. +- `setColorMode(colorModeChoice: 'light' | 'dark' | null, options: {persist: boolean}): void`: A function to call when the user explicitly chose a color mode. `null` permits to reset the choice to the system/default value. By default, the choice is persisted in `localStorage` and restored on page reload, but you can opt out with `{persist: false}`. + +:::warning + +Don't use `colorMode` and `colorModeChoice` while rendering React components. Doing so is likely to produce [FOUC](https://en.wikipedia.org/wiki/Flash_of_unstyled_content), layout shifts and [React hydration](https://18.react.dev/reference/react-dom/client/hydrateRoot) mismatches if you use them to render JSX content dynamically. + +However, these values are safe to use **after React hydration**, in `useEffect` and event listeners, like in the `MyColorModeButton` example above. + +If you need to render content dynamically depending on the current theme, the only way to avoid FOUC, layout shifts and hydration mismatch is to rely on CSS selectors to render content dynamically, based on the `html` data attributes that we set before the page displays anything: + +```html +<html data-theme="<light | dark>" data-theme-choice="<light | dark | system>"> + <!-- content --> +</html> +``` + +```css +[data-theme='light'] +[data-theme='dark'] + +[data-theme-choice='light'] +[data-theme-choice='dark'] +[data-theme-choice='system'] +``` + +<details> + <summary>Why are `colorMode` and `colorModeChoice` unsafe when rendering?</summary> + +To understand the problem, you need to understand how [React hydration](https://18.react.dev/reference/react-dom/client/hydrateRoot) works. + +During the static site generation phase, Docusaurus doesn't know what the user color mode choice is, and `useColorMode()` returns the following static values: + +- `colorMode = themeConfig.colorMode.defaultMode` +- `colorModeChoice = null` + +During the very first React client-side render (the hydration), React must produce the exact same HTML markup, and will also use these static values. + +The correct `colorMode` and `colorModeChoice` values will only be provided in the second React render. + +Typically, the following component will lead to **React hydration mismatches**. The label may switch from `light` to `dark` while React hydrates, leading to a confusing user experience. + +```jsx +import {useColorMode} from '@docusaurus/theme-common'; + +const DisplayCurrentColorMode = () => { + const {colorMode} = useColorMode(); + return <span>{colorMode}</span>; +}; +``` + +</details> + +::: + +:::note + +The component calling `useColorMode` must be a child of the `Layout` component. + +```jsx +function ExamplePage() { + return ( + <Layout> + <Example /> + </Layout> + ); +} +``` + +::: + +## i18n {#i18n} + +Read the [i18n introduction](../../i18n/i18n-introduction.mdx) first. + +### Translation files location {#translation-files-location} + +- **Base path**: `website/i18n/[locale]/docusaurus-theme-[themeName]` +- **Multi-instance path**: N/A +- **JSON files**: extracted with [`docusaurus write-translations`](../../cli.mdx#docusaurus-write-translations-sitedir) +- **Markdown files**: N/A + +### Example file-system structure {#example-file-system-structure} + +```bash +website/i18n/[locale]/docusaurus-theme-classic +│ +│ # translations for the theme +├── navbar.json +└── footer.json +``` diff --git a/website/versioned_docs/version-3.9.0/api/themes/theme-live-codeblock.mdx b/website/versioned_docs/version-3.9.0/api/themes/theme-live-codeblock.mdx new file mode 100644 index 0000000000..212c910b3e --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/themes/theme-live-codeblock.mdx @@ -0,0 +1,29 @@ +--- +sidebar_position: 3 +slug: /api/themes/@docusaurus/theme-live-codeblock +--- + +# 📦 theme-live-codeblock + +This theme provides a `@theme/CodeBlock` component that is powered by [react-live](https://commerce.nearform.com/open-source/react-live/). You can read more on [interactive code editor](../../guides/markdown-features/markdown-features-code-blocks.mdx#interactive-code-editor) documentation. + +```bash npm2yarn +npm install --save @docusaurus/theme-live-codeblock +``` + +### Configuration {#configuration} + +```js title="docusaurus.config.js" +export default { + plugins: ['@docusaurus/theme-live-codeblock'], + themeConfig: { + liveCodeBlock: { + /** + * The position of the live playground, above or under the editor + * Possible values: "top" | "bottom" + */ + playgroundPosition: 'bottom', + }, + }, +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/themes/theme-mermaid.mdx b/website/versioned_docs/version-3.9.0/api/themes/theme-mermaid.mdx new file mode 100644 index 0000000000..d9a2059535 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/themes/theme-mermaid.mdx @@ -0,0 +1,25 @@ +--- +sidebar_position: 5 +slug: /api/themes/@docusaurus/theme-mermaid +--- + +# 📦 theme-mermaid + +This theme provides a `@theme/Mermaid` component that is powered by [mermaid](https://mermaid-js.github.io/). You can read more on [diagrams](../../guides/markdown-features/markdown-features-diagrams.mdx) documentation. + +```bash npm2yarn +npm install --save @docusaurus/theme-mermaid +``` + +## Configuration {#configuration} + +```js title="docusaurus.config.js" +export default { + themes: ['@docusaurus/theme-mermaid'], + // In order for Mermaid code blocks in Markdown to work, + // you also need to enable the Remark plugin with this option + markdown: { + mermaid: true, + }, +}; +``` diff --git a/website/versioned_docs/version-3.9.0/api/themes/theme-search-algolia.mdx b/website/versioned_docs/version-3.9.0/api/themes/theme-search-algolia.mdx new file mode 100644 index 0000000000..f8aa09a99c --- /dev/null +++ b/website/versioned_docs/version-3.9.0/api/themes/theme-search-algolia.mdx @@ -0,0 +1,20 @@ +--- +sidebar_position: 4 +slug: /api/themes/@docusaurus/theme-search-algolia +--- + +# 📦 theme-search-algolia + +This theme provides a `@theme/SearchBar` component that integrates with Algolia DocSearch easily. Combined with `@docusaurus/theme-classic`, it provides a very easy search integration. You can read more on [search](../../search.mdx) documentation. + +```bash npm2yarn +npm install --save @docusaurus/theme-search-algolia +``` + +This theme also adds search page available at `/search` (as swizzlable `SearchPage` component) path with OpenSearch support. You can change this default path via `themeConfig.algolia.searchPagePath`. Use `false` to disable search page. + +:::tip + +If you have installed `@docusaurus/preset-classic`, you don't need to install it as a dependency. + +::: diff --git a/website/versioned_docs/version-3.9.0/assets/docusaurus-asset-example-banner.png b/website/versioned_docs/version-3.9.0/assets/docusaurus-asset-example-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..ebe95f5ec8388c2da311f5e568a4ae147c42ffc8 GIT binary patch literal 69264 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 U1P8z~^8f$<07*qoM6N<$g6C^Z00000 literal 0 HcmV?d00001 diff --git a/website/versioned_docs/version-3.9.0/assets/docusaurus-asset-example.docx b/website/versioned_docs/version-3.9.0/assets/docusaurus-asset-example.docx new file mode 100644 index 0000000000000000000000000000000000000000..3c51aea4e79742676624b15b6608cc59582308ef GIT binary patch literal 6114 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 Gf&T{x){!s( literal 0 HcmV?d00001 diff --git a/website/versioned_docs/version-3.9.0/assets/docusaurus-asset-example.xyz b/website/versioned_docs/version-3.9.0/assets/docusaurus-asset-example.xyz new file mode 100644 index 0000000000000000000000000000000000000000..188262276aa40805c9cce37260352a11d3b99403 GIT binary patch literal 125786 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 literal 0 HcmV?d00001 diff --git a/website/versioned_docs/version-3.9.0/blog.mdx b/website/versioned_docs/version-3.9.0/blog.mdx new file mode 100644 index 0000000000..92a9551150 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/blog.mdx @@ -0,0 +1,783 @@ +--- +description: Deploy a full-featured blog in no time with Docusaurus. +--- + +# Blog + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +The blog feature enables you to deploy a full-featured blog in no time. + +:::info + +Check the [Blog Plugin API Reference documentation](./api/plugins/plugin-content-blog.mdx) for an exhaustive list of options. + +::: + +## Initial setup {#initial-setup} + +To set up your site's blog, start by creating a `blog` directory. + +Then, add an item link to your blog within `docusaurus.config.js`: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + // ... + navbar: { + items: [ + // ... + // highlight-next-line + {to: 'blog', label: 'Blog', position: 'left'}, // or position: 'right' + ], + }, + }, +}; +``` + +## Adding posts {#adding-posts} + +To publish in the blog, create a Markdown file within the blog directory. + +For example, create a file at `website/blog/2019-09-05-hello-docusaurus.md`: + +```md title="website/blog/2019-09-05-hello-docusaurus.md" +--- +title: Welcome Docusaurus +description: This is my first post on Docusaurus. +slug: welcome-docusaurus-v2 +authors: + - name: Joel Marcey + title: Co-creator of Docusaurus 1 + url: https://github.com/JoelMarcey + image_url: https://github.com/JoelMarcey.png + socials: + x: joelmarcey + github: JoelMarcey + - name: Sébastien Lorber + title: Docusaurus maintainer + url: https://sebastienlorber.com + image_url: https://github.com/slorber.png + socials: + x: sebastienlorber + github: slorber + email: seb@example.com +tags: [hello, docusaurus-v2] +image: https://i.imgur.com/mErPwqL.png +hide_table_of_contents: false +--- + +Welcome to this blog. This blog is created with [**Docusaurus**](https://docusaurus.io/). + +<!-- truncate --> + +This is my first post on Docusaurus. + +A whole bunch of exploration to follow. +``` + +The [front matter](./guides/markdown-features/markdown-features-intro.mdx#front-matter) is useful to add more metadata to your blog post, for example, author information, but Docusaurus will be able to infer all necessary metadata without the front matter. For all possible fields, see [the API documentation](api/plugins/plugin-content-blog.mdx#markdown-front-matter). + +## Blog list {#blog-list} + +The blog's index page (by default, it is at `/blog`) is the _blog list page_, where all blog posts are collectively displayed. + +Use the `<!--truncate-->` marker in your blog post to represent what will be shown as the summary when viewing all published blog posts. Anything above `<!--truncate-->` will be part of the summary. Note that the portion above the truncate marker must be standalone renderable Markdown. For example: + +```md title="website/blog/my-post.md" {7} +--- +title: Markdown blog truncation example +--- + +All these will be part of the blog post summary. + +<!-- truncate --> + +But anything from here on down will not be. +``` + +For files using the `.mdx` extension, use a [MDX](https://mdxjs.com/) comment `{/* truncate */}` instead: + +{/* prettier-ignore */} +```md title="website/blog/my-post.mdx" {7} +--- +title: MDX blog truncation Example +--- + +All these will be part of the blog post summary. + +{/* truncate */} + +But anything from here on down will not be. +``` + +By default, 10 posts are shown on each blog list page, but you can control pagination with the `postsPerPage` option in the plugin configuration. If you set `postsPerPage: 'ALL'`, pagination will be disabled and all posts will be displayed on the first page. You can also add a meta description to the blog list page for better SEO: + +```js title="docusaurus.config.js" +export default { + // ... + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + // highlight-start + blogTitle: 'Docusaurus blog!', + blogDescription: 'A Docusaurus powered blog!', + postsPerPage: 'ALL', + // highlight-end + }, + }, + ], + ], +}; +``` + +## Blog sidebar {#blog-sidebar} + +The blog sidebar displays recent blog posts. The default number of items shown is 5, but you can customize with the `blogSidebarCount` option in the plugin configuration. By setting `blogSidebarCount: 0`, the sidebar will be completely disabled, with the container removed as well. This will increase the width of the main container. Specially, if you have set `blogSidebarCount: 'ALL'`, _all_ posts will be displayed. + +You can also alter the sidebar heading text with the `blogSidebarTitle` option. For example, if you have set `blogSidebarCount: 'ALL'`, instead of the default "Recent posts", you may rather make it say "All posts": + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + // highlight-start + blogSidebarTitle: 'All posts', + blogSidebarCount: 'ALL', + // highlight-end + }, + }, + ], + ], +}; +``` + +## Blog post date {#blog-post-date} + +Docusaurus will extract a `YYYY-MM-DD` date from many patterns such as `YYYY-MM-DD-my-blog-post-title.md` or `YYYY/MM/DD/my-blog-post-title.md`. This enables you to easily group blog posts by year, by month, or to use a flat structure. + +<details> +<summary>Supported date extraction patterns</summary> + +| Pattern | Example | +| --- | --- | +| Single file | `2021-05-28-my-blog-post-title.md` | +| MDX file | `2021-05-28-my-blog-post-title.mdx` | +| Single folder + `index.md` | `2021-05-28-my-blog-post-title/index.md` | +| Folder named by date | `2021-05-28/my-blog-post-title.md` | +| Nested folders by date | `2021/05/28/my-blog-post-title.md` | +| Partially nested folders by date | `2021/05-28-my-blog-post-title.md` | +| Nested folders + `index.md` | `2021/05/28/my-blog-post-title/index.md` | +| Date in the middle of path | `category/2021/05-28-my-blog-post-title.md` | + +Docusaurus can extract the date from the posts using any of the naming patterns above. It is advisable to choose one pattern and apply it to all posts to avoid confusion. + +</details> + +:::tip + +Using a folder can be convenient to co-locate blog post images alongside the Markdown file. + +::: + +This naming convention is optional, and you can also provide the date as front matter. Since the front matter follows YAML syntax where the datetime notation is supported, you can use front matter if you need more fine-grained publish dates. For example, if you have multiple posts published on the same day, you can order them according to the time of the day: + +```md title="earlier-post.md" +--- +date: 2021-09-13T10:00 +--- +``` + +```md title="later-post.md" +--- +date: 2021-09-13T18:00 +--- +``` + +## Blog post authors {#blog-post-authors} + +Use the `authors` front matter field to declare blog post authors. An author should have at least a `name` or an `image_url`. Docusaurus uses information like `url`, `email`, and `title`, but any other information is allowed. + +### Inline authors {#inline-authors} + +Blog post authors can be declared directly inside the front matter: + +```mdx-code-block +<Tabs groupId="author-front-matter"> +<TabItem value="single" label="Single author"> +``` + +```md title="my-blog-post.md" +--- +authors: + name: Joel Marcey + title: Co-creator of Docusaurus 1 + url: https://github.com/JoelMarcey + image_url: https://github.com/JoelMarcey.png + email: jimarcey@gmail.com + socials: + x: joelmarcey + github: JoelMarcey +--- +``` + +```mdx-code-block +</TabItem> +<TabItem value="multiple" label="Multiple authors"> +``` + +```md title="my-blog-post.md" +--- +authors: + - name: Joel Marcey + title: Co-creator of Docusaurus 1 + url: https://github.com/JoelMarcey + image_url: https://github.com/JoelMarcey.png + email: jimarcey@gmail.com + socials: + x: joelmarcey + github: JoelMarcey + - name: Sébastien Lorber + title: Docusaurus maintainer + url: https://sebastienlorber.com + image_url: https://github.com/slorber.png + socials: + x: sebastienlorber + github: slorber +--- +``` + +```mdx-code-block +</TabItem> +</Tabs> +``` + +:::tip + +This option works best to get started, or for casual, irregular authors. + +::: + +:::info + +Prefer using the `authors` front matter, but the legacy `author_*` front matter remains supported: + +```md title="my-blog-post.md" +--- +author: Joel Marcey +author_title: Co-creator of Docusaurus 1 +author_url: https://github.com/JoelMarcey +author_image_url: https://github.com/JoelMarcey.png +--- +``` + +::: + +### Global authors {#global-authors} + +For regular blog post authors, it can be tedious to maintain authors' information inlined in each blog post. + +It is possible to declare those authors globally in a configuration file: + +```yml title="website/blog/authors.yml" +jmarcey: + name: Joel Marcey + title: Co-creator of Docusaurus 1 + url: https://github.com/JoelMarcey + image_url: https://github.com/JoelMarcey.png + email: jimarcey@gmail.com + socials: + x: joelmarcey + github: JoelMarcey + +slorber: + name: Sébastien Lorber + title: Docusaurus maintainer + url: https://sebastienlorber.com + image_url: https://github.com/slorber.png + socials: + x: sebastienlorber + github: slorber + email: seb@example.com +``` + +:::tip + +Use the `authorsMapPath` plugin option to configure the path. JSON is also supported. + +::: + +In blog posts front matter, you can reference the authors declared in the global configuration file: + +```mdx-code-block +<Tabs groupId="author-front-matter"> +<TabItem value="single" label="Single author"> +``` + +```md title="my-blog-post.md" +--- +authors: jmarcey +--- +``` + +```mdx-code-block +</TabItem> +<TabItem value="multiple" label="Multiple authors"> +``` + +```md title="my-blog-post.md" +--- +authors: [jmarcey, slorber] +--- +``` + +```mdx-code-block +</TabItem> +</Tabs> +``` + +:::info + +The `authors` system is very flexible and can suit more advanced use-case: + +<details> + <summary>Mix inline authors and global authors</summary> + +You can use global authors most of the time, and still use inline authors: + +```md title="my-blog-post.md" +--- +authors: + - jmarcey + - slorber + - name: Inline Author name + title: Inline Author Title + url: https://github.com/inlineAuthor + image_url: https://github.com/inlineAuthor +--- +``` + +</details> + +<details> + <summary>Local override of global authors</summary> + +You can customize the global author's data on per-blog-post basis: + +```md title="my-blog-post.md" +--- +authors: + - key: jmarcey + title: Joel Marcey's new title + - key: slorber + name: Sébastien Lorber's new name +--- +``` + +</details> + +<details> + <summary>Localize the author's configuration file</summary> + +The configuration file can be localized, just create a localized copy of it at: + +```bash +website/i18n/[locale]/docusaurus-plugin-content-blog/authors.yml +``` + +</details> + +::: + +An author, either declared through front matter or through the authors map, needs to have a name or an avatar, or both. If all authors of a post don't have names, Docusaurus will display their avatars compactly. See [this test post](/tests/blog/2022/01/20/image-only-authors) for the effect. + +:::warning Feed generation + +[RSS feeds](#feed) require the author's email to be set for the author to appear in the feed. + +::: + +### Authors pages {#authors-pages} + +The authors pages feature is optional, and mainly useful for multi-author blogs. + +You can activate it independently for each author by adding a `page: true` attribute to the [global author configuration](#global-authors): + +```yml title="website/blog/authors.yml" +slorber: + name: Sébastien Lorber + // highlight-start + page: true # Turns the feature on - route will be /authors/slorber + // highlight-end + +jmarcey: + name: Joel Marcey + // highlight-start + page: + # Turns the feature on - route will be /authors/custom-author-url + permalink: '/custom-author-url' + // highlight-end +``` + +The blog plugin will now generate: + +- a dedicated author page for each author ([example](/blog/authors/slorber)) listing all the blog posts they contributed to +- an authors index page ([example](/blog/authors)) listing all these authors, in the order they appear in `authors.yml` + +:::warning About inline authors + +Only [global authors](#global-authors) can activate this feature. [Inline authors](#inline-authors) are not supported. + +::: + +## Blog post tags {#blog-post-tags} + +Tags are declared in the front matter and introduce another dimension of categorization. + +It is possible to define tags inline, or to reference predefined tags declared in a [`tags file`](api/plugins/plugin-content-blog.mdx#tags-file) (optional, usually `blog/tags.yml`). + +In the following example: + +- `docusaurus` references a predefined tag key declared in `blog/tags.yml` +- `Releases` is an inline tag, because it does not exist in `blog/tags.yml` + +```md title="blog/my-post.md" +--- +title: 'My blog post' +tags: + - Releases + - docusaurus +--- + +Content +``` + +```yml title="blog/tags.yml" +docusaurus: + label: 'Docusaurus' + permalink: '/docusaurus' + description: 'Blog posts related to the Docusaurus framework' +``` + +## Reading time {#reading-time} + +Docusaurus generates a reading time estimation for each blog post based on word count. We provide an option to customize this. + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + // highlight-start + showReadingTime: true, // When set to false, the "x min read" won't be shown + readingTime: ({content, locale, frontMatter, defaultReadingTime}) => + defaultReadingTime({ + content, + locale, + options: {wordsPerMinute: 300}, + }), + // highlight-end + }, + }, + ], + ], +}; +``` + +The `readingTime` callback receives the following parameters: + +- `content`: the blog content text as a string +- `frontMatter`: the front matter as a record of string keys and their values +- `locale`: the locale of the current Docusaurus site +- `defaultReadingTime`: the default built-in reading time function. It returns a number (reading time in minutes) or `undefined` (disable reading time for this page). + +The default reading time is able to accept additional options: + +- `wordsPerMinute` as a number (default: 300) + +:::tip + +Use the callback for all your customization needs: + +```mdx-code-block +<Tabs> +<TabItem value="disable-per-post" label="Per-post disabling"> +``` + +**Disable reading time on one page:** + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + showReadingTime: true, + // highlight-start + readingTime: ({content, locale, frontMatter, defaultReadingTime}) => + frontMatter.hide_reading_time + ? undefined + : defaultReadingTime({content, locale}), + // highlight-end + }, + }, + ], + ], +}; +``` + +Usage: + +```md "my-blog-post.md" +--- +hide_reading_time: true +--- + +This page will no longer display the reading time stats! +``` + +```mdx-code-block +</TabItem> +<TabItem value="passing-options" label="Passing options"> +``` + +**Pass options to the default reading time function:** + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + // highlight-start + readingTime: ({content, locale, defaultReadingTime}) => + defaultReadingTime({ + content, + locale, + options: {wordsPerMinute: 100}, + }), + // highlight-end + }, + }, + ], + ], +}; +``` + +```mdx-code-block +</TabItem> +<TabItem value="using-custom-algo" label="Using custom algorithms"> +``` + +**Use a custom implementation of reading time:** + +```js title="docusaurus.config.js" +import myReadingTime from './myReadingTime'; + +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + // highlight-next-line + readingTime: ({content, locale}) => myReadingTime(content, locale), + }, + }, + ], + ], +}; +``` + +```mdx-code-block +</TabItem> +</Tabs> +``` + +::: + +## Feed {#feed} + +You can generate RSS / Atom / JSON feed by passing `feedOptions`. By default, RSS and Atom feeds are generated. To disable feed generation, set `feedOptions.type` to `null`. + +```ts +type FeedType = 'rss' | 'atom' | 'json'; + +type BlogOptions = { + feedOptions?: { + type?: FeedType | 'all' | FeedType[] | null; + title?: string; + description?: string; + copyright: string; + + language?: string; // possible values: http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes + limit?: number | false | null; // defaults to 20 + // XSLT permits browsers to style and render nicely the feed XML files + xslt?: + | boolean + | { + // + rss?: string | boolean; + atom?: string | boolean; + }; + // Allow control over the construction of BlogFeedItems + createFeedItems?: (params: { + blogPosts: BlogPost[]; + siteConfig: DocusaurusConfig; + outDir: string; + defaultCreateFeedItems: (params: { + blogPosts: BlogPost[]; + siteConfig: DocusaurusConfig; + outDir: string; + }) => Promise<BlogFeedItem[]>; + }) => Promise<BlogFeedItem[]>; + }; +}; +``` + +Example usage: + +```js title="docusaurus.config.js" +export default { + // ... + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + // highlight-start + feedOptions: { + type: 'all', + copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc.`, + createFeedItems: async (params) => { + const {blogPosts, defaultCreateFeedItems, ...rest} = params; + return defaultCreateFeedItems({ + // keep only the 10 most recent blog posts in the feed + blogPosts: blogPosts.filter((item, index) => index < 10), + ...rest, + }); + }, + }, + // highlight-end + }, + }, + ], + ], +}; +``` + +The feeds can be found at: + +<Tabs> +<TabItem value="RSS"> + +```text +https://example.com/blog/rss.xml +``` + +</TabItem> +<TabItem value="Atom"> + +```text +https://example.com/blog/atom.xml +``` + +</TabItem> +<TabItem value="JSON"> + +```text +https://example.com/blog/feed.json +``` + +</TabItem> +</Tabs> + +## Advanced topics {#advanced-topics} + +### Blog-only mode {#blog-only-mode} + +You can run your Docusaurus site without a dedicated landing page and instead have your blog's post list page as the index page. Set the `routeBasePath` to be `'/'` to serve the blog through the root route `example.com/` instead of the subroute `example.com/blog/`. + +```js title="docusaurus.config.js" +export default { + // ... + presets: [ + [ + '@docusaurus/preset-classic', + { + // highlight-next-line + docs: false, // Optional: disable the docs plugin + blog: { + // highlight-next-line + routeBasePath: '/', // Serve the blog at the site's root + /* other blog options */ + }, + }, + ], + ], +}; +``` + +:::warning + +Don't forget to delete the existing homepage at `./src/pages/index.js` or else there will be two files mapping to the same route! + +::: + +:::warning + +If you disable the docs plugin, don't forget to delete references to the docs plugin elsewhere in your configuration file. Notably, make sure to remove the docs-related navbar items. + +::: + +:::tip + +There's also a "Docs-only mode" for those who only want to use the docs. Read [Docs-only mode](./guides/docs/docs-introduction.mdx) for detailed instructions or a more elaborate explanation of `routeBasePath`. + +::: + +### Multiple blogs {#multiple-blogs} + +By default, the classic theme assumes only one blog per website and hence includes only one instance of the blog plugin. If you would like to have multiple blogs on a single website, it's possible too! You can add another blog by specifying another blog plugin in the `plugins` option for `docusaurus.config.js`. + +Set the `routeBasePath` to the URL route that you want your second blog to be accessed on. Note that the `routeBasePath` here has to be different from the first blog or else there could be a collision of paths! Also, set `path` to the path to the directory containing your second blog's entries. + +As documented for [multi-instance plugins](./using-plugins.mdx#multi-instance-plugins-and-plugin-ids), you need to assign a unique ID to the plugins. + +```js title="docusaurus.config.js" +export default { + // ... + plugins: [ + [ + '@docusaurus/plugin-content-blog', + { + /** + * Required for any multi-instance plugin + */ + id: 'second-blog', + /** + * URL route for the blog section of your site. + * *DO NOT* include a trailing slash. + */ + routeBasePath: 'my-second-blog', + /** + * Path to data on filesystem relative to site dir. + */ + path: './my-second-blog', + }, + ], + ], +}; +``` + +As an example, we host a second blog [here](/tests/blog). diff --git a/website/versioned_docs/version-3.9.0/browser-support.mdx b/website/versioned_docs/version-3.9.0/browser-support.mdx new file mode 100644 index 0000000000..79c01861d7 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/browser-support.mdx @@ -0,0 +1,106 @@ +--- +description: How to keep a reasonable bundle size while ensuring sufficient browser support. +--- + +# Browser support + +Docusaurus allows sites to define the list of supported browsers through a [browserslist configuration](https://github.com/browserslist/browserslist). + +## Purpose {#purpose} + +Websites need to balance between backward compatibility and bundle size. As old browsers do not support modern APIs or syntax, more code is needed to implement the same functionality. + +For example, you may use the [optional chaining syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining): + +```js +const value = obj?.prop?.val; +``` + +...which unfortunately is only recognized by browser versions released after 2020. To be compatible with earlier browser versions, when building your site for production, our JS loader will transpile your code to a more verbose syntax: + +```js +var _obj, _obj$prop; + +const value = + (_obj = obj) === null || _obj === void 0 + ? void 0 + : (_obj$prop = _obj.prop) === null || _obj$prop === void 0 + ? void 0 + : _obj$prop.val; +``` + +However, this penalizes all other users with increased site load time because the 29-character line now becomes 168 characters—a 6-fold increase! (In practice, it will be better because the names used will be shorter.) As a tradeoff, the JS loader only transpiles the syntax to the degree that's supported by all browser versions defined in the browser list. + +The browser list by default is provided through the `package.json` file as a root `browserslist` field. + +:::warning + +On old browsers, the compiled output will use unsupported (too recent) JS syntax, causing React to fail to initialize and end up with a static website with only HTML/CSS and no JS. + +::: + +## Default values {#default-values} + +Websites initialized with the default classic template has the following in `package.json`: + +```json title="package.json" +{ + "name": "docusaurus", + // ... + // highlight-start + "browserslist": { + "production": [">0.5%", "not dead", "not op_mini all"], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } + // highlight-end + // ... +} +``` + +Explained in natural language, the browsers supported in production are those: + +- With more than 0.5% of market share; _and_ +- Has official support or updates in the past 24 months (the opposite of "dead"); _and_ +- Is not Opera Mini. + +And browsers used in development are: + +- The latest version of Chrome _or_ Firefox _or_ Safari. + +You can "evaluate" any config with the `browserslist` CLI to obtain the actual list: + +```bash +npx browserslist --env="production" +``` + +The output is all browsers supported in production. Below is the output in January 2022: + +```text +and_chr 96 +and_uc 12.12 +chrome 96 +chrome 95 +chrome 94 +edge 96 +firefox 95 +firefox 94 +ie 11 +ios_saf 15.2 +ios_saf 15.0-15.1 +ios_saf 14.5-14.8 +ios_saf 14.0-14.4 +ios_saf 12.2-12.5 +opera 82 +opera 81 +safari 15.1 +safari 14.1 +safari 13.1 +``` + +## Read more {#read-more} + +You may wish to visit the [browserslist documentation](https://github.com/browserslist/browserslist/blob/main/README.md) for more specifications, especially the accepted [query values](https://github.com/browserslist/browserslist/blob/main/README.md#queries) and [best practices](https://github.com/browserslist/browserslist/blob/main/README.md#best-practices). diff --git a/website/versioned_docs/version-3.9.0/cli.mdx b/website/versioned_docs/version-3.9.0/cli.mdx new file mode 100644 index 0000000000..1ec8120b49 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/cli.mdx @@ -0,0 +1,190 @@ +--- +description: Docusaurus provides a set of scripts to help you generate, serve, and deploy your website. +--- + +# CLI + +Docusaurus provides a set of scripts to help you generate, serve, and deploy your website. + +Once your website is bootstrapped, the website source will contain the Docusaurus scripts that you can invoke with your package manager: + +```json title="package.json" +{ + // ... + "scripts": { + "docusaurus": "docusaurus", + "start": "docusaurus start", + "build": "docusaurus build", + "swizzle": "docusaurus swizzle", + "deploy": "docusaurus deploy", + "clear": "docusaurus clear", + "serve": "docusaurus serve", + "write-translations": "docusaurus write-translations", + "write-heading-ids": "docusaurus write-heading-ids" + } +} +``` + +## Docusaurus CLI commands {#docusaurus-cli-commands} + +Below is a list of Docusaurus CLI commands and their usages: + +### `docusaurus start [siteDir]` {#docusaurus-start-sitedir} + +Builds and serves a preview of your site locally with [Webpack Dev Server](https://webpack.js.org/configuration/dev-server). + +#### Options {#options} + +| Name | Default | Description | +| --- | --- | --- | +| `--port` | `3000` | Specifies the port of the dev server. | +| `--host` | `localhost` | Specify a host to use. For example, if you want your server to be accessible externally, you can use `--host 0.0.0.0`. | +| `--locale` | | Specify site locale to be used. | +| `--hot-only` | `false` | Enables Hot Module Replacement without page refresh as a fallback in case of build failures. More information [here](https://webpack.js.org/configuration/dev-server/#devserverhotonly). | +| `--no-open` | `false` | Do not open the page automatically in the browser. | +| `--config` | `undefined` | Path to Docusaurus config file, default to `[siteDir]/docusaurus.config.js` | +| `--poll [optionalIntervalMs]` | `false` | Use polling of files rather than watching for live reload as a fallback in environments where watching doesn't work. More information [here](https://webpack.js.org/configuration/watch/#watchoptionspoll). | +| `--no-minify` | `false` | Build website without minimizing JS/CSS bundles. | + +:::info + +Please note that some functionality (for example, anchor links) will not work in development. The functionality will work as expected in production. + +::: + +:::info Development over network + +When forwarding port 3000 from a remote server or VM (e.g. GitHub Codespaces), you can run the dev server on `0.0.0.0` to make it listen on the local IP. + +```bash npm2yarn +npm run start -- --host 0.0.0.0 +``` + +::: + +#### Enabling HTTPS {#enabling-https} + +There are multiple ways to obtain a certificate. We will use [mkcert](https://github.com/FiloSottile/mkcert) as an example. + +1. Run `mkcert localhost` to generate `localhost.pem` + `localhost-key.pem` + +2. Run `mkcert -install` to install the cert in your trust store, and restart your browser + +3. Start the app with Docusaurus HTTPS env variables: + +```bash +HTTPS=true SSL_CRT_FILE=localhost.pem SSL_KEY_FILE=localhost-key.pem yarn start +``` + +4. Open `https://localhost:3000/` + +### `docusaurus build [siteDir]` {#docusaurus-build-sitedir} + +Compiles your site for production. + +#### Options {#options-1} + +| Name | Default | Description | +| --- | --- | --- | +| `--dev` | | Builds the website in dev mode, including full React error messages. | +| `--bundle-analyzer` | `false` | Analyze your bundle with the [webpack bundle analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer). | +| `--out-dir` | `build` | The full path for the new output directory, relative to the current workspace. | +| `--config` | `undefined` | Path to Docusaurus config file, default to `[siteDir]/docusaurus.config.js` | +| `--locale` | | Build the site in the specified locale(s). If not specified, all known locales are built. | +| `--no-minify` | `false` | Build website without minimizing JS/CSS bundles. | + +:::info + +For advanced minification of CSS bundle, we use the [advanced cssnano preset](https://github.com/cssnano/cssnano/tree/master/packages/cssnano-preset-advanced) (along with additional several PostCSS plugins) and [level 2 optimization of clean-css](https://github.com/jakubpawlowicz/clean-css#level-2-optimizations). If as a result of this advanced CSS minification you find broken CSS, build your website with the environment variable `USE_SIMPLE_CSS_MINIFIER=true` to minify CSS with the [default cssnano preset](https://github.com/cssnano/cssnano/tree/master/packages/cssnano-preset-default). **Please [fill out an issue](https://github.com/facebook/docusaurus/issues/new?labels=bug%2C+needs+triage&template=bug.md) if you experience CSS minification bugs.** + +You can skip the HTML minification with the environment variable `SKIP_HTML_MINIFICATION=true`. + +::: + +### `docusaurus swizzle [themeName] [componentName] [siteDir]` {#docusaurus-swizzle} + +[Swizzle](./swizzling.mdx) a theme component to customize it. + +```bash npm2yarn +npm run swizzle [themeName] [componentName] [siteDir] + +# Example (leaving out the siteDir to indicate this directory) +npm run swizzle @docusaurus/theme-classic Footer -- --eject +``` + +The swizzle CLI is interactive and will guide you through the whole [swizzle process](./swizzling.mdx). + +#### Options {#options-swizzle} + +| Name | Description | +| --- | --- | +| `themeName` | The name of the theme to swizzle from. | +| `componentName` | The name of the theme component to swizzle. | +| `--list` | Display components available for swizzling | +| `--eject` | [Eject](./swizzling.mdx#ejecting) the theme component | +| `--wrap` | [Wrap](./swizzling.mdx#wrapping) the theme component | +| `--danger` | Allow immediate swizzling of unsafe components | +| `--typescript` | Swizzle the TypeScript variant component | +| `--config` | Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js` | + +:::warning + +Unsafe components have a higher risk of breaking changes due to internal refactorings. + +::: + +### `docusaurus deploy [siteDir]` {#docusaurus-deploy-sitedir} + +Deploys your site with [GitHub Pages](https://pages.github.com/). Check out the docs on [deployment](deployment.mdx#deploying-to-github-pages) for more details. + +#### Options {#options-3} + +| Name | Default | Description | +| --- | --- | --- | +| `--locale` | | Deploy the site in the specified locale(s). If not specified, all known locales are deployed. | +| `--out-dir` | `build` | The full path for the new output directory, relative to the current workspace. | +| `--skip-build` | `false` | Deploy website without building it. This may be useful when using a custom deploy script. | +| `--target-dir` | `.` | Path to the target directory to deploy to. | +| `--config` | `undefined` | Path to Docusaurus config file, default to `[siteDir]/docusaurus.config.js` | + +### `docusaurus serve [siteDir]` {#docusaurus-serve-sitedir} + +Serve your built website locally. + +| Name | Default | Description | +| --- | --- | --- | +| `--port` | `3000` | Use specified port | +| `--dir` | `build` | The full path for the output directory, relative to the current workspace | +| `--build` | `false` | Build website before serving | +| `--config` | `undefined` | Path to Docusaurus config file, default to `[siteDir]/docusaurus.config.js` | +| `--host` | `localhost` | Specify a host to use. For example, if you want your server to be accessible externally, you can use `--host 0.0.0.0`. | +| `--no-open` | `false` locally, `true` in CI | Do not open a browser window to the server location. | + +### `docusaurus clear [siteDir]` {#docusaurus-clear-sitedir} + +Clear a Docusaurus site's generated assets, caches, build artifacts. + +We recommend running this command before reporting bugs, after upgrading versions, or anytime you have issues with your Docusaurus site. + +### `docusaurus write-translations [siteDir]` {#docusaurus-write-translations-sitedir} + +Write the JSON translation files that you will have to translate. + +By default, the files are written in `website/i18n/<defaultLocale>/...`. + +| Name | Default | Description | +| --- | --- | --- | +| `--locale` | `<defaultLocale>` | Define which locale folder you want to write translations the JSON files in | +| `--override` | `false` | Override existing translation messages | +| `--config` | `undefined` | Path to Docusaurus config file, default to `[siteDir]/docusaurus.config.js` | +| `--messagePrefix` | `''` | Allows adding a prefix to each translation message, to help you highlight untranslated strings | + +### `docusaurus write-heading-ids [siteDir] [files]` {#docusaurus-write-heading-ids-sitedir} + +Add [explicit heading IDs](./guides/markdown-features/markdown-features-toc.mdx#heading-ids) to the Markdown documents of your site. + +| Name | Default | Description | +| --- | --- | --- | +| `files` | All MD files used by plugins | The files that you want heading IDs to be written to. | +| `--maintain-case` | `false` | Keep the headings' casing, otherwise make all lowercase. | +| `--overwrite` | `false` | Overwrite existing heading IDs. | diff --git a/website/versioned_docs/version-3.9.0/configuration.mdx b/website/versioned_docs/version-3.9.0/configuration.mdx new file mode 100644 index 0000000000..40e435afef --- /dev/null +++ b/website/versioned_docs/version-3.9.0/configuration.mdx @@ -0,0 +1,294 @@ +--- +description: Configuring your site's behavior through docusaurus.config.js and more. +--- + +# Configuration + +import TOCInline from '@theme/TOCInline'; + +:::info + +Check the [**`docusaurus.config.js` API reference**](api/docusaurus.config.js.mdx) for an exhaustive list of options. + +::: + +Docusaurus has a unique take on configurations. We encourage you to congregate information about your site into one place. We guard the fields of this file and facilitate making this data object accessible across your site. + +Keeping a well-maintained `docusaurus.config.js` helps you, your collaborators, and your open source contributors to be able to focus on documentation while still being able to customize the site. + +## Syntax to declare `docusaurus.config.js` {#syntax-to-declare-docusaurus-config} + +The `docusaurus.config.js` file is run in Node.js and should export either: + +- a **config object** +- a **function** that creates the config object + +:::info + +The `docusaurus.config.js` file supports: + +- [**ES Modules**](https://flaviocopes.com/es-modules/) +- [**CommonJS**](https://flaviocopes.com/commonjs/) +- [**TypeScript**](./typescript-support.mdx#typing-config) + +Constraints: + +- **Required:** use `export default /* your config*/` (or `module.exports`) to export your Docusaurus config +- **Optional:** use `import Lib from 'lib'` (or `require('lib')`) to import Node.js packages + +::: + +Docusaurus gives us the ability to declare its configuration in various **equivalent ways**, and all the following config examples lead to the exact same result: + +```js title="docusaurus.config.js" +export default { + title: 'Docusaurus', + url: 'https://docusaurus.io', + // your site config ... +}; +``` + +```js title="docusaurus.config.js" +module.exports = { + title: 'Docusaurus', + url: 'https://docusaurus.io', + // your site config ... +}; +``` + +```ts title="docusaurus.config.ts" +import type {Config} from '@docusaurus/types'; + +export default { + title: 'Docusaurus', + url: 'https://docusaurus.io', + // your site config ... +} satisfies Config; +``` + +```js title="docusaurus.config.js" +const config = { + title: 'Docusaurus', + url: 'https://docusaurus.io', + // your site config ... +}; + +export default config; +``` + +```js title="docusaurus.config.js" +export default function configCreator() { + return { + title: 'Docusaurus', + url: 'https://docusaurus.io', + // your site config ... + }; +} +``` + +```js title="docusaurus.config.js" +export default async function createConfigAsync() { + return { + title: 'Docusaurus', + url: 'https://docusaurus.io', + // your site config ... + }; +} +``` + +:::tip Using ESM-only packages + +Using an async config creator can be useful to import ESM-only modules (notably most Remark plugins). It is possible to import such modules thanks to dynamic imports: + +```js title="docusaurus.config.js" +export default async function createConfigAsync() { + // Use a dynamic import instead of require('esm-lib') + // highlight-next-line + const lib = await import('lib'); + + return { + title: 'Docusaurus', + url: 'https://docusaurus.io', + // rest of your site config... + }; +} +``` + +::: + +## What goes into a `docusaurus.config.js`? {#what-goes-into-a-docusaurusconfigjs} + +You should not have to write your `docusaurus.config.js` from scratch even if you are developing your site. All templates come with a `docusaurus.config.js` that includes defaults for the common options. + +However, it can be helpful if you have a high-level understanding of how the configurations are designed and implemented. + +The high-level overview of Docusaurus configuration can be categorized into: + +<TOCInline toc={toc} minHeadingLevel={3} maxHeadingLevel={3} /> + +### Site metadata {#site-metadata} + +Site metadata contains the essential global metadata such as `title`, `url`, `baseUrl`, and `favicon`. + +They are used in several places such as your site's title and headings, browser tab icon, social sharing (Facebook, X) information or even to generate the correct path to serve your static files. + +### Deployment configurations {#deployment-configurations} + +Deployment configurations such as `projectName`, `organizationName`, and optionally `deploymentBranch` are used when you deploy your site with the `deploy` command. + +It is recommended to check the [deployment docs](deployment.mdx) for more information. + +### Theme, plugin, and preset configurations {#theme-plugin-and-preset-configurations} + +List the [themes](./using-plugins.mdx#using-themes), [plugins](./using-plugins.mdx), and [presets](./using-plugins.mdx#using-presets) for your site in the `themes`, `plugins`, and `presets` fields, respectively. These are typically npm packages: + +```js title="docusaurus.config.js" +export default { + // ... + plugins: [ + '@docusaurus/plugin-content-blog', + '@docusaurus/plugin-content-pages', + ], + themes: ['@docusaurus/theme-classic'], +}; +``` + +:::tip + +Docusaurus supports [**module shorthands**](./using-plugins.mdx#module-shorthands), allowing you to simplify the above configuration as: + +```js title="docusaurus.config.js" +export default { + // ... + plugins: ['content-blog', 'content-pages'], + themes: ['classic'], +}; +``` + +::: + +They can also be loaded from local directories: + +```js title="docusaurus.config.js" +import path from 'path'; + +export default { + // ... + themes: [path.resolve(__dirname, '/path/to/docusaurus-local-theme')], +}; +``` + +To specify options for a plugin or theme, replace the name of the plugin or theme in the config file with an array containing the name and an options object: + +```js title="docusaurus.config.js" +export default { + // ... + plugins: [ + [ + 'content-blog', + { + path: 'blog', + routeBasePath: 'blog', + include: ['*.md', '*.mdx'], + // ... + }, + ], + 'content-pages', + ], +}; +``` + +To specify options for a plugin or theme that is bundled in a preset, pass the options through the `presets` field. In this example, `docs` refers to `@docusaurus/plugin-content-docs` and `theme` refers to `@docusaurus/theme-classic`. + +```js title="docusaurus.config.js" +export default { + // ... + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + sidebarPath: './sidebars.js', + }, + theme: { + customCss: ['./src/css/custom.css'], + }, + }, + ], + ], +}; +``` + +:::tip + +The `presets: [['classic', {...}]]` shorthand works as well. + +::: + +For further help configuring themes, plugins, and presets, see [Using Plugins](./using-plugins.mdx). + +### Custom configurations {#custom-configurations} + +Docusaurus guards `docusaurus.config.js` from unknown fields. To add custom fields, define them in `customFields`. + +Example: + +```js title="docusaurus.config.js" +export default { + // ... + // highlight-start + customFields: { + image: '', + keywords: [], + }, + // highlight-end + // ... +}; +``` + +## Accessing configuration from components {#accessing-configuration-from-components} + +Your configuration object will be made available to all the components of your site. And you may access them via React context as `siteConfig`. + +Basic example: + +```jsx +import React from 'react'; +// highlight-next-line +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; + +const Hello = () => { + // highlight-start + const {siteConfig} = useDocusaurusContext(); + // highlight-end + const {title, tagline} = siteConfig; + + return <div>{`${title} · ${tagline}`}</div>; +}; +``` + +:::tip + +If you just want to use those fields on the client side, you could create your own JS files and import them as ES6 modules, there is no need to put them in `docusaurus.config.js`. + +::: + +## Customizing Babel Configuration {#customizing-babel-configuration} + +Docusaurus transpiles your site's source code using Babel by default. If you want to customize the Babel configuration, you can do so by creating a `babel.config.js` file in your project root. + +To use the built-in preset as a base configuration, install the following package and use it + +```bash npm2yarn +npm install --save @docusaurus/babel +``` + +Then use the preset in your `babel.config.js` file: + +```js title="babel.config.js" +export default { + presets: ['@docusaurus/babel/preset'], +}; +``` + +Most of the time, the default preset configuration will work just fine. If you want to customize your Babel configuration (e.g. to add support for Flow), you can directly edit this file. For your changes to take effect, you need to restart the Docusaurus dev server. diff --git a/website/versioned_docs/version-3.9.0/deployment.mdx b/website/versioned_docs/version-3.9.0/deployment.mdx new file mode 100644 index 0000000000..98f8f02cfa --- /dev/null +++ b/website/versioned_docs/version-3.9.0/deployment.mdx @@ -0,0 +1,939 @@ +--- +description: Deploy your Docusaurus app for production on a range of static site hosting services. +--- + +# Deployment + +To build the static files of your website for production, run: + +```bash npm2yarn +npm run build +``` + +Once it finishes, the static files will be generated within the `build` directory. + +:::note + +The only responsibility of Docusaurus is to build your site and emit static files in `build`. + +It is now up to you to choose how to host those static files. + +::: + +You can deploy your site to static site hosting services such as [Vercel](https://vercel.com/), [GitHub Pages](https://pages.github.com/), [Netlify](https://www.netlify.com/), [Render](https://render.com/docs/static-sites), and [Surge](https://surge.sh/help/getting-started-with-surge). + +A Docusaurus site is statically rendered, and it can generally work without JavaScript! + +## Configuration {#configuration} + +The following parameters are required in `docusaurus.config.js` to optimize routing and serve files from the correct location: + +| Name | Description | +| --- | --- | +| `url` | URL for your site. For a site deployed at `https://my-org.com/my-project/`, `url` is `https://my-org.com/`. | +| `baseUrl` | Base URL for your project, with a trailing slash. For a site deployed at `https://my-org.com/my-project/`, `baseUrl` is `/my-project/`. | + +## Testing your Build Locally {#testing-build-locally} + +It is important to test your build locally before deploying it for production. Docusaurus provides a [`docusaurus serve`](cli.mdx#docusaurus-serve-sitedir) command for that: + +```bash npm2yarn +npm run serve +``` + +By default, this will load your site at [`http://localhost:3000/`](http://localhost:3000/). + +## Trailing slash configuration {#trailing-slashes} + +Docusaurus has a [`trailingSlash` config](./api/docusaurus.config.js.mdx#trailingSlash) to allow customizing URLs/links and emitted filename patterns. + +The default value generally works fine. Unfortunately, each static hosting provider has a **different behavior**, and deploying the exact same site to various hosts can lead to distinct results. Depending on your host, it can be useful to change this config. + +:::tip + +Use [slorber/trailing-slash-guide](https://github.com/slorber/trailing-slash-guide) to understand better the behavior of your host and configure `trailingSlash` appropriately. + +::: + +## Using environment variables {#using-environment-variables} + +Putting potentially sensitive information in the environment is common practice. However, in a typical Docusaurus website, the `docusaurus.config.js` file is the only interface to the Node.js environment (see [our architecture overview](advanced/architecture.mdx)), while everything else (MDX pages, React components, etc.) are client side and do not have direct access to the `process` global variable. In this case, you can consider using [`customFields`](api/docusaurus.config.js.mdx#customFields) to pass environment variables to the client side. + +```js title="docusaurus.config.js" +// If you are using dotenv (https://www.npmjs.com/package/dotenv) +import 'dotenv/config'; + +export default { + title: '...', + url: process.env.URL, // You can use environment variables to control site specifics as well + // highlight-start + customFields: { + // Put your custom environment here + teamEmail: process.env.EMAIL, + }, + // highlight-end +}; +``` + +```jsx title="home.jsx" +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; + +export default function Home() { + const { + siteConfig: {customFields}, + } = useDocusaurusContext(); + return <div>Contact us through {customFields.teamEmail}!</div>; +} +``` + +## Choosing a hosting provider {#choosing-a-hosting-provider} + +There are a few common hosting options: + +- [Self hosting](#self-hosting) with an HTTP server like Apache2 or Nginx. +- Jamstack providers (e.g. [Netlify](#deploying-to-netlify) and [Vercel](#deploying-to-vercel)). We will use them as references, but the same reasoning can apply to other providers. +- [GitHub Pages](#deploying-to-github-pages) (by definition, it is also Jamstack, but we compare it separately). + +If you are unsure of which one to choose, ask the following questions: + +<details> + +<summary> + How many resources (money, person-hours, etc.) am I willing to invest in this? +</summary> + +- 🔴 Self-hosting requires experience in networking as well as Linux and web server administration. It's the most difficult option, and would require the most time to manage successfully. Expense-wise, cloud services are almost never free, and purchasing/deploying an onsite server can be even more costly. +- 🟢 Jamstack providers can help you set up a working website in almost no time and offer features like server-side redirects that are easily configurable. Many providers offer generous build-time quotas even for free plans that you would almost never exceed. However, free plans have limits, and you would need to pay once you hit those limits. Check the pricing page of your provider for details. +- 🟡 The GitHub Pages deployment workflow can be tedious to set up. (Evidence: see the length of [Deploying to GitHub Pages](#deploying-to-github-pages)!) However, this service (including build and deployment) is always free for public repositories, and we have detailed instructions to help you make it work. + +</details> + +<details> + +<summary>How much server-side customization do I need?</summary> + +- 🟢 With self-hosting, you have access to the entire server's configuration. You can configure the virtual host to serve different content based on the request URL, you can do complicated server-side redirects, you can implement authentication, and so on. If you need a lot of server-side features, self-host your website. +- 🟡 Jamstack usually offers some server-side configuration (e.g. URL formatting (trailing slashes), server-side redirects, etc.). +- 🔴 GitHub Pages doesn't expose server-side configuration besides enforcing HTTPS and setting CNAME records. + +</details> + +<details> + +<summary>Do I need collaboration-friendly deployment workflows?</summary> + +- 🟡 Self-hosted services can leverage continuous deployment functionality like Netlify, but more heavy-lifting is involved. Usually, you would designate a specific person to manage the deployment, and the workflow wouldn't be very git-based as opposed to the other two options. +- 🟢 Netlify and Vercel have deploy previews for every pull request, which is useful for a team to review work before merging to production. You can also manage a team with different member access to the deployment. +- 🟡 GitHub Pages cannot do deploy previews in a non-convoluted way. One repo can only be associated with one site deployment. On the other hand, you can control who has write access to the site's deployment. + +</details> + +There isn't a silver bullet. You need to weigh your needs and resources before making a choice. + +## Self-Hosting {#self-hosting} + +Docusaurus can be self-hosted using [`docusaurus serve`](cli.mdx#docusaurus-serve-sitedir). Change port using `--port` and `--host` to change host. + +```bash npm2yarn +npm run serve -- --build --port 80 --host 0.0.0.0 +``` + +:::warning + +It is not the best option, compared to a static hosting provider / CDN. + +::: + +:::warning + +In the following sections, we will introduce a few common hosting providers and how they should be configured to deploy Docusaurus sites most efficiently. Docusaurus is not affiliated with any of these services, and this information is provided for convenience only. Some of the write-ups are provided by third-parties, and recent API changes may not be reflected on our side. If you see outdated content, PRs are welcome. + +Because we can only provide this content on a best-effort basis only, we have stopped accepting PRs adding new hosting options. You can, however, publish your writeup on a separate site (e.g. your blog, or the provider's official website), and ask us to include a link to your writeup. + +::: + +## Deploying to Netlify {#deploying-to-netlify} + +To deploy your Docusaurus sites to [Netlify](https://www.netlify.com/), first make sure the following options are properly configured: + +```js title="docusaurus.config.js" +export default { + // highlight-start + url: 'https://docusaurus-2.netlify.app', // Url to your site with no trailing slash + baseUrl: '/', // Base directory of your site relative to your repo + // highlight-end + // ... +}; +``` + +Then, [create your site with Netlify](https://app.netlify.com/start). + +While you set up the site, specify the build commands and directories as follows: + +- build command: `npm run build` +- publish directory: `build` + +If you did not configure these build options, you may still go to "Site settings" -> "Build & deploy" after your site is created. + +Once properly configured with the above options, your site should deploy and automatically redeploy upon merging to your deploy branch, which defaults to `main`. + +:::warning + +Some Docusaurus sites put the `docs` folder outside of `website` (most likely former Docusaurus v1 sites): + +```bash +repo # git root +├── docs # MD files +└── website # Docusaurus root +``` + +If you decide to use the `website` folder as Netlify's base directory, Netlify will not trigger builds when you update the `docs` folder, and you need to configure a [custom `ignore` command](https://docs.netlify.com/configure-builds/common-configurations/ignore-builds/): + +```toml title="website/netlify.toml" +[build] + ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF . ../docs/" +``` + +::: + +:::warning + +By default, Netlify adds trailing slashes to Docusaurus URLs. + +It is recommended to disable the Netlify setting `Post Processing > Asset Optimization > Pretty Urls` to prevent lowercase URLs, unnecessary redirects, and 404 errors. + +**Be very careful**: the `Disable asset optimization` global checkbox is broken and does not really disable the `Pretty URLs` setting in practice. Please make sure to **uncheck it independently**. + +If you want to keep the `Pretty Urls` Netlify setting on, adjust the `trailingSlash` Docusaurus config appropriately. + +Refer to [slorber/trailing-slash-guide](https://github.com/slorber/trailing-slash-guide) for more information. + +::: + +## Deploying to Vercel {#deploying-to-vercel} + +Deploying your Docusaurus project to [Vercel](https://vercel.com/) will provide you with [various benefits](https://vercel.com/) in the areas of performance and ease of use. + +To deploy your Docusaurus project with a [Vercel for Git Integration](https://vercel.com/docs/concepts/git), make sure it has been pushed to a Git repository. + +Import the project into Vercel using the [Import Flow](https://vercel.com/import/git). During the import, you will find all relevant options preconfigured for you; however, you can choose to change any of these [options](https://vercel.com/docs/build-step#build-&-development-settings). + +After your project has been imported, all subsequent pushes to branches will generate [Preview Deployments](https://vercel.com/docs/platform/deployments#preview), and all changes made to the [Production Branch](https://vercel.com/docs/git-integrations#production-branch) (usually "main" or "master") will result in a [Production Deployment](https://vercel.com/docs/platform/deployments#production). + +## Deploying to GitHub Pages {#deploying-to-github-pages} + +Docusaurus provides an easy way to publish to [GitHub Pages](https://pages.github.com/), which comes free with every GitHub repository. + +### Overview {#github-pages-overview} + +Usually, there are two repositories (at least two branches) involved in a publishing process: the branch containing the source files, and the branch containing the build output to be served with GitHub Pages. In the following tutorial, they will be referred to as **"source"** and **"deployment"**, respectively. + +Each GitHub repository is associated with a GitHub Pages service. If the deployment repository is called `my-org/my-project` (where `my-org` is the organization name or username), the deployed site will appear at `https://my-org.github.io/my-project/`. If the deployment repository is called `my-org/my-org.github.io` (the _organization GitHub Pages repo_), the site will appear at `https://my-org.github.io/`. + +:::info + +In case you want to use your custom domain for GitHub Pages, create a `CNAME` file in the `static` directory. Anything within the `static` directory will be copied to the root of the `build` directory for deployment. When using a custom domain, you should be able to move back from `baseUrl: '/projectName/'` to `baseUrl: '/'`, and also set your `url` to your custom domain. + +You may refer to GitHub Pages' documentation [User, Organization, and Project Pages](https://help.github.com/en/articles/user-organization-and-project-pages) for more details. + +::: + +GitHub Pages picks up deploy-ready files (the output from `docusaurus build`) from the default branch (`master` / `main`, usually) or the `gh-pages` branch, and either from the root or the `/docs` folder. You can configure that through `Settings > Pages` in your repository. This branch will be called the "deployment branch". + +We provide a `docusaurus deploy` command that helps you deploy your site from the source branch to the deployment branch in one command: clone, build, and commit. + +### `docusaurus.config.js` settings {#docusaurusconfigjs-settings} + +First, modify your `docusaurus.config.js` and add the following params: + +| Name | Description | +| --- | --- | +| `organizationName` | The GitHub user or organization that owns the deployment repository. | +| `projectName` | The name of the deployment repository. | +| `deploymentBranch` | The name of the deployment branch. It defaults to `'gh-pages'` for non-organization GitHub Pages repos (`projectName` not ending in `.github.io`). Otherwise, it needs to be explicit as a config field or environment variable. | + +These fields also have their environment variable counterparts which have a higher priority: `ORGANIZATION_NAME`, `PROJECT_NAME`, and `DEPLOYMENT_BRANCH`. + +:::warning + +GitHub Pages adds a trailing slash to Docusaurus URLs by default. It is recommended to set a `trailingSlash` config (`true` or `false`, not `undefined`). + +::: + +Example: + +```js title="docusaurus.config.js" +export default { + // ... + url: 'https://endiliey.github.io', // Your website URL + baseUrl: '/', + // highlight-start + projectName: 'endiliey.github.io', + organizationName: 'endiliey', + trailingSlash: false, + // highlight-end + // ... +}; +``` + +:::warning + +By default, GitHub Pages runs published files through [Jekyll](https://jekyllrb.com/). Since Jekyll will discard any files that begin with `_`, it is recommended that you disable Jekyll by adding an empty file named `.nojekyll` file to your `static` directory. + +::: + +### Environment settings {#environment-settings} + +| Name | Description | +| --- | --- | +| `USE_SSH` | Set to `true` to use SSH instead of the default HTTPS for the connection to the GitHub repo. If the source repo URL is an SSH URL (e.g. `git@github.com:facebook/docusaurus.git`), `USE_SSH` is inferred to be `true`. | +| `GIT_USER` | The username for a GitHub account that **has push access to the deployment repo**. For your own repositories, this will usually be your GitHub username. Required if not using SSH, and ignored otherwise. | +| `GIT_PASS` | Personal access token of the git user (specified by `GIT_USER`), to facilitate non-interactive deployment (e.g. continuous deployment) | +| `CURRENT_BRANCH` | The source branch. Usually, the branch will be `main` or `master`, but it could be any branch except for `gh-pages`. If nothing is set for this variable, then the current branch from which `docusaurus deploy` is invoked will be used. | +| `GIT_USER_NAME` | The `git config user.name` value to use when pushing to the deployment repo | +| `GIT_USER_EMAIL` | The `git config user.email` value to use when pushing to the deployment repo | + +GitHub enterprise installations should work in the same manner as github.com; you only need to set the organization's GitHub Enterprise host as an environment variable: + +| Name | Description | +| ------------- | ----------------------------------------------- | +| `GITHUB_HOST` | The domain name of your GitHub enterprise site. | +| `GITHUB_PORT` | The port of your GitHub enterprise site. | + +### Deploy {#deploy} + +Finally, to deploy your site to GitHub Pages, run: + +```mdx-code-block +<Tabs> +<TabItem value="bash" label="Bash"> +``` + +```bash +GIT_USER=<GITHUB_USERNAME> yarn deploy +``` + +```mdx-code-block +</TabItem> +<TabItem value="windows" label="Windows"> +``` + +```batch +cmd /C "set "GIT_USER=<GITHUB_USERNAME>" && yarn deploy" +``` + +```mdx-code-block +</TabItem> +<TabItem value="powershell" label="PowerShell"> +``` + +```powershell +cmd /C 'set "GIT_USER=<GITHUB_USERNAME>" && yarn deploy' +``` + +```mdx-code-block +</TabItem> +</Tabs> +``` + +:::warning + +Beginning in August 2021, GitHub requires every command-line sign-in to use the **personal access token** instead of the password. When GitHub prompts for your password, enter the PAT instead. See the [GitHub documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) for more information. + +Alternatively, you can use SSH (`USE_SSH=true`) to log in. + +::: + +### Triggering deployment with GitHub Actions {#triggering-deployment-with-github-actions} + +[GitHub Actions](https://help.github.com/en/actions) allow you to automate, customize, and execute your software development workflows right in your repository. + +The workflow examples below assume your website source resides in the `main` branch of your repository (the _source branch_ is `main`), and your [publishing source](https://help.github.com/en/github/working-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site) is configured for [publishing with a custom GitHub Actions Workflow](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow). + +Our goal is that: + +1. When a new pull request is made to `main`, there's an action that ensures the site builds successfully, without actually deploying. This job will be called `test-deploy`. +2. When a pull request is merged to the `main` branch or someone pushes to the `main` branch directly, it will be built and deployed to GitHub Pages. This job will be called `deploy`. + +Here are two approaches to deploying your docs with GitHub Actions. Based on the location of your deployment repository, choose the relevant tab below: + +- Source repo and deployment repo are the **same** repository. +- The deployment repo is a **remote** repository, different from the source. Instructions for this scenario assume [publishing source](https://help.github.com/en/github/working-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site) is the `gh-pages` branch. + +```mdx-code-block +<Tabs> +<TabItem value="same" label="Same"> +``` + +While you can have both jobs defined in the same workflow file, the original `deploy` workflow will always be listed as skipped in the PR check suite status, which is not indicative of the actual status and provides no value to the review process. We therefore propose to manage them as separate workflows instead. + +<details> +<summary>GitHub action files</summary> + +Add these two workflow files: + +:::warning Tweak the parameters for your setup + +If your Docusaurus project is not at the root of your repo, you may need to configure a [default working directory](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-set-the-default-shell-and-working-directory), and adjust the paths accordingly. + +::: + +<Tabs> + <TabItem value="npm" label="npm"> + +```yml title=".github/workflows/deploy.yml" +name: Deploy to GitHub Pages + +on: + push: + branches: + - main + # Review gh actions docs if you want to further define triggers, paths, etc + # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on + +jobs: + build: + name: Build Docusaurus + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: npm + + - name: Install dependencies + run: npm ci + - name: Build website + run: npm run build + + - name: Upload Build Artifact + uses: actions/upload-pages-artifact@v3 + with: + path: build + + deploy: + name: Deploy to GitHub Pages + needs: build + + # Grant GITHUB_TOKEN the permissions required to make a Pages deployment + permissions: + pages: write # to deploy to Pages + id-token: write # to verify the deployment originates from an appropriate source + + # Deploy to the github-pages environment + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + runs-on: ubuntu-latest + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 +``` + +```yml title=".github/workflows/test-deploy.yml" +name: Test deployment + +on: + pull_request: + branches: + - main + # Review gh actions docs if you want to further define triggers, paths, etc + # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on + +jobs: + test-deploy: + name: Test deployment + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: npm + + - name: Install dependencies + run: npm ci + - name: Test build website + run: npm run build +``` + + </TabItem> + <TabItem value="yarn" label="Yarn"> + +```yml title=".github/workflows/deploy.yml" +name: Deploy to GitHub Pages + +on: + push: + branches: + - main + # Review gh actions docs if you want to further define triggers, paths, etc + # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on + +jobs: + build: + name: Build Docusaurus + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: yarn + + - name: Install dependencies + run: yarn install --frozen-lockfile + - name: Build website + run: yarn build + + - name: Upload Build Artifact + uses: actions/upload-pages-artifact@v3 + with: + path: build + + deploy: + name: Deploy to GitHub Pages + needs: build + + # Grant GITHUB_TOKEN the permissions required to make a Pages deployment + permissions: + pages: write # to deploy to Pages + id-token: write # to verify the deployment originates from an appropriate source + + # Deploy to the github-pages environment + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + runs-on: ubuntu-latest + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 +``` + +```yml title=".github/workflows/test-deploy.yml" +name: Test deployment + +on: + pull_request: + branches: + - main + # Review gh actions docs if you want to further define triggers, paths, etc + # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on + +jobs: + test-deploy: + name: Test deployment + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: yarn + + - name: Install dependencies + run: yarn install --frozen-lockfile + - name: Test build website + run: yarn build +``` + + </TabItem> +</Tabs> + +</details> + +```mdx-code-block +</TabItem> +<TabItem value="remote" label="Remote"> +``` + +A cross-repo publish is more difficult to set up because you need to push to another repo with permission checks. We will be using SSH to do the authentication. + +1. Generate a new [SSH key](https://help.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent). Since this SSH key will be used in CI, make sure to not enter any passphrase. +2. By default, your public key should have been created in `~/.ssh/id_rsa.pub`; otherwise, use the name you've provided in the previous step to add your key to [GitHub deploy keys](https://developer.github.com/v3/guides/managing-deploy-keys/). +3. Copy the key to clipboard with `pbcopy < ~/.ssh/id_rsa.pub` and paste it as a [deploy key](https://developer.github.com/v3/guides/managing-deploy-keys/#deploy-keys) in the deployment repository. Copy the file content if the command line doesn't work for you. Check the box for `Allow write access` before saving your deployment key. +4. You'll need your private key as a [GitHub secret](https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets) to allow Docusaurus to run the deployment for you. +5. Copy your private key with `pbcopy < ~/.ssh/id_rsa` and paste a GitHub secret with the name `GH_PAGES_DEPLOY` on your source repository. Copy the file content if the command line doesn't work for you. Save your secret. +6. Create your [documentation workflow](https://docs.github.com/en/actions/use-cases-and-examples/creating-an-example-workflow) in the `.github/workflows/` directory. In this example it's the `deploy.yml` file. + +At this point, you should have: + +- the source repo with the GitHub workflow set with the private SSH key as the GitHub Secret, and +- your deployment repo set with the public SSH key in GitHub Deploy Keys. + +<details> + +<summary>GitHub action file</summary> + +:::warning + +Please make sure that you replace `actions@github.com` with your GitHub email and `gh-actions` with your name. + +This file assumes you are using Yarn. If you use npm, change `cache: yarn`, `yarn install --frozen-lockfile`, `yarn build` to `cache: npm`, `npm ci`, `npm run build` accordingly. + +::: + +```yml title=".github/workflows/deploy.yml" +name: Deploy to GitHub Pages + +on: + pull_request: + branches: [main] + push: + branches: [main] + +permissions: + contents: write + +jobs: + test-deploy: + if: github.event_name != 'push' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: yarn + - name: Install dependencies + run: yarn install --frozen-lockfile + - name: Test build website + run: yarn build + deploy: + if: github.event_name != 'pull_request' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: yarn + - uses: webfactory/ssh-agent@v0.5.0 + with: + ssh-private-key: ${{ secrets.GH_PAGES_DEPLOY }} + - name: Deploy to GitHub Pages + env: + USE_SSH: true + run: | + git config --global user.email "actions@github.com" + git config --global user.name "gh-actions" + yarn install --frozen-lockfile + yarn deploy +``` + +</details> + +```mdx-code-block +</TabItem> +</Tabs> +``` + +<details> + +<summary>Site not deployed properly?</summary> + +After pushing to main, if you don't see your site published at the desired location (for example, it says "There isn't a GitHub Pages site here", or it's showing your repo's README.md file), try the following: + +- Wait about three minutes and refresh. It may take a few minutes for GitHub pages to pick up the new files. +- Check your repo's landing page for a little green tick next to the last commit's title, indicating the CI has passed. If you see a cross, it means the build or deployment failed, and you should check the log for more debugging information. +- Click on the tick and make sure you see a "Deploy to GitHub Pages" workflow. Names like "pages build and deployment / deploy" are GitHub's default workflows, indicating your custom deployment workflow failed to be triggered at all. Make sure the YAML files are placed under the `.github/workflows` folder, and that the trigger condition is set correctly (e.g., if your default branch is "master" instead of "main", you need to change the `on.push` property). +- Under your repo's Settings > Pages, make sure the "Source" (which is the source for the _deployment_ files, not "source" as in our terminology) is set to "gh-pages" + "/ (root)", since we are using `gh-pages` as the deployment branch. + +If you are using a custom domain: + +- Verify that you have the correct DNS records set up if you're using a custom domain. See [GitHub pages documentation on configuring custom domains](https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/about-custom-domains-and-github-pages). Also, please be aware that it may take up to 24 hours for DNS changes to propagate through the internet. + +</details> + +### Triggering deployment with Travis CI {#triggering-deployment-with-travis-ci} + +Continuous integration (CI) services are typically used to perform routine tasks whenever new commits are checked in to source control. These tasks can be any combination of running unit tests and integration tests, automating builds, publishing packages to npm, and deploying changes to your website. All you need to do to automate the deployment of your website is to invoke the `yarn deploy` script whenever your website is updated. The following section covers how to do just that using [Travis CI](https://travis-ci.com/), a popular continuous integration service provider. + +1. Go to https://github.com/settings/tokens and generate a new [personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/). When creating the token, grant it the `repo` scope so that it has the permissions it needs. +2. Using your GitHub account, [add the Travis CI app](https://github.com/marketplace/travis-ci) to the repository you want to activate. +3. Open your Travis CI dashboard. The URL looks like `https://travis-ci.com/USERNAME/REPO`, and navigate to the `More options > Setting > Environment Variables` section of your repository. +4. Create a new environment variable named `GH_TOKEN` with your newly generated token as its value, then `GH_EMAIL` (your email address) and `GH_NAME` (your GitHub username). +5. Create a `.travis.yml` on the root of your repository with the following: + +```yml title=".travis.yml" +language: node_js +node_js: + - 18 +branches: + only: + - main +cache: + yarn: true +script: + - git config --global user.name "${GH_NAME}" + - git config --global user.email "${GH_EMAIL}" + - echo "machine github.com login ${GH_NAME} password ${GH_TOKEN}" > ~/.netrc + - yarn install + - GIT_USER="${GH_NAME}" yarn deploy +``` + +Now, whenever a new commit lands in `main`, Travis CI will run your suite of tests and if everything passes, your website will be deployed via the `yarn deploy` script. + +### Triggering deployment with Buddy {#triggering-deployment-with-buddy} + +[Buddy](https://buddy.works/) is an easy-to-use CI/CD tool that allows you to automate the deployment of your portal to different environments, including GitHub Pages. + +Follow these steps to create a pipeline that automatically deploys a new version of your website whenever you push changes to the selected branch of your project: + +1. Go to https://github.com/settings/tokens and generate a new [personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/). When creating the token, grant it the `repo` scope so that it has the permissions it needs. +2. Sign in to your Buddy account and create a new project. +3. Choose GitHub as your git hosting provider and select the repository with the code of your website. +4. Using the left navigation panel, switch to the `Pipelines` view. +5. Create a new pipeline. Define its name, set the trigger mode to `On push`, and select the branch that triggers the pipeline execution. +6. Add a `Node.js` action. +7. Add these commands in the action's terminal: + +```bash +GIT_USER=<GH_PERSONAL_ACCESS_TOKEN> +git config --global user.email "<YOUR_GH_EMAIL>" +git config --global user.name "<YOUR_GH_USERNAME>" +yarn deploy +``` + +After creating this simple pipeline, each new commit pushed to the branch you selected deploys your website to GitHub Pages using `yarn deploy`. Read [this guide](https://buddy.works/guides/react-docusaurus) to learn more about setting up a CI/CD pipeline for Docusaurus. + +### Using Azure Pipelines {#using-azure-pipelines} + +1. Sign Up at [Azure Pipelines](https://azure.microsoft.com/en-us/services/devops/pipelines/) if you haven't already. +2. Create an organization. Within the organization, create a project and connect your repository from GitHub. +3. Go to https://github.com/settings/tokens and generate a new [personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) with the `repo` scope. +4. In the project page (which looks like `https://dev.azure.com/ORG_NAME/REPO_NAME/_build`), create a new pipeline with the following text. Also, click on edit and add a new environment variable named `GH_TOKEN` with your newly generated token as its value, then `GH_EMAIL` (your email address) and `GH_NAME` (your GitHub username). Make sure to mark them as secret. Alternatively, you can also add a file named `azure-pipelines.yml` at your repository root. + +```yml title="azure-pipelines.yml" +trigger: + - main + +pool: + vmImage: ubuntu-latest + +steps: + - checkout: self + persistCredentials: true + + - task: NodeTool@0 + inputs: + versionSpec: '18' + displayName: Install Node.js + + - script: | + git config --global user.name "${GH_NAME}" + git config --global user.email "${GH_EMAIL}" + git checkout -b main + echo "machine github.com login ${GH_NAME} password ${GH_TOKEN}" > ~/.netrc + yarn install + GIT_USER="${GH_NAME}" yarn deploy + env: + GH_NAME: $(GH_NAME) + GH_EMAIL: $(GH_EMAIL) + GH_TOKEN: $(GH_TOKEN) + displayName: Install and build +``` + +### Using Drone {#using-drone} + +1. Create a new SSH key that will be the [deploy key](https://docs.github.com/en/free-pro-team@latest/developers/overview/managing-deploy-keys#deploy-keys) for your project. +2. Name your private and public keys to be specific and so that it does not overwrite your other [SSH keys](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent). +3. Go to `https://github.com/USERNAME/REPO/settings/keys` and add a new deploy key by pasting in the public key you just generated. +4. Open your Drone.io dashboard and log in. The URL looks like `https://cloud.drone.io/USERNAME/REPO`. +5. Click on the repository, click on activate repository, and add a secret called `git_deploy_private_key` with your private key value that you just generated. +6. Create a `.drone.yml` on the root of your repository with the below text. + +```yml title=".drone.yml" +kind: pipeline +type: docker +trigger: + event: + - tag +- name: Website + image: node + commands: + - mkdir -p $HOME/.ssh + - ssh-keyscan -t rsa github.com >> $HOME/.ssh/known_hosts + - echo "$GITHUB_PRIVATE_KEY" > "$HOME/.ssh/id_rsa" + - chmod 0600 $HOME/.ssh/id_rsa + - cd website + - yarn install + - yarn deploy + environment: + USE_SSH: true + GITHUB_PRIVATE_KEY: + from_secret: git_deploy_private_key +``` + +Now, whenever you push a new tag to GitHub, this trigger will start the drone CI job to publish your website. + +## Deploying to Flightcontrol {#deploying-to-flightcontrol} + +[Flightcontrol](https://www.flightcontrol.dev/?ref=docusaurus) is a service that automatically builds and deploys your web apps to AWS Fargate directly from your Git repository. It gives you full access to inspect and make infrastructure changes without the limitations of a traditional PaaS. + +Get started by following [Flightcontrol's step-by-step Docusaurus guide](https://www.flightcontrol.dev/docs/reference/examples/docusaurus/?ref=docusaurus). + +## Deploying to Koyeb {#deploying-to-koyeb} + +[Koyeb](https://www.koyeb.com) is a developer-friendly serverless platform to deploy apps globally. The platform lets you seamlessly run Docker containers, web apps, and APIs with git-based deployment, native autoscaling, a global edge network, and built-in service mesh and discovery. Check out the [Koyeb's Docusaurus deployment guide](https://www.koyeb.com/tutorials/deploy-docusaurus-on-koyeb) to get started. + +## Deploying to Render {#deploying-to-render} + +[Render](https://render.com) offers [free static site hosting](https://render.com/docs/static-sites) with fully managed SSL, custom domains, a global CDN, and continuous auto-deploy from your Git repo. Get started in just a few minutes by following [Render's guide to deploying Docusaurus](https://render.com/docs/deploy-docusaurus). + +## Deploying to Qovery {#deploying-to-qovery} + +[Qovery](https://www.qovery.com) is a fully-managed cloud platform that runs on your AWS, Digital Ocean, and Scaleway account where you can host static sites, backend APIs, databases, cron jobs, and all your other apps in one place. + +1. Create a Qovery account. Visit the [Qovery dashboard](https://console.qovery.com) to create an account if you don't already have one. +2. Create a project. + - Click on **Create project** and give a name to your project. + - Click on **Next**. +3. Create a new environment. + - Click on **Create environment** and give a name (e.g. staging, production). +4. Add an application. + - Click on **Create an application**, give a name and select your GitHub or GitLab repository where your Docusaurus app is located. + - Define the main branch name and the root application path. + - Click on **Create**. After the application is created: + - Navigate to your application **Settings** + - Select **Port** + - Add port used by your Docusaurus application +5. Deploy + - All you have to do now is to navigate to your application and click on **Deploy**. + +![Deploy the app](https://hub.qovery.com/img/heroku/heroku-1.png) + +That's it. Watch the status and wait till the app is deployed. To open the application in your browser, click on **Action** and **Open** in your application overview. + +## Deploying to Hostman {#deploying-to-hostman} + +[Hostman](https://hostman.com/) allows you to host static websites for free. Hostman automates everything, you just need to connect your repository and follow these easy steps: + +1. Create a service. + + - To deploy a Docusaurus static website, click **Create** in the top-left corner of your [Dashboard](https://dashboard.hostman.com/) and choose **Front-end app or static website**. + +2. Select the project to deploy. + + - If you are logged in to Hostman with your GitHub, GitLab, or Bitbucket account, you will see the repository with your projects, including the private ones. + + - Choose the project you want to deploy. It must contain the directory with the project's files (e.g. `website`). + + - To access a different repository, click **Connect another repository**. + + - If you didn't use your Git account credentials to log in, you'll be able to access the necessary account now, and then select the project. + +3. Configure the build settings. + + - Next, the **Website customization** window will appear. Choose the **Static website** option from the list of frameworks. + + - The **Directory with app** points at the directory that will contain the project's files after the build. If you selected the repository with the contents of the website (or `my_website`) directory during Step 2, you can leave it empty. + + - The standard build command for Docusaurus is: + + ```bash npm2yarn + npm run build + ``` + + - You can modify the build command if needed. You can enter multiple commands separated by `&&`. + +4. Deploy. + + - Click **Deploy** to start the build process. + + - Once it starts, you will enter the deployment log. If there are any issues with the code, you will get warning or error messages in the log specifying the cause of the problem. Usually, the log contains all the debugging data you'll need. + + - When the deployment is complete, you will receive an email notification and also see a log entry. All done! Your project is up and ready. + +## Deploying to Surge {#deploying-to-surge} + +Surge is a [static web hosting platform](https://surge.sh/help/getting-started-with-surge) that you can use to deploy your Docusaurus project from the command line in seconds. Deploying your project to Surge is easy and free (including custom domains and SSL certs). + +Deploy your app in a matter of seconds using Surge with the following steps: + +1. First, install Surge using npm by running the following command: + ```bash npm2yarn + npm install -g surge + ``` +2. To build the static files of your site for production in the root directory of your project, run: + ```bash npm2yarn + npm run build + ``` +3. Then, run this command inside the root directory of your project: + ```bash + surge build/ + ``` + +First-time users of Surge would be prompted to create an account from the command line (which happens only once). + +Confirm that the site you want to publish is in the `build` directory. A randomly generated subdomain `*.surge.sh subdomain` is always given (which can be edited). + +### Using your domain {#using-your-domain} + +If you have a domain name you can deploy your site using the command: + +```bash +surge build/ your-domain.com +``` + +Your site is now deployed for free at `subdomain.surge.sh` or `your-domain.com` depending on the method you chose. + +### Setting up CNAME file {#setting-up-cname-file} + +Store your domain in a CNAME file for future deployments with the following command: + +```bash +echo subdomain.surge.sh > CNAME +``` + +You can deploy any other changes in the future with the command `surge`. + +## Deploying to Stormkit {#deploying-to-stormkit} + +You can deploy your Docusaurus project to [Stormkit](https://www.stormkit.io), a deployment platform for static websites, single-page applications (SPAs), and serverless functions. For detailed instructions, refer to this [guide](https://www.stormkit.io/blog/how-to-deploy-docusarous). + +## Deploying to QuantCDN {#deploying-to-quantcdn} + +1. Install [Quant CLI](https://docs.quantcdn.io/docs/cli/get-started) +2. Create a QuantCDN account by [signing up](https://dashboard.quantcdn.io/register) +3. Initialize your project with `quant init` and fill in your credentials: + ```bash + quant init + ``` +4. Deploy your site. + ```bash + quant deploy + ``` + +See [docs](https://docs.quantcdn.io/docs/cli/continuous-integration) and [blog](https://www.quantcdn.io/blog) for more examples and use cases for deploying to QuantCDN. + +## Deploying to Cloudflare Pages {#deploying-to-cloudflare-pages} + +[Cloudflare Pages](https://pages.cloudflare.com/) is a Jamstack platform for frontend developers to collaborate and deploy websites. Get started within a few minutes by following [this page](https://developers.cloudflare.com/pages/framework-guides/deploy-a-docusaurus-site/). + +## Deploying to Azure Static Web Apps {#deploying-to-azure-static-web-apps} + +[Azure Static Web Apps](https://docs.microsoft.com/en-us/azure/static-web-apps/overview) is a service that automatically builds and deploys full-stack web apps to Azure directly from the code repository, simplifying the developer experience for CI/CD. Static Web Apps separates the web application's static assets from its dynamic (API) endpoints. Static assets are served from globally-distributed content servers, making it faster for clients to retrieve files using servers nearby. Dynamic APIs are scaled with serverless architectures using an event-driven functions-based approach that is more cost-effective and scales on demand. Get started in a few minutes by following [this step-by-step guide](https://dev.to/azure/11-share-content-with-docusaurus-azure-static-web-apps-30hc). + +## Deploying to Kinsta {#deploying-to-kinsta} + +[Kinsta Static Site Hosting](https://kinsta.com/static-site-hosting) lets you deploy up to 100 static sites for free, custom domains with SSL, 100 GB monthly bandwidth, and 260+ Cloudflare CDN locations. + +Get started in just a few clicks by following our [Docusaurus on Kinsta](https://kinsta.com/docs/docusaurus-example/) article. diff --git a/website/versioned_docs/version-3.9.0/docusaurus-core.mdx b/website/versioned_docs/version-3.9.0/docusaurus-core.mdx new file mode 100644 index 0000000000..63f0f4ddd7 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/docusaurus-core.mdx @@ -0,0 +1,770 @@ +--- +sidebar_label: Client API +--- + +# Docusaurus Client API + +Docusaurus provides some APIs on the clients that can be helpful to you when building your site. + +## Components {#components} + +### `<ErrorBoundary />` {#errorboundary} + +This component creates a [React error boundary](https://reactjs.org/docs/error-boundaries.html). + +Use it to wrap components that might throw, and display a fallback when that happens instead of crashing the whole app. + +```jsx +import React from 'react'; +import ErrorBoundary from '@docusaurus/ErrorBoundary'; + +const SafeComponent = () => ( + <ErrorBoundary + fallback={({error, tryAgain}) => ( + <div> + <p>This component crashed because of error: {error.message}.</p> + <button onClick={tryAgain}>Try Again!</button> + </div> + )}> + <SomeDangerousComponentThatMayThrow /> + </ErrorBoundary> +); +``` + +```mdx-code-block +import ErrorBoundaryTestButton from '@site/src/components/ErrorBoundaryTestButton' +``` + +:::tip + +To see it in action, click here: <ErrorBoundaryTestButton/> + +::: + +:::info + +Docusaurus uses this component to catch errors within the theme's layout, and also within the entire app. + +::: + +:::note + +This component doesn't catch build-time errors and only protects against client-side render errors that can happen when using stateful React components. + +::: + +#### Props {#errorboundary-props} + +- `fallback`: an optional render callback returning a JSX element. It will receive an object with 2 attributes: `error`, the error that was caught, and `tryAgain`, a function (`() => void`) callback to reset the error in the component and try rendering it again. If not present, `@theme/Error` will be rendered instead. `@theme/Error` is used for the error boundaries wrapping the site, above the layout. + +:::warning + +The `fallback` prop is a callback, and **not a React functional component**. You can't use React hooks inside this callback. + +::: + +### `<Head/>` {#head} + +This reusable React component will manage all of your changes to the document head. It takes plain HTML tags and outputs plain HTML tags and is beginner-friendly. It is a wrapper around [React Helmet](https://github.com/nfl/react-helmet). + +Usage Example: + +```jsx +import React from 'react'; +// highlight-next-line +import Head from '@docusaurus/Head'; + +const MySEO = () => ( + // highlight-start + <Head> + <meta property="og:description" content="My custom description" /> + <meta charSet="utf-8" /> + <title>My Title + + + // highlight-end +); +``` + +Nested or latter components will override duplicate usages: + +```jsx + + {/* highlight-start */} + + My Title + + + {/* highlight-end */} + + {/* highlight-start */} + + Nested Title + + + {/* highlight-end */} + + +``` + +Outputs: + +```html + + Nested Title + + +``` + +### `` {#link} + +This component enables linking to internal pages as well as a powerful performance feature called preloading. Preloading is used to prefetch resources so that the resources are fetched by the time the user navigates with this component. We use an `IntersectionObserver` to fetch a low-priority request when the `` is in the viewport and then use an `onMouseOver` event to trigger a high-priority request when it is likely that a user will navigate to the requested resource. + +The component is a wrapper around react-router’s `` component that adds useful enhancements specific to Docusaurus. All props are passed through to react-router’s `` component. + +External links also work, and automatically have these props: `target="_blank" rel="noopener noreferrer"`. + +```jsx +import React from 'react'; +// highlight-next-line +import Link from '@docusaurus/Link'; + +const Page = () => ( +
    +

    + {/* highlight-next-line */} + Check out my blog! +

    +

    + {/* highlight-next-line */} + Follow me on X! +

    +
    +); +``` + +#### `to`: string {#to-string} + +The target location to navigate to. Example: `/docs/introduction`. + +```jsx + +``` + +:::tip + +Prefer this component to vanilla `` tags because Docusaurus does a lot of optimizations (e.g. broken path detection, prefetching, applying base URL...) if you use ``. + +::: + +### `` {#redirect} + +Rendering a `` will navigate to a new location. The new location will override the current location in the history stack like server-side redirects (HTTP 3xx) do. You can refer to [React Router's Redirect documentation](https://reacttraining.com/react-router/web/api/Redirect) for more info on available props. + +Example usage: + +```jsx +import React from 'react'; +// highlight-next-line +import {Redirect} from '@docusaurus/router'; + +const Home = () => { + // highlight-next-line + return ; +}; +``` + +:::note + +`@docusaurus/router` implements [React Router](https://reacttraining.com/react-router/web/guides/quick-start) and supports its features. + +::: + +### `` {#browseronly} + +The `` component permits to render React components only in the browser after the React app has hydrated. + +:::tip + +Use it for integrating with code that can't run in Node.js, because the `window` or `document` objects are being accessed. + +::: + +#### Props {#browseronly-props} + +- `children`: render function prop returning browser-only JSX. Will not be executed in Node.js +- `fallback` (optional): JSX to render on the server (Node.js) and until React hydration completes. + +#### Example with code {#browseronly-example-code} + +```jsx +// highlight-start +import BrowserOnly from '@docusaurus/BrowserOnly'; +// highlight-end + +const MyComponent = () => { + return ( + // highlight-start + + {() => page url = {window.location.href}} + + // highlight-end + ); +}; +``` + +#### Example with a library {#browseronly-example-library} + +```jsx +// highlight-start +import BrowserOnly from '@docusaurus/BrowserOnly'; +// highlight-end + +const MyComponent = (props) => { + return ( + // highlight-start + Loading...
    }> + {() => { + const LibComponent = require('some-lib').LibComponent; + return ; + }} + + // highlight-end + ); +}; +``` + +### `` {#interpolate} + +A simple interpolation component for text containing dynamic placeholders. + +The placeholders will be replaced with the provided dynamic values and JSX elements of your choice (strings, links, styled elements...). + +#### Props {#interpolate-props} + +- `children`: text containing interpolation placeholders like `{placeholderName}` +- `values`: object containing interpolation placeholder values + +```jsx +import React from 'react'; +import Link from '@docusaurus/Link'; +import Interpolate from '@docusaurus/Interpolate'; + +export default function VisitMyWebsiteMessage() { + return ( + // highlight-start + + website + + ), + }}> + {'Hello, {firstName}! How are you? Take a look at my {website}'} + + // highlight-end + ); +} +``` + +### `` {#translate} + +When [localizing your site](./i18n/i18n-introduction.mdx), the `` component will allow providing **translation support to React components**, such as your homepage. The `` component supports [interpolation](#interpolate). + +The translation strings will statically extracted from your code with the [`docusaurus write-translations`](./cli.mdx#docusaurus-write-translations-sitedir) CLI and a `code.json` translation file will be created in `website/i18n/[locale]`. + +:::note + +The `` props **must be hardcoded strings**. + +Apart from the `values` prop used for interpolation, it is **not possible to use variables**, or the static extraction wouldn't work. + +::: + +#### Props {#translate-props} + +- `children`: untranslated string in the default site locale (can contain [interpolation placeholders](#interpolate)) +- `id`: optional value to be used as the key in JSON translation files +- `description`: optional text to help the translator +- `values`: optional object containing interpolation placeholder values + +#### Example {#example} + +```jsx title="src/pages/index.js" +import React from 'react'; +import Layout from '@theme/Layout'; + +// highlight-start +import Translate from '@docusaurus/Translate'; +// highlight-end + +export default function Home() { + return ( + +

    + {/* highlight-start */} + + Welcome to my website + + {/* highlight-end */} +

    +
    + {/* highlight-start */} + + {'Welcome, {firstName}! How are you?'} + + {/* highlight-end */} +
    +
    + ); +} +``` + +:::note + +You can even omit the children prop and specify a translation string in your `code.json` file manually after running the `docusaurus write-translations` CLI command. + +```jsx + +``` + +::: + +:::info + +The `` component supports interpolation. You can also implement [string pluralization](https://github.com/facebook/docusaurus/pull/i18n/i18n-tutorial.mdx#pluralization) through some custom code and the [`translate` imperative API](#translate-imperative). + +::: + +## Hooks {#hooks} + +### `useDocusaurusContext` {#useDocusaurusContext} + +React hook to access Docusaurus Context. The context contains the `siteConfig` object from [docusaurus.config.js](api/docusaurus.config.js.mdx) and some additional site metadata. + +```ts +type PluginVersionInformation = + | {readonly type: 'package'; readonly version?: string} + | {readonly type: 'project'} + | {readonly type: 'local'} + | {readonly type: 'synthetic'}; + +type SiteMetadata = { + readonly docusaurusVersion: string; + readonly siteVersion?: string; + readonly pluginVersions: Record; +}; + +type I18nLocaleConfig = { + label: string; + direction: string; +}; + +type I18n = { + defaultLocale: string; + locales: [string, ...string[]]; + currentLocale: string; + localeConfigs: Record; +}; + +type DocusaurusContext = { + siteConfig: DocusaurusConfig; + siteMetadata: SiteMetadata; + globalData: Record; + i18n: I18n; + codeTranslations: Record; +}; +``` + +Usage example: + +```jsx +import React from 'react'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; + +const MyComponent = () => { + // highlight-next-line + const {siteConfig, siteMetadata} = useDocusaurusContext(); + return ( +
    + {/* highlight-start */} +

    {siteConfig.title}

    +
    {siteMetadata.siteVersion}
    +
    {siteMetadata.docusaurusVersion}
    + {/* highlight-end */} +
    + ); +}; +``` + +:::note + +The `siteConfig` object only contains **serializable values** (values that are preserved after `JSON.stringify()`). Functions, regexes, etc. would be lost on the client side. + +::: + +### `useIsBrowser` {#useIsBrowser} + +Returns `true` when the React app has successfully hydrated in the browser. + +:::warning + +Use this hook instead of `typeof windows !== 'undefined'` in React rendering logic. + +The first client-side render output (in the browser) **must be exactly the same** as the server-side render output (Node.js). Not following this rule can lead to unexpected hydration behaviors, as described in [The Perils of Rehydration](https://www.joshwcomeau.com/react/the-perils-of-rehydration/). + +::: + +Usage example: + +```jsx +import React from 'react'; +import useIsBrowser from '@docusaurus/useIsBrowser'; + +const MyComponent = () => { + // highlight-start + const isBrowser = useIsBrowser(); + // highlight-end + return
    {isBrowser ? 'Client' : 'Server'}
    ; +}; +``` + +### `useBaseUrl` {#useBaseUrl} + +React hook to prepend your site `baseUrl` to a string. + +:::warning + +**Don't use it for regular links!** + +The `/baseUrl/` prefix is automatically added to all **absolute paths** by default: + +- Markdown: `[link](/my/path)` will link to `/baseUrl/my/path` +- React: `link` will link to `/baseUrl/my/path` + +::: + +#### Options {#options} + +```ts +type BaseUrlOptions = { + forcePrependBaseUrl: boolean; + absolute: boolean; +}; +``` + +#### Example usage: {#example-usage} + +```jsx +import React from 'react'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + +const SomeImage = () => { + // highlight-start + const imgSrc = useBaseUrl('/img/myImage.png'); + // highlight-end + return ; +}; +``` + +:::tip + +In most cases, you don't need `useBaseUrl`. + +Prefer a `require()` call for [assets](./guides/markdown-features/markdown-features-assets.mdx): + +```jsx + +``` + +::: + +### `useBaseUrlUtils` {#useBaseUrlUtils} + +Sometimes `useBaseUrl` is not good enough. This hook return additional utils related to your site's base URL. + +- `withBaseUrl`: useful if you need to add base URLs to multiple URLs at once. + +```jsx +import React from 'react'; +import {useBaseUrlUtils} from '@docusaurus/useBaseUrl'; + +const Component = () => { + const urls = ['/a', '/b']; + // highlight-start + const {withBaseUrl} = useBaseUrlUtils(); + const urlsWithBaseUrl = urls.map(withBaseUrl); + // highlight-end + return
    {/* ... */}
    ; +}; +``` + +### `useGlobalData` {#useGlobalData} + +React hook to access Docusaurus global data created by all the plugins. + +Global data is namespaced by plugin name then by plugin ID. + +:::info + +Plugin ID is only useful when a plugin is used multiple times on the same site. Each plugin instance is able to create its own global data. + +::: + +```ts +type GlobalData = Record< + PluginName, + Record< + PluginId, // "default" by default + any // plugin-specific data + > +>; +``` + +Usage example: + +```jsx +import React from 'react'; +// highlight-next-line +import useGlobalData from '@docusaurus/useGlobalData'; + +const MyComponent = () => { + // highlight-start + const globalData = useGlobalData(); + const myPluginData = globalData['my-plugin']['default']; + return
    {myPluginData.someAttribute}
    ; + // highlight-end +}; +``` + +:::tip + +Inspect your site's global data at `.docusaurus/globalData.json` + +::: + +### `usePluginData` {#usePluginData} + +Access global data created by a specific plugin instance. + +This is the most convenient hook to access plugin global data and should be used most of the time. + +`pluginId` is optional if you don't use multi-instance plugins. + +```ts +function usePluginData( + pluginName: string, + pluginId?: string, + options?: {failfast?: boolean}, +); +``` + +Usage example: + +```jsx +import React from 'react'; +// highlight-next-line +import {usePluginData} from '@docusaurus/useGlobalData'; + +const MyComponent = () => { + // highlight-start + const myPluginData = usePluginData('my-plugin'); + return
    {myPluginData.someAttribute}
    ; + // highlight-end +}; +``` + +### `useAllPluginInstancesData` {#useAllPluginInstancesData} + +Access global data created by a specific plugin. Given a plugin name, it returns the data of all the plugins instances of that name, by plugin id. + +```ts +function useAllPluginInstancesData( + pluginName: string, + options?: {failfast?: boolean}, +); +``` + +Usage example: + +```jsx +import React from 'react'; +// highlight-next-line +import {useAllPluginInstancesData} from '@docusaurus/useGlobalData'; + +const MyComponent = () => { + // highlight-start + const allPluginInstancesData = useAllPluginInstancesData('my-plugin'); + const myPluginData = allPluginInstancesData['default']; + return
    {myPluginData.someAttribute}
    ; + // highlight-end +}; +``` + +### `useBrokenLinks` {#useBrokenLinks} + +React hook to access the Docusaurus broken link checker APIs, exposing a way for a Docusaurus pages to report and collect their links and anchors. + +:::warning + +This is an **advanced** API that **most Docusaurus users don't need to use directly**. + +It is already **built-in** in existing high-level components: + +- the [``](#link) component will collect links for you +- the `@theme/Heading` (used for Markdown headings) will collect anchors + +Use `useBrokenLinks()` if you implement your own `` or `` component. + +::: + +Usage example: + +```js title="MyHeading.js" +import useBrokenLinks from '@docusaurus/useBrokenLinks'; + +export default function MyHeading(props) { + useBrokenLinks().collectAnchor(props.id); + return

    ; +} +``` + +```js title="MyLink.js" +import useBrokenLinks from '@docusaurus/useBrokenLinks'; + +export default function MyLink(props) { + useBrokenLinks().collectLink(props.href); + return ; +} +``` + +## Functions {#functions} + +### `interpolate` {#interpolate-1} + +The imperative counterpart of the [``](#interpolate) component. + +#### Signature {#signature} + +```ts +// Simple string interpolation +function interpolate(text: string, values: Record): string; + +// JSX interpolation +function interpolate( + text: string, + values: Record, +): ReactNode; +``` + +#### Example {#example-1} + +```js +// highlight-next-line +import {interpolate} from '@docusaurus/Interpolate'; + +const message = interpolate('Welcome {firstName}', {firstName: 'Sébastien'}); +``` + +### `translate` {#translate-imperative} + +The imperative counterpart of the [``](#translate) component. Also supporting [placeholders interpolation](#interpolate). + +:::tip + +Use the imperative API for the **rare cases** where a **component cannot be used**, such as: + +- the page `title` metadata +- the `placeholder` props of form inputs +- the `aria-label` props for accessibility + +::: + +#### Signature {#signature-1} + +```ts +function translate( + translation: {message: string; id?: string; description?: string}, + values: Record, +): string; +``` + +#### Example {#example-2} + +```jsx title="src/pages/index.js" +import React from 'react'; +import Layout from '@theme/Layout'; + +// highlight-next-line +import {translate} from '@docusaurus/Translate'; + +export default function Home() { + return ( + + + + ); +} +``` + +## Modules {#modules} + +### `ExecutionEnvironment` {#executionenvironment} + +A module that exposes a few boolean variables to check the current rendering environment. + +:::warning + +For React rendering logic, use [`useIsBrowser()`](#useIsBrowser) or [``](#browseronly) instead. + +::: + +Example: + +```js +import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; + +if (ExecutionEnvironment.canUseDOM) { + require('lib-that-only-works-client-side'); +} +``` + +| Field | Description | +| --- | --- | +| `ExecutionEnvironment.canUseDOM` | `true` if on client/browser, `false` on Node.js/prerendering. | +| `ExecutionEnvironment.canUseEventListeners` | `true` if on client and has `window.addEventListener`. | +| `ExecutionEnvironment.canUseIntersectionObserver` | `true` if on client and has `IntersectionObserver`. | +| `ExecutionEnvironment.canUseViewport` | `true` if on client and has `window.screen`. | + +### `constants` {#constants} + +A module exposing useful constants to client-side theme code. + +```js +import {DEFAULT_PLUGIN_ID} from '@docusaurus/constants'; +``` + +| Named export | Value | +| ------------------- | --------- | +| `DEFAULT_PLUGIN_ID` | `default` | diff --git a/website/versioned_docs/version-3.9.0/guides/creating-pages.mdx b/website/versioned_docs/version-3.9.0/guides/creating-pages.mdx new file mode 100644 index 0000000000..c256716078 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/creating-pages.mdx @@ -0,0 +1,140 @@ +--- +slug: /creating-pages +sidebar_label: Pages +--- + +# Creating Pages + +In this section, we will learn about creating pages in Docusaurus. + +The `@docusaurus/plugin-content-pages` plugin empowers you to create **one-off standalone pages** like a showcase page, playground page, or support page. You can use React components, or Markdown. + +:::note + +Pages do not have sidebars, only [docs](./docs/docs-introduction.mdx) do. + +::: + +:::info + +Check the [Pages Plugin API Reference documentation](./../api/plugins/plugin-content-pages.mdx) for an exhaustive list of options. + +::: + +## Add a React page {#add-a-react-page} + +React is used as the UI library to create pages. Every page component should export a React component, and you can leverage the expressiveness of React to build rich and interactive content. + +Create a file `/src/pages/helloReact.js`: + +```jsx title="/src/pages/helloReact.js" +import React from 'react'; +import Layout from '@theme/Layout'; + +export default function Hello() { + return ( + +
    +

    + Edit pages/helloReact.js and save to reload. +

    +
    +
    + ); +} +``` + +Once you save the file, the development server will automatically reload the changes. Now open [`http://localhost:3000/helloReact`](http://localhost:3000/helloReact) and you will see the new page you just created. + +Each page doesn't come with any styling. You will need to import the `Layout` component from `@theme/Layout` and wrap your contents within that component if you want the navbar and/or footer to appear. + +:::tip + +You can also create TypeScript pages with the `.tsx` extension (`helloReact.tsx`). + +::: + +## Add a Markdown page {#add-a-markdown-page} + +Create a file `/src/pages/helloMarkdown.md`: + +```md title="/src/pages/helloMarkdown.md" +--- +title: my hello page title +description: my hello page description +hide_table_of_contents: true +--- + +# Hello + +How are you? +``` + +In the same way, a page will be created at [`http://localhost:3000/helloMarkdown`](http://localhost:3000/helloMarkdown). + +Markdown pages are less flexible than React pages because it always uses the theme layout. + +Here's an [example Markdown page](/examples/markdownPageExample). + +:::tip + +You can use the full power of React in Markdown pages too, refer to the [MDX](https://mdxjs.com/) documentation. + +::: + +## Routing {#routing} + +If you are familiar with other static site generators like Jekyll and Next, this routing approach will feel familiar to you. Any JavaScript file you create under `/src/pages/` directory will be automatically converted to a website page, following the `/src/pages/` directory hierarchy. For example: + +- `/src/pages/index.js` → `[baseUrl]` +- `/src/pages/foo.js` → `[baseUrl]/foo` +- `/src/pages/foo/test.js` → `[baseUrl]/foo/test` +- `/src/pages/foo/index.js` → `[baseUrl]/foo/` + +In this component-based development era, it is encouraged to co-locate your styling, markup, and behavior together into components. Each page is a component, and if you need to customize your page design with your own styles, we recommend co-locating your styles with the page component in its own directory. For example, to create a "Support" page, you could do one of the following: + +- Add a `/src/pages/support.js` file +- Create a `/src/pages/support/` directory and a `/src/pages/support/index.js` file. + +The latter is preferred as it has the benefits of letting you put files related to the page within that directory. For example, a CSS module file (`styles.module.css`) with styles meant to only be used on the "Support" page. + +:::note + +This is merely a recommended directory structure, and you will still need to manually import the CSS module file within your component module (`support/index.js`). + +::: + +By default, any Markdown or JavaScript file starting with `_` will be ignored and no routes will be created for that file (see the `exclude` option). + +```bash +my-website +├── src +│ └── pages +│ ├── styles.module.css +│ ├── index.js +│ ├── _ignored.js +│ ├── _ignored-folder +│ │ ├── Component1.js +│ │ └── Component2.js +│ └── support +│ ├── index.js +│ └── styles.module.css +. +``` + +:::warning + +All JavaScript/TypeScript files within the `src/pages/` directory will have corresponding website paths generated for them. If you want to create reusable components into that directory, use the `exclude` option (by default, files prefixed with `_`, test files(`.test.js`), and files in `__tests__` directory are not turned into pages). + +::: + +### Duplicate Routes {#duplicate-routes} + +You may accidentally create multiple pages that are meant to be accessed on the same route. When this happens, Docusaurus will warn you about duplicate routes when you run `yarn start` or `yarn build` (behavior configurable through the [`onDuplicateRoutes`](../api/docusaurus.config.js.mdx#onDuplicateRoutes) config), but the site will still be built successfully. The page that was created last will be accessible, but it will override other conflicting pages. To resolve this issue, you should modify or remove any conflicting routes. diff --git a/website/versioned_docs/version-3.9.0/guides/docs/docs-create-doc.mdx b/website/versioned_docs/version-3.9.0/guides/docs/docs-create-doc.mdx new file mode 100644 index 0000000000..b45cf6d331 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/docs/docs-create-doc.mdx @@ -0,0 +1,202 @@ +--- +id: create-doc +description: Create a Markdown Document +slug: /create-doc +--- + +# Create a doc + +Create a Markdown file, `greeting.md`, and place it under the `docs` directory. + +```bash +website # root directory of your site +├── docs +│ └── greeting.md +├── src +│ └── pages +├── docusaurus.config.js +├── ... +``` + +```md +--- +description: Create a doc page with rich content. +--- + +# Hello from Docusaurus + +Are you ready to create the documentation site for your open source project? + +## Headers + +will show up on the table of contents on the upper right + +So that your users will know what this page is all about without scrolling down or even without reading too much. + +## Only h2 and h3 will be in the TOC by default. + +You can configure the TOC heading levels either per-document or in the theme configuration. + +The headers are well-spaced so that the hierarchy is clear. + +- lists will help you +- present the key points +- that you want your users to remember + - and you may nest them + - multiple times +``` + +:::note + +All files prefixed with an underscore (`_`) under the `docs` directory are treated as "partial" pages and will be ignored by default. + +Read more about [importing partial pages](../markdown-features/markdown-features-react.mdx#importing-markdown). + +::: + +## Doc front matter {#doc-front-matter} + +The [front matter](../markdown-features/markdown-features-intro.mdx#front-matter) is used to provide additional metadata for your doc page. Front matter is optional—Docusaurus will be able to infer all necessary metadata without the front matter. For example, the [doc tags](#doc-tags) feature introduced below requires using front matter. For all possible fields, see [the API documentation](../../api/plugins/plugin-content-docs.mdx#markdown-front-matter). + +## Doc tags {#doc-tags} + +Tags are declared in the front matter and introduce another dimension of categorization in addition to the [docs sidebar](./sidebar/index.mdx). + +It is possible to define tags inline, or to reference predefined tags declared in a [`tags file`](../../api/plugins/plugin-content-docs.mdx#tags-file) (optional, usually `docs/tags.yml`). + +In the following example: + +- `docusaurus` references a predefined tag key declared in `docs/tags.yml` +- `Releases` is an inline tag, because it does not exist in `docs/tags.yml` + +```md title="docs/my-doc.md" +--- +tags: + - Releases + - docusaurus +--- + +# Title + +Content +``` + +```yml title="docs/tags.yml" +docusaurus: + label: 'Docusaurus' + permalink: '/docusaurus' + description: 'Docs related to the Docusaurus framework' +``` + +:::tip + +Tags can also be declared with `tags: [Demo, Getting started]`. + +Read more about all the possible [Yaml array syntaxes](https://www.w3schools.io/file/yaml-arrays/). + +::: + +## Organizing folder structure {#organizing-folder-structure} + +How the Markdown files are arranged under the `docs` folder can have multiple impacts on Docusaurus content generation. However, most of them can be decoupled from the file structure. + +### Document ID {#document-id} + +Every document has a unique `id`. By default, a document `id` is the name of the document (without the extension) relative to the root docs directory. + +For example, the ID of `greeting.md` is `greeting`, and the ID of `guide/hello.md` is `guide/hello`. + +```bash +website # Root directory of your site +└── docs + ├── greeting.md + └── guide + └── hello.md +``` + +However, the **last part** of the `id` can be defined by the user in the front matter. For example, if `guide/hello.md`'s content is defined as below, its final `id` is `guide/part1`. + +```md +--- +id: part1 +--- + +Lorem ipsum +``` + +The ID is used to refer to a document when hand-writing sidebars, or when using docs-related layout components or hooks. + +### Doc URLs {#doc-urls} + +By default, the document's URL location is derived from the [document `id`](#document-id), which in turn is based on the document's file path. + +If a file is named one of the following, the file name won't be included in the URL: + +- Named as `index` (case-insensitive): `docs/Guides/index.md` +- Named as `README` (case-insensitive): `docs/Guides/README.mdx` +- Same name as parent folder: `docs/Guides/Guides.md` + +In all cases, the default `slug` would only be `/Guides`, without the `/index`, `/README`, or duplicate `/Guides` segment. + +:::note + +This convention is exactly the same as [the category index convention](./sidebar/autogenerated.mdx#category-index-convention). However, the `isCategoryIndex` configuration does _not_ affect the document URL. + +::: + +Use the `slug` front matter to provide an explicit document URL and override the default one. + +For example, suppose your site structure looks like this: + +```bash +website # Root directory of your site +└── docs + └── guide + └── hello.md +``` + +By default, `hello.md` will be available at `/docs/guide/hello`. You can change its URL location to `/docs/bonjour`: + +```md +--- +slug: /bonjour +--- + +Lorem ipsum +``` + +`slug` will be appended to the doc plugin's `routeBasePath`, which is `/docs` by default. See [Docs-only mode](docs-introduction.mdx#docs-only-mode) for how to remove the `/docs` part from the URL. + +:::note + +It is possible to use: + +- absolute slugs: `slug: /mySlug`, `slug: /`... +- relative slugs: `slug: mySlug`, `slug: ./../mySlug`... + +::: + +:::tip + +Changing a document's filename or `id`, will change its default URL. To prevent breaking permalinks when renaming files, we recommend setting an explicit `slug` to keep your URLs stable. + +::: + +#### Making a document available at the root + +If you want a document to be available at the root, and have a path like `https://docusaurus.io/docs/`, you can use the slug front matter: + +```md +--- +id: my-home-doc +slug: / +--- + +Lorem ipsum +``` + +### Sidebars {#sidebars} + +When using [autogenerated sidebars](./sidebar/autogenerated.mdx), the file structure will determine the sidebar structure. + +Our recommendation for file system organization is: make your file system mirror the sidebar structure (so you don't need to handwrite your `sidebars.js` file), and use the `slug` front matter to customize URLs of each document. diff --git a/website/versioned_docs/version-3.9.0/guides/docs/docs-introduction.mdx b/website/versioned_docs/version-3.9.0/guides/docs/docs-introduction.mdx new file mode 100644 index 0000000000..3892c316be --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/docs/docs-introduction.mdx @@ -0,0 +1,120 @@ +--- +id: introduction +sidebar_label: Introduction +slug: /docs-introduction +--- + +# Docs Introduction + +The docs feature provides users with a way to organize Markdown files in a hierarchical format. + +:::info + +Check the [Docs Plugin API Reference documentation](./../../api/plugins/plugin-content-docs.mdx) for an exhaustive list of options. + +::: + +Your site's documentation is organized by four levels, from lowest to highest: + +1. Individual pages. +2. Sidebars. +3. Versions. +4. Plugin instances. + +The guide will introduce them in that order: starting from [how individual pages can be configured](./docs-create-doc.mdx), to [how to create a sidebar or multiple ones](./sidebar/index.mdx), to [how to create and manage versions](./versioning.mdx), to [how to use multiple docs plugin instances](./docs-multi-instance.mdx). + +## Docs-only mode {#docs-only-mode} + +A freshly initialized Docusaurus site has the following structure: + +``` +example.com/ -> generated from `src/pages/index.js` + +example.com/docs/intro -> generated from `docs/intro.md` +example.com/docs/tutorial-basics/... -> generated from `docs/tutorial-basics/...` +... + +example.com/blog/2021/08/26/welcome -> generated from `blog/2021-08-26-welcome/index.md` +example.com/blog/2021/08/01/mdx-blog-post -> generated from `blog/2021-08-01-mdx-blog-post.mdx` +... +``` + +All docs will be served under the subroute `docs/`. But what if **your site only has docs**, or you want to prioritize your docs by putting them at the root? + +Assume that you have the following in your configuration: + +```js title="docusaurus.config.js" +export default { + // ... + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + /* docs plugin options */ + }, + blog: { + /* blog plugin options */ + }, + // ... + }, + ], + ], +}; +``` + +To enter docs-only mode, change it to like this: + +```js title="docusaurus.config.js" +export default { + // ... + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + // highlight-next-line + routeBasePath: '/', // Serve the docs at the site's root + /* other docs plugin options */ + }, + // highlight-next-line + blog: false, // Optional: disable the blog plugin + // ... + }, + ], + ], +}; +``` + +Note that you **don't necessarily have to give up on using the blog** or other plugins; all that `routeBasePath: '/'` does is that instead of serving the docs through `https://example.com/docs/some-doc`, they are now at the site root: `https://example.com/some-doc`. The blog, if enabled, can still be accessed through the `blog/` subroute. + +Don't forget to put some page at the root (`https://example.com/`) through adding the front matter: + +```md title="docs/intro.md" +--- +# highlight-next-line +slug: / +--- + +This page will be the home page when users visit https://example.com/. +``` + +:::warning + +If you added `slug: /` to a doc to make it the homepage, you should delete the existing homepage at `./src/pages/index.js`, or else there will be two files mapping to the same route! + +::: + +Now, the site's structure will be like the following: + +``` +example.com/ -> generated from `docs/intro.md` +example.com/tutorial-basics/... -> generated from `docs/tutorial-basics/...` +... +``` + +:::tip + +There's also a "blog-only mode" for those who only want to use the blog feature of Docusaurus. You can use the same method detailed above. Follow the setup instructions on [Blog-only mode](../../blog.mdx#blog-only-mode). + +::: diff --git a/website/versioned_docs/version-3.9.0/guides/docs/docs-multi-instance.mdx b/website/versioned_docs/version-3.9.0/guides/docs/docs-multi-instance.mdx new file mode 100644 index 0000000000..3fd9a607f9 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/docs/docs-multi-instance.mdx @@ -0,0 +1,213 @@ +--- +id: multi-instance +description: Use multiple docs plugin instances on a single Docusaurus site. +slug: /docs-multi-instance +--- + +# Docs Multi-instance + +The `@docusaurus/plugin-content-docs` plugin can support [multi-instance](../../using-plugins.mdx#multi-instance-plugins-and-plugin-ids). + +:::note + +This feature is only useful for [versioned documentation](./versioning.mdx). It is recommended to be familiar with docs versioning before reading this page. If you just want [multiple sidebars](./sidebar/multiple-sidebars.mdx), you can do so within one plugin. + +::: + +## Use-cases {#use-cases} + +Sometimes you want a Docusaurus site to host 2 distinct sets of documentation (or more). + +These documentations may even have different versioning/release lifecycles. + +### Mobile SDKs documentation {#mobile-sdks-documentation} + +If you build a cross-platform mobile SDK, you may have 2 documentations: + +- Android SDK documentation (`v1.0`, `v1.1`) +- iOS SDK documentation (`v1.0`, `v2.0`) + +In this case, you can use a distinct docs plugin instance per mobile SDK documentation. + +:::warning + +If each documentation instance is very large, you should rather create 2 distinct Docusaurus sites. + +If someone edits the iOS documentation, is it really useful to rebuild everything, including the whole Android documentation that did not change? + +::: + +### Versioned and unversioned doc {#versioned-and-unversioned-doc} + +Sometimes, you want some documents to be versioned, while other documents are more "global", and it feels useless to version them. + +We use this pattern on the Docusaurus website itself: + +- The [/docs/\*](/docs) section is versioned +- The [/community/\*](/community/support) section is unversioned + +## Setup {#setup} + +Suppose you have 2 documentations: + +- Product: some versioned doc about your product +- Community: some unversioned doc about the community around your product + +In this case, you should use the same plugin twice in your site configuration. + +:::warning + +`@docusaurus/preset-classic` already includes a docs plugin instance for you! + +::: + +When using the preset: + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + // highlight-start + // id: 'product', // omitted => default instance + // highlight-end + path: 'product', + routeBasePath: 'product', + sidebarPath: './sidebarsProduct.js', + // ... other options + }, + }, + ], + ], + plugins: [ + [ + '@docusaurus/plugin-content-docs', + { + // highlight-start + id: 'community', + // highlight-end + path: 'community', + routeBasePath: 'community', + sidebarPath: './sidebarsCommunity.js', + // ... other options + }, + ], + ], +}; +``` + +When not using the preset: + +```js title="docusaurus.config.js" +export default { + plugins: [ + [ + '@docusaurus/plugin-content-docs', + { + // highlight-start + // id: 'product', // omitted => default instance + // highlight-end + path: 'product', + routeBasePath: 'product', + sidebarPath: './sidebarsProduct.js', + // ... other options + }, + ], + [ + '@docusaurus/plugin-content-docs', + { + // highlight-start + id: 'community', + // highlight-end + path: 'community', + routeBasePath: 'community', + sidebarPath: './sidebarsCommunity.js', + // ... other options + }, + ], + ], +}; +``` + +Don't forget to assign a unique `id` attribute to plugin instances. + +:::note + +We consider that the `product` instance is the most important one, and make it the "default" instance by not assigning any ID. + +::: + +## Versioned paths {#versioned-paths} + +Each plugin instance will store versioned docs in a distinct folder. + +The default plugin instance will use these paths: + +- `website/versions.json` +- `website/versioned_docs` +- `website/versioned_sidebars` + +The other plugin instances (with an `id` attribute) will use these paths: + +- `website/[pluginId]_versions.json` +- `website/[pluginId]_versioned_docs` +- `website/[pluginId]_versioned_sidebars` + +:::tip + +You can omit the `id` attribute (defaults to `default`) for one of the docs plugin instances. + +The instance paths will be simpler, and retro-compatible with a single-instance setup. + +::: + +## Tagging new versions {#tagging-new-versions} + +Each plugin instance will have its own CLI command to tag a new version. They will be displayed if you run: + +```bash npm2yarn +npm run docusaurus -- --help +``` + +To version the product/default docs plugin instance: + +```bash npm2yarn +npm run docusaurus docs:version 1.0.0 +``` + +To version the non-default/community docs plugin instance: + +```bash npm2yarn +npm run docusaurus docs:version:community 1.0.0 +``` + +## Docs navbar items {#docs-navbar-items} + +Each docs-related [theme navbar items](../../api/themes/theme-configuration.mdx#navbar) take an optional `docsPluginId` attribute. + +For example, if you want to have one version dropdown for each mobile SDK (iOS and Android), you could do: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + items: [ + { + type: 'docsVersionDropdown', + // highlight-start + docsPluginId: 'ios', + // highlight-end + }, + { + type: 'docsVersionDropdown', + // highlight-start + docsPluginId: 'android', + // highlight-end + }, + ], + }, + }, +}; +``` diff --git a/website/versioned_docs/version-3.9.0/guides/docs/sidebar/autogenerated.mdx b/website/versioned_docs/version-3.9.0/guides/docs/sidebar/autogenerated.mdx new file mode 100644 index 0000000000..7e3bfcf0a0 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/docs/sidebar/autogenerated.mdx @@ -0,0 +1,497 @@ +--- +slug: /sidebar/autogenerated +--- + +# Autogenerated + +```mdx-code-block +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +``` + +Docusaurus can **create a sidebar automatically** from your **filesystem structure**: each folder creates a sidebar category, and each file creates a doc link. + +```ts +type SidebarItemAutogenerated = { + type: 'autogenerated'; + dirName: string; // Source folder to generate the sidebar slice from (relative to docs) +}; +``` + +Docusaurus can generate a full sidebar from your docs folder: + +```js title="sidebars.js" +export default { + myAutogeneratedSidebar: [ + // highlight-start + { + type: 'autogenerated', + dirName: '.', // '.' means the current docs folder + }, + // highlight-end + ], +}; +``` + +An `autogenerated` item is converted by Docusaurus to a **sidebar slice** (also discussed in [category shorthands](items.mdx#category-shorthand)): a list of items of type `doc` or `category`, so you can splice **multiple `autogenerated` items** from multiple directories, interleaving them with regular sidebar items, in one sidebar level. + +
    +A real-world example + +Consider this file structure: + +```bash +docs +├── api +│ ├── product1-api +│ │ └── api.md +│ └── product2-api +│ ├── basic-api.md +│ └── pro-api.md +├── intro.md +└── tutorials + ├── advanced + │ ├── advanced1.md + │ ├── advanced2.md + │ └── read-more + │ ├── resource1.md + │ └── resource2.md + ├── easy + │ ├── easy1.md + │ └── easy2.md + ├── tutorial-end.md + ├── tutorial-intro.md + └── tutorial-medium.md +``` + +And assume every doc's ID is just its file name. If you define an autogenerated sidebar like this: + +```js title="sidebars.js" +export default { + mySidebar: [ + 'intro', + { + type: 'category', + label: 'Tutorials', + items: [ + 'tutorial-intro', + // highlight-start + { + type: 'autogenerated', + dirName: 'tutorials/easy', // Generate sidebar slice from docs/tutorials/easy + }, + // highlight-end + 'tutorial-medium', + // highlight-start + { + type: 'autogenerated', + dirName: 'tutorials/advanced', // Generate sidebar slice from docs/tutorials/advanced + }, + // highlight-end + 'tutorial-end', + ], + }, + // highlight-start + { + type: 'autogenerated', + dirName: 'api', // Generate sidebar slice from docs/api + }, + // highlight-end + { + type: 'category', + label: 'Community', + items: ['team', 'chat'], + }, + ], +}; +``` + +It would be resolved as: + +```js title="sidebars.js" +export default { + mySidebar: [ + 'intro', + { + type: 'category', + label: 'Tutorials', + items: [ + 'tutorial-intro', + // highlight-start + // Two files in docs/tutorials/easy + 'easy1', + 'easy2', + // highlight-end + 'tutorial-medium', + // highlight-start + // Two files and a folder in docs/tutorials/advanced + 'advanced1', + 'advanced2', + { + type: 'category', + label: 'read-more', + items: ['resource1', 'resource2'], + }, + // highlight-end + 'tutorial-end', + ], + }, + // highlight-start + // Two folders in docs/api + { + type: 'category', + label: 'product1-api', + items: ['api'], + }, + { + type: 'category', + label: 'product2-api', + items: ['basic-api', 'pro-api'], + }, + // highlight-end + { + type: 'category', + label: 'Community', + items: ['team', 'chat'], + }, + ], +}; +``` + +Note how the autogenerate source directories themselves don't become categories: only the items they contain do. This is what we mean by "sidebar slice". + +
    + +## Category index convention {#category-index-convention} + +Docusaurus can automatically link a category to its index document. + +A category index document is a document following one of those filename conventions: + +- Named as `index` (case-insensitive): `docs/Guides/index.md` +- Named as `README` (case-insensitive): `docs/Guides/README.mdx` +- Same name as parent folder: `docs/Guides/Guides.md` + +This is equivalent to using a category with a [doc link](items.mdx#category-doc-link): + +```js title="sidebars.js" +export default { + docs: [ + // highlight-start + { + type: 'category', + label: 'Guides', + link: {type: 'doc', id: 'Guides/index'}, + items: [], + }, + // highlight-end + ], +}; +``` + +:::tip + +Naming your introductory document `README.md` makes it show up when browsing the folder using the GitHub interface, while using `index.md` makes the behavior more in line with how HTML files are served. + +::: + +:::tip + +If a folder only has one index page, it will be turned into a link instead of a category. This is useful for **asset collocation**: + +``` +some-doc +├── index.md +├── img1.png +└── img2.png +``` + +::: + +
    + +Customizing category index matching + +It is possible to opt out any of the category index conventions, or define even more conventions. You can inject your own `isCategoryIndex` matcher through the [`sidebarItemsGenerator`](#customize-the-sidebar-items-generator) callback. For example, you can also pick `intro` as another file name eligible for automatically becoming the category index. + +```js title="docusaurus.config.js" +export default { + plugins: [ + [ + '@docusaurus/plugin-content-docs', + { + async sidebarItemsGenerator({ + ...args, + isCategoryIndex: defaultCategoryIndexMatcher, // The default matcher implementation, given below + defaultSidebarItemsGenerator, + }) { + return defaultSidebarItemsGenerator({ + ...args, + // highlight-start + isCategoryIndex(doc) { + return ( + // Also pick intro.md in addition to the default ones + doc.fileName.toLowerCase() === 'intro' || + defaultCategoryIndexMatcher(doc) + ); + }, + // highlight-end + }); + }, + }, + ], + ], +}; +``` + +Or choose to not have any category index convention. + +```js title="docusaurus.config.js" +export default { + plugins: [ + [ + '@docusaurus/plugin-content-docs', + { + async sidebarItemsGenerator({ + ...args, + isCategoryIndex: defaultCategoryIndexMatcher, // The default matcher implementation, given below + defaultSidebarItemsGenerator, + }) { + return defaultSidebarItemsGenerator({ + ...args, + // highlight-start + isCategoryIndex() { + // No doc will be automatically picked as category index + return false; + }, + // highlight-end + }); + }, + }, + ], + ], +}; +``` + +The `isCategoryIndex` matcher will be provided with three fields: + +- `fileName`, the file's name without extension and with casing preserved +- `directories`, the list of directory names _from the lowest level to the highest level_, relative to the docs root directory +- `extension`, the file's extension, with a leading dot. + +For example, for a doc file at `guides/sidebar/autogenerated.md`, the props the matcher receives are + +```js +const props = { + fileName: 'autogenerated', + directories: ['sidebar', 'guides'], + extension: '.md', +}; +``` + +The default implementation is: + +```js +function isCategoryIndex({fileName, directories}) { + const eligibleDocIndexNames = [ + 'index', + 'readme', + directories[0].toLowerCase(), + ]; + return eligibleDocIndexNames.includes(fileName.toLowerCase()); +} +``` + +
    + +## Autogenerated sidebar metadata {#autogenerated-sidebar-metadata} + +For handwritten sidebar definitions, you would provide metadata to sidebar items through `sidebars.js`; for autogenerated, Docusaurus would read them from the item's respective file. In addition, you may want to adjust the relative position of each item because, by default, items within a sidebar slice will be generated in **alphabetical order** (using file and folder names). + +### Doc item metadata {#doc-item-metadata} + +The `label`, `className`, and `customProps` attributes are declared in front matter as `sidebar_label`, `sidebar_class_name`, and `sidebar_custom_props`, respectively. Position can be specified in the same way, via `sidebar_position` front matter. + +```md title="docs/tutorials/tutorial-easy.md" +--- +# highlight-start +sidebar_position: 2 +sidebar_label: Easy +sidebar_class_name: green +# highlight-end +--- + +# Easy Tutorial + +This is the easy tutorial! +``` + +### Category item metadata {#category-item-metadata} + +Add a `_category_.json` or `_category_.yml` file in the respective folder. You can specify any category metadata and also the `position` metadata. `label`, `className`, `position`, and `customProps` will default to the respective values of the category's linked doc, if there is one. + + + + +```json title="docs/tutorials/_category_.json" +{ + "position": 2.5, + "label": "Tutorial", + "collapsible": true, + "collapsed": false, + "className": "red", + "link": { + "type": "generated-index", + "title": "Tutorial overview" + }, + "customProps": { + "description": "This description can be used in the swizzled DocCard" + } +} +``` + + + + +```yml title="docs/tutorials/_category_.yml" +position: 2.5 # float position is supported +label: 'Tutorial' +collapsible: true # make the category collapsible +collapsed: false # keep the category open by default +className: red +link: + type: generated-index + title: Tutorial overview +customProps: + description: This description can be used in the swizzled DocCard +``` + + + + +:::info + +If the `link` is explicitly specified, Docusaurus will not apply any [default conventions](#category-index-convention). + +The doc links can be specified relatively, e.g. if the category is generated with the `guides` directory, `"link": {"type": "doc", "id": "intro"}` will be resolved to the ID `guides/intro`, only falling back to `intro` if a doc with the former ID doesn't exist. + +You can also use `link: null` to opt out of default conventions and not generate any category index page. + +::: + +:::info + +The position metadata is only used **within a sidebar slice**: Docusaurus does not re-order other items of your sidebar. + +::: + +## Using number prefixes {#using-number-prefixes} + +A simple way to order an autogenerated sidebar is to prefix docs and folders by number prefixes, which also makes them appear in the file system in the same order when sorted by file name: + +```bash +docs +├── 01-Intro.md +├── 02-Tutorial Easy +│ ├── 01-First Part.md +│ ├── 02-Second Part.md +│ └── 03-End.md +├── 03-Tutorial Advanced +│ ├── 01-First Part.md +│ ├── 02-Second Part.md +│ ├── 03-Third Part.md +│ └── 04-End.md +└── 04-End.md +``` + +To make it **easier to adopt**, Docusaurus supports **multiple number prefix patterns**. + +By default, Docusaurus will **remove the number prefix** from the doc id, title, label, and URL paths. + +:::warning + +**Prefer using [additional metadata](#autogenerated-sidebar-metadata)**. + +Updating a number prefix can be annoying, as it can require **updating multiple existing Markdown links**: + +```diff title="docs/02-Tutorial Easy/01-First Part.md" +- Check the [Tutorial End](../04-End.mdx); ++ Check the [Tutorial End](../05-End.mdx); +``` + +::: + +## Customize the sidebar items generator {#customize-the-sidebar-items-generator} + +You can provide a custom `sidebarItemsGenerator` function in the docs plugin (or preset) config: + +```js title="docusaurus.config.js" +export default { + plugins: [ + [ + '@docusaurus/plugin-content-docs', + { + // highlight-start + async sidebarItemsGenerator({ + defaultSidebarItemsGenerator, + numberPrefixParser, + item, + version, + docs, + categoriesMetadata, + isCategoryIndex, + }) { + // Example: return an hardcoded list of static sidebar items + return [ + {type: 'doc', id: 'doc1'}, + {type: 'doc', id: 'doc2'}, + ]; + }, + // highlight-end + }, + ], + ], +}; +``` + +:::tip + +**Re-use and enhance the default generator** instead of writing a generator from scratch: [the default generator we provide](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts) is 250 lines long. + +**Add, update, filter, re-order** the sidebar items according to your use case: + +```js title="docusaurus.config.js" +// highlight-start +// Reverse the sidebar items ordering (including nested category items) +function reverseSidebarItems(items) { + // Reverse items in categories + const result = items.map((item) => { + if (item.type === 'category') { + return {...item, items: reverseSidebarItems(item.items)}; + } + return item; + }); + // Reverse items at current level + result.reverse(); + return result; +} +// highlight-end + +export default { + plugins: [ + [ + '@docusaurus/plugin-content-docs', + { + // highlight-start + async sidebarItemsGenerator({defaultSidebarItemsGenerator, ...args}) { + const sidebarItems = await defaultSidebarItemsGenerator(args); + return reverseSidebarItems(sidebarItems); + }, + // highlight-end + }, + ], + ], +}; +``` + +::: diff --git a/website/versioned_docs/version-3.9.0/guides/docs/sidebar/index.mdx b/website/versioned_docs/version-3.9.0/guides/docs/sidebar/index.mdx new file mode 100644 index 0000000000..82cf0499ae --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/docs/sidebar/index.mdx @@ -0,0 +1,254 @@ +--- +slug: /sidebar +--- + +# Sidebar + +Creating a sidebar is useful to: + +- Group multiple **related documents** into an ordered tree +- **Display a common sidebar** on each of those documents +- Provide **paginated navigation**, with next/previous button + +To use sidebars on your Docusaurus site: + +1. Define a sidebars file that exports a dictionary of [sidebar objects](#sidebar-object). +2. Pass its path to the `@docusaurus/plugin-docs` plugin directly or via `@docusaurus/preset-classic`. + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + // highlight-next-line + sidebarPath: './sidebars.js', + }, + }, + ], + ], +}; +``` + +:::important Node.js runtime + +The sidebars file is run with Node.js. You can't use or import browsers APIs, React or JSX in it. + +::: + +This section serves as an overview of miscellaneous features of the doc sidebar. In the following sections, we will more systematically introduce the following concepts: + +```mdx-code-block +import DocCardList from '@theme/DocCardList'; + + +``` + +## Default sidebar {#default-sidebar} + +If the `sidebarPath` is unspecified, Docusaurus [automatically generates a sidebar](autogenerated.mdx) for you, by using the filesystem structure of the `docs` folder: + +```js title="sidebars.js" +export default { + mySidebar: [ + { + type: 'autogenerated', + dirName: '.', // generate sidebar from the docs folder (or versioned_docs/) + }, + ], +}; +``` + +You can also define your sidebars explicitly. + +## Sidebar object {#sidebar-object} + +A sidebar is a hierarchy of categories, doc links, and other hyperlinks. + +```ts +type Sidebar = + // Normal syntax + | SidebarItem[] + // Shorthand syntax + | {[categoryLabel: string]: SidebarItem[]}; +``` + +For example: + +```js title="sidebars.js" +export default { + mySidebar: [ + { + type: 'category', + label: 'Getting Started', + items: [ + { + type: 'doc', + id: 'doc1', + }, + ], + }, + { + type: 'category', + label: 'Docusaurus', + items: [ + { + type: 'doc', + id: 'doc2', + }, + { + type: 'doc', + id: 'doc3', + }, + ], + }, + { + type: 'link', + label: 'Learn more', + href: 'https://example.com', + }, + ], +}; +``` + +This is a sidebars file that exports one sidebar, called `mySidebar`. It has three top-level items: two categories and one external link. Within each category, there are a few doc links. + +A sidebars file can contain [**multiple sidebar objects**](multiple-sidebars.mdx), identified by their object keys. + +```ts +type SidebarsFile = { + [sidebarID: string]: Sidebar; +}; +``` + +## Theme configuration {#theme-configuration} + +### Hideable sidebar {#hideable-sidebar} + +By enabling the `themeConfig.docs.sidebar.hideable` option, you can make the entire sidebar hideable, allowing users to better focus on the content. This is especially useful when content is consumed on medium-sized screens (e.g. tablets). + +```js title="docusaurus.config.js" +export default { + themeConfig: { + // highlight-start + docs: { + sidebar: { + hideable: true, + }, + }, + // highlight-end + }, +}; +``` + +### Auto-collapse sidebar categories {#auto-collapse-sidebar-categories} + +The `themeConfig.docs.sidebar.autoCollapseCategories` option would collapse all sibling categories when expanding one category. This saves the user from having too many categories open and helps them focus on the selected section. + +```js title="docusaurus.config.js" +export default { + themeConfig: { + // highlight-start + docs: { + sidebar: { + autoCollapseCategories: true, + }, + }, + // highlight-end + }, +}; +``` + +## Passing CSS classes {#passing-css-classes} + +To pass CSS classes to a sidebar item, add the optional `className` attribute to any of the items. This is useful to apply visual customizations to specific sidebar items. + +```js +{ + type: 'doc', + id: 'doc1', + // highlight-start + className: 'sidebar-item--highlighted', + // highlight-end +}; +``` + +## Passing custom props {#passing-custom-props} + +To pass in custom props to a sidebar item, add the optional `customProps` object to any of the items. This is useful to apply site customizations by swizzling React components rendering sidebar items. + +```js +{ + type: 'doc', + id: 'doc1', + // highlight-start + customProps: { + badges: ['new', 'green'], + featured: true, + }, + // highlight-end +}; +``` + +## Passing a unique key {#passing-unique-key} + +Passing a unique `key` attribute can help uniquely identify a sidebar item. Sometimes other attributes (such as `label`) are not enough to distinguish two sidebar items from each other. + +```js +{ + type: 'category', + // highlight-start + label: 'API', // You may have multiple categories with this widespread label + key: 'api-for-feature-1', // and now, they can be uniquely identified + // highlight-end +}; +``` + +:::info How is this useful? + +Docusaurus only uses the `key` attribute to generate unique i18n translation keys. When a translation key conflict happens ([issue](https://github.com/facebook/docusaurus/issues/10913)), Docusaurus will tell you to apply a `key` to distinguish sidebar items. + +Alternatively, you may have your own reasons for using the `key` attribute that will be passed to the respective sidebar item React components. + +::: + +## Sidebar Breadcrumbs {#sidebar-breadcrumbs} + +By default, breadcrumbs are rendered at the top, using the "sidebar path" of the current page. + +This behavior can be disabled with plugin options: + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + // highlight-next-line + breadcrumbs: false, + }, + }, + ], + ], +}; +``` + +## Complex sidebars example {#complex-sidebars-example} + +A real-world example from the Docusaurus site: + +```mdx-code-block +import CodeBlock from '@theme/CodeBlock'; + + + {require('!!raw-loader!@site/sidebars.ts') + .default + .split('\n') + // remove comments + .map((line) => !['//','/*','*'].some(commentPattern => line.trim().startsWith(commentPattern)) && line) + .filter(Boolean) + .join('\n')} + +``` diff --git a/website/versioned_docs/version-3.9.0/guides/docs/sidebar/items.mdx b/website/versioned_docs/version-3.9.0/guides/docs/sidebar/items.mdx new file mode 100644 index 0000000000..12c4a518ee --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/docs/sidebar/items.mdx @@ -0,0 +1,626 @@ +--- +toc_max_heading_level: 4 +slug: /sidebar/items +--- + +# Sidebar items + +```mdx-code-block +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BrowserWindow from '@site/src/components/BrowserWindow'; +``` + +The sidebar supports various item types: + +- **[Doc](#sidebar-item-doc)**: link to a doc page, associating it with the sidebar +- **[Link](#sidebar-item-link)**: link to any internal or external page +- **[Category](#sidebar-item-category)**: creates a dropdown of sidebar items +- **[Autogenerated](autogenerated.mdx)**: generate a sidebar slice automatically +- **[HTML](#sidebar-item-html)**: renders pure HTML in the item's position +- **[Ref](multiple-sidebars.mdx#sidebar-item-ref)**: link to a doc page, without making the item take part in navigation generation + +## Doc: link to a doc {#sidebar-item-doc} + +Use the `doc` type to link to a doc page and assign that doc to a sidebar: + +```ts +type SidebarItemDoc = + // Normal syntax + | { + type: 'doc'; + id: string; + label: string; // Sidebar label text + key?: string; // Sidebar key to uniquely identify the item + className?: string; // Class name for sidebar label + customProps?: Record; // Custom props + } + + // Shorthand syntax + | string; // docId shortcut +``` + +Example: + +```js title="sidebars.js" +export default { + mySidebar: [ + // Normal syntax: + // highlight-start + { + type: 'doc', + id: 'doc1', // document ID + label: 'Getting started', // sidebar label + }, + // highlight-end + + // Shorthand syntax: + // highlight-start + 'doc2', // document ID + // highlight-end + ], +}; +``` + +If you use the doc shorthand or [autogenerated](autogenerated.mdx) sidebar, you would lose the ability to customize the sidebar label through item definition. You can, however, use the `sidebar_label` Markdown front matter within that doc, which has higher precedence over the `label` key in the sidebar item. Similarly, you can use `sidebar_custom_props` to declare custom metadata for a doc page. + +:::note + +A `doc` item sets an [implicit sidebar association](./multiple-sidebars.mdx#sidebar-association). Don't assign the same doc to multiple sidebars: change the type to `ref` instead. + +::: + +:::tip + +Sidebar custom props is a useful way to propagate arbitrary doc metadata to the client side, so you can get additional information when using any doc-related hook that fetches a doc object. + +::: + +## Link: link to any page {#sidebar-item-link} + +Use the `link` type to link to any page (internal or external) that is not a doc. + +```ts +type SidebarItemLink = { + type: 'link'; + label: string; + href: string; + description?: string; + key?: string; + className?: string; + customProps?: Record; +}; +``` + +Example: + +```js title="sidebars.js" +export default { + myLinksSidebar: [ + // highlight-start + // External link + { + type: 'link', + label: 'Facebook', // The link label + href: 'https://facebook.com', // The external URL + }, + // highlight-end + + // highlight-start + // Internal link + { + type: 'link', + label: 'Home', // The link label + href: '/', // The internal path + }, + // highlight-end + ], +}; +``` + +## HTML: render custom markup {#sidebar-item-html} + +Use the `html` type to render custom HTML within the item's `
  • ` tag. + +This can be useful for inserting custom items such as dividers, section titles, ads, and images. + +```ts +type SidebarItemHtml = { + type: 'html'; + value: string; + defaultStyle?: boolean; // Use default menu item styles + key?: string; + className?: string; + customProps?: Record; +}; +``` + +Example: + +```js title="sidebars.js" +export default { + myHtmlSidebar: [ + // highlight-start + { + type: 'html', + value: 'Sponsor', // The HTML to be rendered + defaultStyle: true, // Use the default menu item styling + }, + // highlight-end + ], +}; +``` + +:::tip + +The menu item is already wrapped in an `
  • ` tag, so if your custom item is simple, such as a title, just supply a string as the value and use the `className` property to style it: + +```js title="sidebars.js" +export default { + myHtmlSidebar: [ + { + type: 'html', + value: 'Core concepts', + className: 'sidebar-title', + }, + ], +}; +``` + +::: + +## Category: create a hierarchy {#sidebar-item-category} + +Use the `category` type to create a hierarchy of sidebar items. + +```ts +type SidebarItemCategory = { + type: 'category'; + label: string; // Sidebar label text. + items: SidebarItem[]; // Array of sidebar items. + description?: string; + key?: string; + className?: string; + customProps?: Record; + + // Category options: + collapsible: boolean; // Set the category to be collapsible + collapsed: boolean; // Set the category to be initially collapsed or open by default + link: SidebarItemCategoryLinkDoc | SidebarItemCategoryLinkGeneratedIndex; +}; +``` + +Example: + +```js title="sidebars.js" +export default { + docs: [ + { + type: 'category', + label: 'Guides', + collapsible: true, + collapsed: false, + items: [ + 'creating-pages', + { + type: 'category', + label: 'Docs', + items: ['introduction', 'sidebar', 'markdown-features', 'versioning'], + }, + ], + }, + ], +}; +``` + +:::tip + +Use the [**shorthand syntax**](#category-shorthand) when you don't need customizations: + +```js title="sidebars.js" +export default { + docs: { + Guides: [ + 'creating-pages', + { + Docs: ['introduction', 'sidebar', 'markdown-features', 'versioning'], + }, + ], + }, +}; +``` + +::: + +### Category links {#category-link} + +With category links, clicking on a category can navigate you to another page. + +:::tip + +Use category links to introduce a category of documents. + +Autogenerated categories can use the [`_category_.yml`](./autogenerated.mdx#category-item-metadata) file to declare the link. + +::: + +#### Generated index page {#generated-index-page} + +You can auto-generate an index page that displays all the direct children of this category. The `slug` allows you to customize the generated page's route, which defaults to `/category/[categoryName]`. + +```js title="sidebars.js" +export default { + docs: [ + { + type: 'category', + label: 'Guides', + // highlight-start + link: { + type: 'generated-index', + title: 'Docusaurus Guides', + description: 'Learn about the most important Docusaurus concepts!', + slug: '/category/docusaurus-guides', + keywords: ['guides'], + image: '/img/docusaurus.png', + }, + // highlight-end + items: ['pages', 'docs', 'blog', 'search'], + }, + ], +}; +``` + +See it in action on the [Docusaurus Guides page](/docs/category/guides). + +:::tip + +Use `generated-index` links as a quick way to get an introductory document. + +::: + +#### Doc link {#category-doc-link} + +A category can link to an existing document. + +```js title="sidebars.js" +export default { + docs: [ + { + type: 'category', + label: 'Guides', + // highlight-start + link: {type: 'doc', id: 'introduction'}, + // highlight-end + items: ['pages', 'docs', 'blog', 'search'], + }, + ], +}; +``` + +See it in action on the [i18n introduction page](../../../i18n/i18n-introduction.mdx). + +#### 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 with the `DocCardList` component. It will display all the sidebar items of the parent category of the current document. + +```md title="docs/sidebar/index.md" +import DocCardList from '@theme/DocCardList'; + + +``` + +```mdx-code-block + + +import DocCardList from '@theme/DocCardList'; + + + + +``` + +### Collapsible categories {#collapsible-categories} + +We support the option to expand/collapse categories. Categories are collapsible by default, but you can disable collapsing with `collapsible: false`. + +```js title="sidebars.js" +export default { + docs: [ + { + type: 'category', + label: 'Guides', + items: [ + 'creating-pages', + { + type: 'category', + // highlight-next-line + collapsible: false, + label: 'Docs', + items: ['introduction', 'sidebar', 'markdown-features', 'versioning'], + }, + ], + }, + ], +}; +``` + +To make all categories non-collapsible by default, set the `sidebarCollapsible` option in `plugin-content-docs` to `false`: + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + // highlight-next-line + sidebarCollapsible: false, + }, + }, + ], + ], +}; +``` + +:::note + +The option in `sidebars.js` takes precedence over plugin configuration, so it is possible to make certain categories collapsible when `sidebarCollapsible` is set to `false` globally. + +::: + +### Expanded categories by default {#expanded-categories-by-default} + +Collapsible categories are collapsed by default. If you want them to be expanded on the first render, you can set `collapsed` to `false`: + +```js title="sidebars.js" +export default { + docs: { + Guides: [ + 'creating-pages', + { + type: 'category', + label: 'Docs', + // highlight-next-line + collapsed: false, + items: ['markdown-features', 'sidebar', 'versioning'], + }, + ], + }, +}; +``` + +Similar to `collapsible`, you can also set the global configuration `options.sidebarCollapsed` to `false`. Individual `collapsed` options in `sidebars.js` will still take precedence over this configuration. + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + // highlight-next-line + sidebarCollapsed: false, + }, + }, + ], + ], +}; +``` + +:::warning + +When a category has `collapsed: true` but `collapsible: false` (either through `sidebars.js` or through plugin configuration), the latter takes precedence and the category is still rendered as expanded. + +::: + +## Using shorthands {#using-shorthands} + +You can express typical sidebar items without much customization more concisely with **shorthand syntaxes**. There are two parts to this: [**doc shorthand**](#doc-shorthand) and [**category shorthand**](#category-shorthand). + +### Doc shorthand {#doc-shorthand} + +An item with type `doc` can be simply a string representing its ID: + +```mdx-code-block + + +``` + +```js title="sidebars.js" +export default { + sidebar: [ + // highlight-start + { + type: 'doc', + id: 'myDoc', + }, + // highlight-end + ], +}; +``` + +```mdx-code-block + + +``` + +```js title="sidebars.js" +export default { + sidebar: [ + // highlight-start + 'myDoc', + // highlight-end + ], +}; +``` + +```mdx-code-block + + +``` + +So it's possible to simplify the example above to: + +```js title="sidebars.js" +export default { + mySidebar: [ + { + type: 'category', + label: 'Getting Started', + items: [ + // highlight-next-line + 'doc1', + ], + }, + { + type: 'category', + label: 'Docusaurus', + items: [ + // highlight-start + 'doc2', + 'doc3', + // highlight-end + ], + }, + { + type: 'link', + label: 'Learn more', + href: 'https://example.com', + }, + ], +}; +``` + +### Category shorthand {#category-shorthand} + +A category item can be represented by an object whose key is its label, and the value is an array of subitems. + +```mdx-code-block + + +``` + +```js title="sidebars.js" +export default { + sidebar: [ + // highlight-start + { + type: 'category', + label: 'Getting started', + items: ['doc1', 'doc2'], + }, + // highlight-end + ], +}; +``` + +```mdx-code-block + + +``` + +```js title="sidebars.js" +export default { + sidebar: [ + // highlight-start + { + 'Getting started': ['doc1', 'doc2'], + }, + // highlight-end + ], +}; +``` + +```mdx-code-block + + +``` + +This permits us to simplify that example to: + +```js title="sidebars.js" +export default { + mySidebar: [ + // highlight-start + { + 'Getting started': ['doc1'], + }, + { + Docusaurus: ['doc2', 'doc3'], + }, + // highlight-end + { + type: 'link', + label: 'Learn more', + href: 'https://example.com', + }, + ], +}; +``` + +Each shorthand object after this transformation will contain exactly one entry. Now consider the further simplified example below: + +```js title="sidebars.js" +export default { + mySidebar: [ + // highlight-start + { + 'Getting started': ['doc1'], + Docusaurus: ['doc2', 'doc3'], + }, + // highlight-end + { + type: 'link', + label: 'Learn more', + href: 'https://example.com', + }, + ], +}; +``` + +Note how the two consecutive category shorthands are compressed into one object with two entries. This syntax generates a **sidebar slice**: you shouldn't see that object as one bulk item—this object is unwrapped, with each entry becoming a separate item, and they spliced together with the rest of the items (in this case, the "Learn more" link) to form the final sidebar level. Sidebar slices are also important when discussing [autogenerated sidebars](autogenerated.mdx). + +Wherever you have an array of items that is reduced to one category shorthand, you can omit that enclosing array as well. + +```mdx-code-block + + +``` + +```js title="sidebars.js" +export default { + sidebar: [ + { + 'Getting started': ['doc1'], + Docusaurus: [ + { + 'Basic guides': ['doc2', 'doc3'], + 'Advanced guides': ['doc4', 'doc5'], + }, + ], + }, + ], +}; +``` + +```mdx-code-block + + +``` + +```js title="sidebars.js" +export default { + sidebar: { + 'Getting started': ['doc1'], + Docusaurus: { + 'Basic guides': ['doc2', 'doc3'], + 'Advanced guides': ['doc4', 'doc5'], + }, + }, +}; +``` + +```mdx-code-block + + +``` diff --git a/website/versioned_docs/version-3.9.0/guides/docs/sidebar/multiple-sidebars.mdx b/website/versioned_docs/version-3.9.0/guides/docs/sidebar/multiple-sidebars.mdx new file mode 100644 index 0000000000..d5fa60cb92 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/docs/sidebar/multiple-sidebars.mdx @@ -0,0 +1,143 @@ +--- +slug: /sidebar/multiple-sidebars +--- + +# Using multiple sidebars + +You can create a sidebar for each **set of Markdown files** that you want to **group together**. + +:::tip + +The Docusaurus site is a good example of using multiple sidebars: + +- [Docs](../../../introduction.mdx) +- [API](../../../cli.mdx) + +::: + +Consider this example: + +```js title="sidebars.js" +export default { + tutorialSidebar: { + 'Category A': ['doc1', 'doc2'], + }, + apiSidebar: ['doc3', 'doc4'], +}; +``` + +When browsing `doc1` or `doc2`, the `tutorialSidebar` will be displayed; when browsing `doc3` or `doc4`, the `apiSidebar` will be displayed. + +## Understanding sidebar association {#sidebar-association} + +Following the example above, if a `commonDoc` is included in both sidebars: + +```js title="sidebars.js" +export default { + tutorialSidebar: { + 'Category A': ['doc1', 'doc2', 'commonDoc'], + }, + apiSidebar: ['doc3', 'doc4', 'commonDoc'], +}; +``` + +How does Docusaurus know which sidebar to display when browsing `commonDoc`? Answer: it doesn't, and we don't guarantee which sidebar it will pick. + +When you add doc Y to sidebar X, it creates a two-way binding: sidebar X contains a link to doc Y, and when browsing doc Y, sidebar X will be displayed. But sometimes, we want to break either implicit binding: + +1. _How do I generate a link to doc Y in sidebar X without making sidebar X displayed on Y?_ For example, when I include doc Y in multiple sidebars as in the example above, and I want to explicitly tell Docusaurus to display one sidebar? +2. _How do I make sidebar X displayed when browsing doc Y, but sidebar X shouldn't contain the link to Y?_ For example, when Y is a "doc home page" and the sidebar is purely used for navigation? + +Front matter option `displayed_sidebar` will forcibly set the sidebar association. For the same example, you can still use doc shorthands without any special configuration: + +```js title="sidebars.js" +export default { + tutorialSidebar: { + 'Category A': ['doc1', 'doc2'], + }, + apiSidebar: ['doc3', 'doc4'], +}; +``` + +And then add a front matter: + +```md title="commonDoc.md" +--- +displayed_sidebar: apiSidebar +--- +``` + +Which explicitly tells Docusaurus to display `apiSidebar` when browsing `commonDoc`. Using the same method, you can make sidebar X which doesn't contain doc Y appear on doc Y: + +```md title="home.md" +--- +displayed_sidebar: tutorialSidebar +--- +``` + +Even when `tutorialSidebar` doesn't contain a link to `home`, it will still be displayed when viewing `home`. + +If you set `displayed_sidebar: null`, no sidebar will be displayed whatsoever on this page, and subsequently, no pagination either. + +## Generating pagination {#generating-pagination} + +Docusaurus uses the sidebar to generate the "next" and "previous" pagination links at the bottom of each doc page. It strictly uses the sidebar that is displayed: if no sidebar is associated, it doesn't generate pagination either. However, the docs linked as "next" and "previous" are not guaranteed to display the same sidebar: they are included in this sidebar, but in their front matter, they may have a different `displayed_sidebar`. + +If a sidebar is displayed by setting `displayed_sidebar` front matter, and this sidebar doesn't contain the doc itself, no pagination is displayed. + +You can customize pagination with front matter `pagination_next` and `pagination_prev`. Consider this sidebar: + +```js title="sidebars.js" +export default { + tutorial: [ + 'introduction', + { + installation: ['windows', 'linux', 'macos'], + }, + 'getting-started', + ], +}; +``` + +The pagination next link on "windows" points to "linux", but that doesn't make sense: you would want readers to proceed to "getting started" after installation. In this case, you can set the pagination manually: + +```md title="windows.md" +--- +# highlight-next-line +pagination_next: getting-started +--- + +# Installation on Windows +``` + +You can also disable displaying a pagination link with `pagination_next: null` or `pagination_prev: null`. + +The pagination label by default is the sidebar label. You can use the front matter `pagination_label` to customize how this doc appears in the pagination. + +## The `ref` item {#sidebar-item-ref} + +The `ref` type is identical to the [`doc` type](./items.mdx#sidebar-item-doc) in every way, except that it doesn't participate in generating navigation metadata. It only registers itself as a link. When [generating pagination](#generating-pagination) and [displaying sidebar](#sidebar-association), `ref` items are completely ignored. + +It is particularly useful where you wish to link to the same document from multiple sidebars. The document only belongs to one sidebar (the one where it's registered as `type: 'doc'` or from an autogenerated directory), but its link will appear in all sidebars that it's registered in. + +Consider this example: + +```js title="sidebars.js" +export default { + tutorialSidebar: { + 'Category A': [ + 'doc1', + 'doc2', + // highlight-next-line + {type: 'ref', id: 'commonDoc'}, + 'doc5', + ], + }, + apiSidebar: ['doc3', 'doc4', 'commonDoc'], +}; +``` + +You can think of the `ref` type as the equivalent to doing the following: + +- Setting `displayed_sidebar: tutorialSidebar` for `commonDoc` (`ref` is ignored in sidebar association) +- Setting `pagination_next: doc5` for `doc2` and setting `pagination_prev: doc2` for `doc5` (`ref` is ignored in pagination generation) diff --git a/website/versioned_docs/version-3.9.0/guides/docs/versioning.mdx b/website/versioned_docs/version-3.9.0/guides/docs/versioning.mdx new file mode 100644 index 0000000000..196f7a3790 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/docs/versioning.mdx @@ -0,0 +1,375 @@ +--- +slug: /versioning +--- + +# Versioning + +You can use the versioning CLI to create a new documentation version based on the latest content in the `docs` directory. That specific set of documentation will then be preserved and accessible even as the documentation in the `docs` directory continues to evolve. + +```mdx-code-block +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +``` + +:::warning + +Think about it before starting to version your documentation - it can become difficult for contributors to help improve it! + +::: + +Most of the time, you don't need versioning as it will just increase your build time, and introduce complexity to your codebase. Versioning is **best suited for websites with high-traffic and rapid changes to documentation between versions**. If your documentation rarely changes, don't add versioning to your documentation. + +To better understand how versioning works and see if it suits your needs, you can read on below. + +## Overview {#overview} + +A typical versioned doc site looks like below: + +```bash +website +├── sidebars.json # sidebar for the current docs version +├── docs # docs directory for the current docs version +│ ├── foo +│ │ └── bar.md # https://mysite.com/docs/next/foo/bar +│ └── hello.md # https://mysite.com/docs/next/hello +├── versions.json # file to indicate what versions are available +├── versioned_docs +│ ├── version-1.1.0 +│ │ ├── foo +│ │ │ └── bar.md # https://mysite.com/docs/foo/bar +│ │ └── hello.md +│ └── version-1.0.0 +│ ├── foo +│ │ └── bar.md # https://mysite.com/docs/1.0.0/foo/bar +│ └── hello.md +├── versioned_sidebars +│ ├── version-1.1.0-sidebars.json +│ └── version-1.0.0-sidebars.json +├── docusaurus.config.js +└── package.json +``` + +The `versions.json` file is a list of version names, ordered from newest to oldest. + +The table below explains how a versioned file maps to its version and the generated URL. + +| Path | Version | URL | +| --------------------------------------- | -------------- | ----------------- | +| `versioned_docs/version-1.0.0/hello.md` | 1.0.0 | /docs/1.0.0/hello | +| `versioned_docs/version-1.1.0/hello.md` | 1.1.0 (latest) | /docs/hello | +| `docs/hello.md` | current | /docs/next/hello | + +:::tip + +The files in the `docs` directory belong to the `current` docs version. + +By default, the `current` docs version is labeled as `Next` and hosted under `/docs/next/*`, but it is entirely configurable to fit your project's release lifecycle. + +::: + +### Terminology {#terminology} + +Note the terminology we use here. + +
    +
    + Current version +
    +
    + {'The version placed in the '} + ./docs + {' folder.'} +
    +
    + Latest version / last version +
    +
    + {'The version served by default for docs navbar items. Usually has path '} + /docs + {'.'} +
    +
    + +Current version is defined by the **file system location**, while latest version is defined by the **the navigation behavior**. They may or may not be the same version! (And the default configuration, as shown in the table above, would treat them as different: current version at `/docs/next` and latest at `/docs`.) + +## Tutorials {#tutorials} + +### Tagging a new version {#tagging-a-new-version} + +1. First, make sure the current docs version (the `./docs` directory) is ready to be frozen. +2. Enter a new version number. + +```bash npm2yarn +npm run docusaurus docs:version 1.1.0 +``` + +When tagging a new version, the document versioning mechanism will: + +- Copy the full `docs/` folder contents into a new `versioned_docs/version-[versionName]/` folder. +- Create a versioned sidebars file based from your current [sidebar](./sidebar/index.mdx) configuration (if it exists) - saved as `versioned_sidebars/version-[versionName]-sidebars.json`. +- Append the new version number to `versions.json`. + +### Creating new docs {#creating-new-docs} + +1. Place the new file into the corresponding version folder. +2. Include the reference to the new file in the corresponding sidebar file according to the version number. + +```mdx-code-block + + +``` + +```bash +# The new file. +docs/new.md + +# Edit the corresponding sidebar file. +sidebars.js +``` + +```mdx-code-block + + +``` + +```bash +# The new file. +versioned_docs/version-1.0.0/new.md + +# Edit the corresponding sidebar file. +versioned_sidebars/version-1.0.0-sidebars.json +``` + +```mdx-code-block + + +``` + +:::tip + +Versioned sidebar files are, like standard sidebar files, relative to the content root for the given version — so for the example above, your versioned sidebar file may look like: + +```json +{ + "sidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} +``` + +or for a manual sidebar: + +```json +{ + "sidebar": [ + { + "type": "doc", + "id": "new", + "label": "New" + } + ] +} +``` + +::: + +### Updating an existing version {#updating-an-existing-version} + +You can update multiple docs versions at the same time because each directory in `versioned_docs/` represents specific routes when published. + +1. Edit any file. +2. Commit and push changes. +3. It will be published to the version. + +Example: When you change any file in `versioned_docs/version-2.6/`, it will only affect the docs for version `2.6`. + +### Deleting an existing version {#deleting-an-existing-version} + +You can delete/remove versions as well. + +1. Remove the version from `versions.json`. + +Example: + +```diff +[ + "2.0.0", + "1.9.0", + // highlight-next-line +- "1.8.0" +] +``` + +2. Delete the versioned docs directory. Example: `versioned_docs/version-1.8.0`. +3. Delete the versioned sidebars file. Example: `versioned_sidebars/version-1.8.0-sidebars.json`. + +## Configuring versioning behavior {#configuring-versioning-behavior} + +The "current" version is the version name for the `./docs` folder. There are different ways to manage versioning, but two very common patterns are: + +- You release v1, and start immediately working on v2 (including its docs). In this case, the **current version** is v2, which is in the `./docs` source folder, and can be browsed at `example.com/docs/next`. The **latest version** is v1, which is in the `./versioned_docs/version-1` source folder, and is browsed by most of your users at `example.com/docs`. +- You release v1, and will maintain it for some time before thinking about v2. In this case, the **current version** and **latest version** will both be point to v1, since the v2 docs doesn't even exist yet! + +Docusaurus defaults work great for the first use case. We will label the current version as "next" and you can even choose not to publish it. + +**For the 2nd use case**: if you release v1 and don't plan to work on v2 anytime soon, instead of versioning v1 and having to maintain the docs in 2 folders (`./docs` + `./versioned_docs/version-1.0.0`), you may consider "pretending" that the current version is a cut version by giving it a path and a label: + +```js title="docusaurus.config.js" +export default { + presets: [ + '@docusaurus/preset-classic', + docs: { + // highlight-start + lastVersion: 'current', + versions: { + current: { + label: '1.0.0', + path: '1.0.0', + }, + }, + // highlight-end + }, + ], +}; +``` + +The docs in `./docs` will be served at `/docs/1.0.0` instead of `/docs/next`, and `1.0.0` will become the default version we link to in the navbar dropdown, and you will only need to maintain a single `./docs` folder. + +We offer these plugin options to customize versioning behavior: + +- `disableVersioning`: Explicitly disable versioning even with versions. This will make the site only include the current version. +- `includeCurrentVersion`: Include the current version (the `./docs` folder) of your docs. + - **Tip**: turn it off if the current version is a work-in-progress, not ready to be published. +- `lastVersion`: Sets which version "latest version" (the `/docs` route) refers to. + - **Tip**: `lastVersion: 'current'` makes sense if your current version refers to a major version that's constantly patched and released. The actual route base path and label of the latest version are configurable. +- `onlyIncludeVersions`: Defines a subset of versions from `versions.json` to be deployed. + - **Tip**: limit to 2 or 3 versions in dev and deploy previews to improve startup and build time. +- `versions`: A dictionary of version metadata. For each version, you can customize the following: + - `label`: the label displayed in the versions dropdown and banner. + - `path`: the route base path of this version. By default, latest version has `/` and current version has `/next`. + - `banner`: one of `'none'`, `'unreleased'`, and `'unmaintained'`. Determines what's displayed at the top of every doc page. Any version above the latest version would be "unreleased", and any version below would be "unmaintained". + - `badge`: show a badge with the version name at the top of a doc of that version. + - `className`: add a custom `className` to the `` element of doc pages of that version. + +See [docs plugin configuration](../../api/plugins/plugin-content-docs.mdx#configuration) for more details. + +## Navbar items {#navbar-items} + +We offer several docs navbar items to help you quickly set up navigation without worrying about versioned routes. + +- [`doc`](../../api/themes/theme-configuration.mdx#navbar-doc-link): a link to a doc. +- [`docSidebar`](../../api/themes/theme-configuration.mdx#navbar-doc-sidebar): a link to the first item in a sidebar. +- [`docsVersion`](../../api/themes/theme-configuration.mdx#navbar-docs-version): a link to the main doc of the currently viewed version. +- [`docsVersionDropdown`](../../api/themes/theme-configuration.mdx#navbar-docs-version-dropdown): a dropdown containing all the versions available. + +These links would all look for an appropriate version to link to, in the following order: + +1. **Active version**: the version that the user is currently browsing, if she is on a page provided by this doc plugin. If she's not on a doc page, fall back to... +2. **Preferred version**: the version that the user last viewed. If there's no history, fall back to... +3. **Latest version**: the default version that we navigate to, configured by the `lastVersion` option. + +## `docsVersionDropdown` {#docsVersionDropdown} + +By default, the [`docsVersionDropdown`](../../api/themes/theme-configuration.mdx#navbar-docs-version-dropdown) displays a dropdown with all the available docs versions. + +The `versions` attribute allows you to display a subset of the available docs versions in a given order: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + items: [ + { + type: 'docsVersionDropdown', + // highlight-start + versions: ['current', '3.0', '2.0'], + // highlight-end + }, + ], + }, + }, +}; +``` + +Passing a `versions` object, lets you override the display label of each version: + +```js title="docusaurus.config.js" +export default { + themeConfig: { + navbar: { + items: [ + { + type: 'docsVersionDropdown', + // highlight-start + versions: { + current: {label: 'Version 4.0'}, + '3.0': {label: 'Version 3.0'}, + '2.0': {label: 'Version 2.0'}, + }, + // highlight-end + }, + ], + }, + }, +}; +``` + +## Recommended practices {#recommended-practices} + +### Version your documentation only when needed {#version-your-documentation-only-when-needed} + +For example, you are building documentation for your npm package `foo` and you are currently in version 1.0.0. You then release a patch version for a minor bug fix and it's now 1.0.1. + +Should you cut a new documentation version 1.0.1? **You probably shouldn't**. 1.0.1 and 1.0.0 docs shouldn't differ according to semver because there are no new features!. Cutting a new version for it will only just create unnecessary duplicated files. + +### Keep the number of versions small {#keep-the-number-of-versions-small} + +As a good rule of thumb, try to keep the number of your versions below 10. You will **very likely** to have a lot of obsolete versioned documentation that nobody even reads anymore. For example, [Jest](https://jestjs.io/versions) is currently in version `27.4`, and only maintains several latest documentation versions with the lowest being `25.X`. Keep it small 😊 + +:::tip archive older versions + +If you deploy your site on a Jamstack provider (e.g. [Netlify](../../deployment.mdx)), the provider will save each production build as a snapshot under an immutable URL. You can include archived versions that will never be rebuilt as external links to these immutable URLs. The Jest website and the Docusaurus website both use such pattern to keep the number of actively built versions low. + +::: + +### Use absolute import within the docs {#use-absolute-import-within-the-docs} + +Don't use relative paths import within the docs. Because when we cut a version the paths no longer work (the nesting level is different, among other reasons). You can utilize the `@site` alias provided by Docusaurus that points to the `website` directory. Example: + +```diff +- import Foo from '../src/components/Foo'; ++ import Foo from '@site/src/components/Foo'; +``` + +### Link docs by file paths {#link-docs-by-file-paths} + +Refer to other docs by relative file paths with the `.md` extension, so that Docusaurus can rewrite them to actual URL paths during building. Files will be linked to the correct corresponding version. + +```md +The [@hello](hello.mdx#paginate) document is great! + +See the [Tutorial](../getting-started/tutorial.mdx) for more info. +``` + +### Global or versioned collocated assets {#global-or-versioned-collocated-assets} + +You should decide if assets like images and files are per-version or shared between versions. + +If your assets should be versioned, put them in the docs version, and use relative paths: + +```md +![img alt](./myImage.png) + +[download this file](./file.pdf) +``` + +If your assets are global, put them in `/static` and use absolute paths: + +```md +![img alt](/myImage.png) + +[download this file](/file.pdf) +``` diff --git a/website/versioned_docs/version-3.9.0/guides/markdown-features/_markdown-partial-example.mdx b/website/versioned_docs/version-3.9.0/guides/markdown-features/_markdown-partial-example.mdx new file mode 100644 index 0000000000..5eb3f3bf11 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/markdown-features/_markdown-partial-example.mdx @@ -0,0 +1,3 @@ +Hello {props.name} + +This is text some content from `_markdown-partial-example.md`. diff --git a/website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-admonitions.mdx b/website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-admonitions.mdx new file mode 100644 index 0000000000..39353f5873 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-admonitions.mdx @@ -0,0 +1,372 @@ +--- +id: admonitions +description: Handling admonitions/callouts in Docusaurus Markdown +slug: /markdown-features/admonitions +--- + +# Admonitions + +import BrowserWindow from '@site/src/components/BrowserWindow'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Admonition from '@theme/Admonition'; + +In addition to the basic Markdown syntax, we have a special admonitions syntax by wrapping text with a set of 3 colons, followed by a label denoting its type. + +Example: + +```md +:::note + +Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + +::: + +:::tip + +Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + +::: + +:::info + +Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + +::: + +:::warning + +Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + +::: + +:::danger + +Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + +::: +``` + +```mdx-code-block + + +:::note + +Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + +::: + +:::tip + +Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + +::: + +:::info + +Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + +::: + +:::warning + +Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + +::: + +:::danger + +Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + +::: + + +``` + +## Usage with Prettier {#usage-with-prettier} + +If you use [Prettier](https://prettier.io) to format your Markdown files, Prettier might auto-format your code to invalid admonition syntax. To avoid this problem, add empty lines around the starting and ending directives. This is also why the examples we show here all have empty lines around the content. + +{/* prettier-ignore */} +```md + +:::note + +Hello world + +::: + + +:::note +Hello world +::: + + +::: note Hello world::: +``` + +## Specifying title {#specifying-title} + +You may also specify an optional title. + +```md +:::note[Your Title **with** some _Markdown_ `syntax`!] + +Some **content** with some _Markdown_ `syntax`. + +::: +``` + +```mdx-code-block + + +:::note[Your Title **with** some _Markdown_ `syntax`!] + +Some **content** with some _Markdown_ `syntax`. + +::: + + +``` + +## Nested admonitions {#nested-admonitions} + +Admonitions can be nested. Use more colons `:` for each parent admonition level. + +```md +:::::info Parent + +Parent content + +::::danger Child + +Child content + +:::tip Deep Child + +Deep child content + +::: + +:::: + +::::: +``` + +```mdx-code-block + + +:::::info Parent + +Parent content + +::::danger Child + +Child content + +:::tip Deep Child + +Deep child content + +::: + +:::: + +::::: + + +``` + +## Admonitions with MDX {#admonitions-with-mdx} + +You can use MDX inside admonitions too! + +```jsx +import Tabs from '@theme/Tabs'; + +import TabItem from '@theme/TabItem'; + +:::tip[Use tabs in admonitions] + + + This is an apple 🍎 + This is an orange 🍊 + This is a banana 🍌 + + +::: +``` + +```mdx-code-block + + +:::tip[Use tabs in admonitions] + + + This is an apple 🍎 + This is an orange 🍊 + This is a banana 🍌 + + +::: + + +``` + +## Usage in JSX {#usage-in-jsx} + +Outside of Markdown, you can use the `@theme/Admonition` component to get the same output. + +```jsx title="MyReactPage.jsx" +import Admonition from '@theme/Admonition'; + +export default function MyReactPage() { + return ( +
    + +

    Some information

    +
    +
    + ); +} +``` + +The types that are accepted are the same as above: `note`, `tip`, `danger`, `info`, `warning`. Optionally, you can specify an icon by passing a JSX element or a string, or a title: + +```jsx title="MyReactPage.jsx" + + Use plugins to introduce shorter syntax for the most commonly used JSX + elements in your project. + +``` + +```mdx-code-block + + + Use plugins to introduce shorter syntax for the most commonly used JSX + elements in your project. + + +``` + +## Customizing admonitions {#customizing-admonitions} + +There are two kinds of customizations possible with admonitions: **parsing** and **rendering**. + +### Customizing rendering behavior {#customizing-rendering-behavior} + +You can customize how each individual admonition type is rendered through [swizzling](../../swizzling.mdx). You can often achieve your goal through a simple wrapper. For example, in the follow example, we swap out the icon for `info` admonitions only. + +```jsx title="src/theme/Admonition.js" +import React from 'react'; +import Admonition from '@theme-original/Admonition'; +import MyCustomNoteIcon from '@site/static/img/info.svg'; + +export default function AdmonitionWrapper(props) { + if (props.type !== 'info') { + return ; + } + return } {...props} />; +} +``` + +### Customizing parsing behavior {#customizing-parsing-behavior} + +Admonitions are implemented with a [Remark plugin](./markdown-features-plugins.mdx). The plugin is designed to be configurable. To customize the Remark plugin for a specific content plugin (docs, blog, pages), pass the options through the `admonitions` key. + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + admonitions: { + keywords: ['note', 'tip', 'info', 'warning', 'danger'], + extendDefaults: true, + }, + }, + }, + ], + ], +}; +``` + +The plugin accepts the following options: + +- `keywords`: An array of keywords that can be used as the type for the admonition. +- `extendDefaults`: Should the provided options (such as `keywords`) be merged into the existing defaults. Defaults to `true`. + +The `keyword` will be passed as the `type` prop of the `Admonition` component. + +### Custom admonition type components {#custom-admonition-type-components} + +By default, the theme doesn't know what do to with custom admonition keywords such as `:::my-custom-admonition`. It is your responsibility to map each admonition keyword to a React component so that the theme knows how to render them. + +If you registered a new admonition type `my-custom-admonition` via the following config: + +```js title="docusaurus.config.js" +export default { + // ... + presets: [ + [ + 'classic', + { + // ... + docs: { + admonitions: { + keywords: ['my-custom-admonition'], + extendDefaults: true, + }, + }, + }, + ], + ], +}; +``` + +You can provide the corresponding React component for `:::my-custom-admonition` by creating the following file (unfortunately, since it's not a React component file, it's not swizzlable): + +```js title="src/theme/Admonition/Types.js" +import React from 'react'; +import DefaultAdmonitionTypes from '@theme-original/Admonition/Types'; + +function MyCustomAdmonition(props) { + return ( +
    +
    {props.title}
    +
    {props.children}
    +
    + ); +} + +const AdmonitionTypes = { + ...DefaultAdmonitionTypes, + + // Add all your custom admonition types here... + // You can also override the default ones if you want + 'my-custom-admonition': MyCustomAdmonition, +}; + +export default AdmonitionTypes; +``` + +Now you can use your new admonition keyword in a Markdown file, and it will be parsed and rendered with your custom logic: + +```md +:::my-custom-admonition[My Title] + +It works! + +::: +``` + + + +:::my-custom-admonition[My Title] + +It works! + +::: + + diff --git a/website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-assets.mdx b/website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-assets.mdx new file mode 100644 index 0000000000..fa75c8f676 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-assets.mdx @@ -0,0 +1,235 @@ +--- +id: assets +description: Handling assets in Docusaurus Markdown +slug: /markdown-features/assets +--- + +# Assets + +import BrowserWindow from '@site/src/components/BrowserWindow'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Sometimes you want to link to assets (e.g. docx files, images...) directly from Markdown files, and it is convenient to co-locate the asset next to the Markdown file using it. + +Let's imagine the following file structure: + +``` +# Your doc +/website/docs/myFeature.mdx + +# Some assets you want to use +/website/docs/assets/docusaurus-asset-example-banner.png +/website/docs/assets/docusaurus-asset-example.docx +``` + +## Images {#images} + +You can display images in three different ways: Markdown syntax, CJS require, or ES imports syntax. + +```mdx-code-block + + +``` + +Display images using simple Markdown syntax: + +```md +![Example banner](./assets/docusaurus-asset-example-banner.png) +``` + +```mdx-code-block + + +``` + +Display images using inline CommonJS `require` in JSX image tag: + +```jsx +Example banner +``` + +```mdx-code-block + + +``` + +Display images using ES `import` syntax and JSX image tag: + +```jsx +import myImageUrl from './assets/docusaurus-asset-example-banner.png'; + +Example banner; +``` + +```mdx-code-block + + +``` + +All of the above result in displaying the image: + + + +![My image alternative text](../../assets/docusaurus-asset-example-banner.png) + + + +:::note + +If you are using [@docusaurus/plugin-ideal-image](../../api/plugins/plugin-ideal-image.mdx), you need to use the dedicated image component, as documented. + +::: + +## Files {#files} + +In the same way, you can link to existing assets by `require`'ing them and using the returned URL in `video`s, `a` anchor links, etc. + +```md +# My Markdown page + +
    Download this docx + +or + +[Download this docx using Markdown](./assets/docusaurus-asset-example.docx) +``` + + + + + {'Download this docx'} + + +[Download this docx using Markdown](../../assets/docusaurus-asset-example.docx) + + + +:::info Markdown links are always file paths + +If you use the Markdown image or link syntax, all asset paths will be resolved as file paths by Docusaurus and automatically converted to `require()` calls. You don't need to use `require()` in Markdown unless you use the JSX syntax, which you do have to handle yourself. + +::: + +## Inline SVGs {#inline-svgs} + +Docusaurus supports inlining SVGs out of the box. + +```jsx +import DocusaurusSvg from './docusaurus.svg'; + +; +``` + + + +import DocusaurusSvg from '@site/static/img/docusaurus.svg'; + + + + + +This can be useful if you want to alter the part of the SVG image via CSS. For example, you can change one of the SVG colors based on the current theme. + +```jsx +import DocusaurusSvg from './docusaurus.svg'; + +; +``` + +```css +[data-theme='light'] .themedDocusaurus [fill='#FFFF50'] { + fill: greenyellow; +} + +[data-theme='dark'] .themedDocusaurus [fill='#FFFF50'] { + fill: seagreen; +} +``` + + + + + +## Themed Images {#themed-images} + +Docusaurus supports themed images: the `ThemedImage` component (included in the themes) allows you to switch the image source based on the current theme. + +```jsx +import useBaseUrl from '@docusaurus/useBaseUrl'; +import ThemedImage from '@theme/ThemedImage'; + +; +``` + +```mdx-code-block +import useBaseUrl from '@docusaurus/useBaseUrl'; +import ThemedImage from '@theme/ThemedImage'; + + + + +``` + +### GitHub-style themed images {#github-style-themed-images} + +GitHub uses its own [image theming approach](https://github.blog/changelog/2021-11-24-specify-theme-context-for-images-in-markdown/) with path fragments, which you can easily implement yourself. + +To toggle the visibility of an image using the path fragment (for GitHub, it's `#gh-dark-mode-only` and `#gh-light-mode-only`), add the following to your custom CSS (you can also use your own suffix if you don't want to be coupled to GitHub): + +```css title="src/css/custom.css" +[data-theme='light'] img[src$='#gh-dark-mode-only'], +[data-theme='dark'] img[src$='#gh-light-mode-only'] { + display: none; +} +``` + +```md +![Docusaurus themed image](/img/docusaurus_keytar.svg#gh-light-mode-only)![Docusaurus themed image](/img/docusaurus_speed.svg#gh-dark-mode-only) +``` + + + +![Docusaurus themed image](/img/docusaurus_keytar.svg#gh-light-mode-only)![Docusaurus themed image](/img/docusaurus_speed.svg#gh-dark-mode-only) + + + +## Static assets {#static-assets} + +If a Markdown link or image has an absolute path, the path will be seen as a file path and will be resolved from the static directories. For example, if you have configured [static directories](../../static-assets.mdx) to be `['public', 'static']`, then for the following image: + +```md title="my-doc.md" +![An image from the static](/img/docusaurus.png) +``` + +Docusaurus will try to look for it in both `static/img/docusaurus.png` and `public/img/docusaurus.png`. The link will then be converted to a `require()` call instead of staying as a URL. This is desirable in two regards: + +1. You don't have to worry about the base URL, which Docusaurus will take care of when serving the asset; +2. The image enters Webpack's build pipeline and its name will be appended by a hash, which enables browsers to aggressively cache the image and improves your site's performance. + +If you intend to write URLs, you can use the `pathname://` protocol to disable automatic asset linking. + +```md +![banner](pathname:///img/docusaurus-asset-example-banner.png) +``` + +This link will be generated as `banner`, without any processing or file existence checking. diff --git a/website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-code-blocks.mdx b/website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-code-blocks.mdx new file mode 100644 index 0000000000..f55442b973 --- /dev/null +++ b/website/versioned_docs/version-3.9.0/guides/markdown-features/markdown-features-code-blocks.mdx @@ -0,0 +1,864 @@ +--- +id: code-blocks +description: Handling code blocks in Docusaurus Markdown +slug: /markdown-features/code-blocks +--- + +# Code blocks + +import BrowserWindow from '@site/src/components/BrowserWindow'; +import CodeBlock from '@theme/CodeBlock'; + +Code blocks within documentation are super-powered 💪. + +## Code title {#code-title} + +You can add a title to the code block by adding a `title` key after the language (leave a space between them). + +````md +```jsx title="/src/components/HelloCodeTitle.js" +function HelloCodeTitle(props) { + return

    Hello, {props.name}

    ; +} +``` +```` + +```mdx-code-block + +``` + +```jsx title="/src/components/HelloCodeTitle.js" +function HelloCodeTitle(props) { + return

    Hello, {props.name}

    ; +} +``` + +```mdx-code-block +
    +``` + +## Syntax highlighting {#syntax-highlighting} + +Code blocks are text blocks wrapped around by strings of 3 backticks. You may check out [this reference](https://mdxjs.com/docs/) for the specifications of MDX. + +````md +```js +console.log('Every repo must come with a mascot.'); +``` +```` + +Use the matching language meta string for your code block, and Docusaurus will pick up syntax highlighting automatically, powered by [Prism React Renderer](https://github.com/FormidableLabs/prism-react-renderer). + + + +```js +console.log('Every repo must come with a mascot.'); +``` + + + +### Theming {#theming} + +By default, the Prism [syntax highlighting theme](https://github.com/FormidableLabs/prism-react-renderer#theming) we use is [Palenight](https://github.com/FormidableLabs/prism-react-renderer/blob/master/packages/prism-react-renderer/src/themes/palenight.ts). You can change this to another theme by passing `theme` field in `prism` as `themeConfig` in your docusaurus.config.js. + +For example, if you prefer to use the `dracula` highlighting theme: + +```js title="docusaurus.config.js" +import {themes as prismThemes} from 'prism-react-renderer'; + +export default { + themeConfig: { + prism: { + // highlight-next-line + theme: prismThemes.dracula, + }, + }, +}; +``` + +Because a Prism theme is just a JS object, you can also write your own theme if you are not satisfied with the default. Docusaurus enhances the `github` and `vsDark` themes to provide richer highlight, and you can check our implementations for the [light](https://github.com/facebook/docusaurus/blob/main/website/src/utils/prismLight.ts) and [dark](https://github.com/facebook/docusaurus/blob/main/website/src/utils/prismDark.ts) code block themes. + +### Supported Languages {#supported-languages} + +By default, Docusaurus comes with a subset of [commonly used languages](https://github.com/FormidableLabs/prism-react-renderer/blob/master/packages/generate-prism-languages/index.ts#L10-L25). + +:::warning + +Some popular languages like Java, C#, or PHP are not enabled by default. + +::: + +To add syntax highlighting for any of the other [Prism-supported languages](https://prismjs.com/#supported-languages), define it in an array of additional languages. + +:::note + +Each additional language has to be a valid Prism component name. For example, Prism would map the _language_ `cs` to `csharp`, but only `prism-csharp.js` exists as a _component_, so you need to use `additionalLanguages: ['csharp']`. You can look into `node_modules/prismjs/components` to find all components (languages) available. + +::: + +For example, if you want to add highlighting for the PowerShell language: + +```js title="docusaurus.config.js" +export default { + // ... + themeConfig: { + prism: { + // highlight-next-line + additionalLanguages: ['powershell'], + }, + // ... + }, +}; +``` + +After adding `additionalLanguages`, restart Docusaurus. + +If you want to add highlighting for languages not yet supported by Prism, you can swizzle `prism-include-languages`: + +```bash npm2yarn +npm run swizzle @docusaurus/theme-classic prism-include-languages +``` + +It will produce `prism-include-languages.js` in your `src/theme` folder. You can add highlighting support for custom languages by editing `prism-include-languages.js`: + +```js title="src/theme/prism-include-languages.js" +const prismIncludeLanguages = (Prism) => { + // ... + + additionalLanguages.forEach((lang) => { + require(`prismjs/components/prism-${lang}`); + }); + + // highlight-next-line + require('/path/to/your/prism-language-definition'); + + // ... +}; +``` + +You can refer to [Prism's official language definitions](https://github.com/PrismJS/prism/tree/master/components) when you are writing your own language definitions. + +When adding a custom language definition, you do not need to add the language to the `additionalLanguages` config array, since Docusaurus only looks up the `additionalLanguages` strings in languages that Prism provides. Adding the language import in `prism-include-languages.js` is sufficient. + +## Line highlighting {#line-highlighting} + +### Highlighting with comments {#highlighting-with-comments} + +You can use comments with `highlight-next-line`, `highlight-start`, and `highlight-end` to select which lines are highlighted. + +````md +```js +function HighlightSomeText(highlight) { + if (highlight) { + // highlight-next-line + return 'This text is highlighted!'; + } + + return 'Nothing highlighted'; +} + +function HighlightMoreText(highlight) { + // highlight-start + if (highlight) { + return 'This range is highlighted!'; + } + // highlight-end + + return 'Nothing highlighted'; +} +``` +```` + +```mdx-code-block + +``` + +```js +function HighlightSomeText(highlight) { + if (highlight) { + // highlight-next-line + return 'This text is highlighted!'; + } + + return 'Nothing highlighted'; +} + +function HighlightMoreText(highlight) { + // highlight-start + if (highlight) { + return 'This range is highlighted!'; + } + // highlight-end + + return 'Nothing highlighted'; +} +``` + +```mdx-code-block + +``` + +Supported commenting syntax: + +| Style | Syntax | +| ---------- | ------------------------ | +| C-style | `/* ... */` and `// ...` | +| JSX-style | `{/* ... */}` | +| Bash-style | `# ...` | +| HTML-style | `` | + +We will do our best to infer which set of comment styles to use based on the language, and default to allowing _all_ comment styles. If there's a comment style that is not currently supported, we are open to adding them! Pull requests welcome. Note that different comment styles have no semantic difference, only their content does. + +You can set your own background color for highlighted code line in your `src/css/custom.css` which will better fit to your selected syntax highlighting theme. The color given below works for the default highlighting theme (Palenight), so if you are using another theme, you will have to tweak the color accordingly. + +```css title="/src/css/custom.css" +:root { + --docusaurus-highlighted-code-line-bg: rgb(72, 77, 91); +} + +/* If you have a different syntax highlighting theme for dark mode. */ +[data-theme='dark'] { + /* Color which works with dark mode syntax highlighting theme */ + --docusaurus-highlighted-code-line-bg: rgb(100, 100, 100); +} +``` + +If you also need to style the highlighted code line in some other way, you can target on `theme-code-block-highlighted-line` CSS class. + +### Highlighting with metadata string {#highlighting-with-metadata-string} + +You can also specify highlighted line ranges within the language meta string (leave a space after the language). To highlight multiple lines, separate the line numbers by commas or use the range syntax to select a chunk of lines. This feature uses the `parse-number-range` library and you can find [more syntax](https://www.npmjs.com/package/parse-numeric-range) on their project details. + +````md +```jsx {1,4-6,11} +import React from 'react'; + +function MyComponent(props) { + if (props.isBar) { + return
    Bar
    ; + } + + return
    Foo
    ; +} + +export default MyComponent; +``` +```` + +```mdx-code-block + +``` + +```jsx {1,4-6,11} +import React from 'react'; + +function MyComponent(props) { + if (props.isBar) { + return
    Bar
    ; + } + + return
    Foo
    ; +} + +export default MyComponent; +``` + +```mdx-code-block +
    +``` + +:::tip prefer comments + +Prefer highlighting with comments where you can. By inlining highlight in the code, you don't have to manually count the lines if your code block becomes long. If you add/remove lines, you also don't have to offset your line ranges. + +````diff +- ```jsx {3} ++ ```jsx {4} + function HighlightSomeText(highlight) { + if (highlight) { ++ console.log('Highlighted text found'); + return 'This text is highlighted!'; + } + + return 'Nothing highlighted'; + } + ``` +```` + +Below, we will introduce how the magic comment system can be extended to define custom directives and their functionalities. The magic comments would only be parsed if a highlight metastring is not present. + +::: + +### Custom magic comments {#custom-magic-comments} + +`// highlight-next-line` and `// highlight-start` etc. are called "magic comments", because they will be parsed and removed, and their purposes are to add metadata to the next line, or the section that the pair of start- and end-comments enclose. + +You can declare custom magic comments through theme config. For example, you can register another magic comment that adds a `code-block-error-line` class name: + +```mdx-code-block + + +``` + +```js +export default { + themeConfig: { + prism: { + magicComments: [ + // Remember to extend the default highlight class name as well! + { + className: 'theme-code-block-highlighted-line', + line: 'highlight-next-line', + block: {start: 'highlight-start', end: 'highlight-end'}, + }, + // highlight-start + { + className: 'code-block-error-line', + line: 'This will error', + }, + // highlight-end + ], + }, + }, +}; +``` + +```mdx-code-block + + +``` + +```css +.code-block-error-line { + background-color: #ff000020; + display: block; + margin: 0 calc(-1 * var(--ifm-pre-padding)); + padding: 0 var(--ifm-pre-padding); + border-left: 3px solid #ff000080; +} +``` + +```mdx-code-block + + +``` + +````md +In JavaScript, trying to access properties on `null` will error. + +```js +const name = null; +// This will error +console.log(name.toUpperCase()); +// Uncaught TypeError: Cannot read properties of null (reading 'toUpperCase') +``` +```` + +```mdx-code-block + + +``` + +```mdx-code-block + +``` + +In JavaScript, trying to access properties on `null` will error. + +```js +const name = null; +// This will error +console.log(name.toUpperCase()); +// Uncaught TypeError: Cannot read properties of null (reading 'toUpperCase') +``` + +```mdx-code-block + +``` + +If you use number ranges in metastring (the `{1,3-4}` syntax), Docusaurus will apply the **first `magicComments` entry**'s class name. This, by default, is `theme-code-block-highlighted-line`, but if you change the `magicComments` config and use a different entry as the first one, the meaning of the metastring range will change as well. + +You can disable the default line highlighting comments with `magicComments: []`. If there's no magic comment config, but Docusaurus encounters a code block containing a metastring range, it will error because there will be no class name to apply—the highlighting class name, after all, is just a magic comment entry. + +Every magic comment entry will contain three keys: `className` (required), `line`, which applies to the directly next line, or `block` (containing `start` and `end`), which applies to the entire block enclosed by the two comments. + +Using CSS to target the class can already do a lot, but you can unlock the full potential of this feature through [swizzling](../../swizzling.mdx). + +```bash npm2yarn +npm run swizzle @docusaurus/theme-classic CodeBlock/Line +``` + +The `Line` component will receive the list of class names, based on which you can conditionally render different markup. + +## Line numbering {#line-numbering} + +You can enable line numbering for your code block by using `showLineNumbers` key within the language meta string (don't forget to add space directly before the key). + +````md +```jsx showLineNumbers +import React from 'react'; + +export default function MyComponent(props) { + return
    Foo
    ; +} +``` +```` + +```mdx-code-block + +``` + +```jsx showLineNumbers +import React from 'react'; + +export default function MyComponent(props) { + return
    Foo
    ; +} +``` + +```mdx-code-block +
    +``` + +By default, the counter starts at line number 1. It's possible to pass a custom counter start value to split large code blocks for readability: + +````md +```jsx showLineNumbers=3 +export default function MyComponent(props) { + return
    Foo
    ; +} +``` +```` + +```mdx-code-block + +``` + +```jsx showLineNumbers=3 +export default function MyComponent(props) { + return
    Foo
    ; +} +``` + +```mdx-code-block +
    +``` + +## Interactive code editor {#interactive-code-editor} + +(Powered by [React Live](https://github.com/FormidableLabs/react-live)) + +You can create an interactive coding editor with the `@docusaurus/theme-live-codeblock` plugin. First, add the plugin to your package. + +```bash npm2yarn +npm install --save @docusaurus/theme-live-codeblock +``` + +You will also need to add the plugin to your `docusaurus.config.js`. + +```js {3} +export default { + // ... + themes: ['@docusaurus/theme-live-codeblock'], + // ... +}; +``` + +To use the plugin, create a code block with `live` attached to the language meta string. + +````md +```jsx live +function Clock(props) { + const [date, setDate] = useState(new Date()); + useEffect(() => { + const timerID = setInterval(() => tick(), 1000); + + return function cleanup() { + clearInterval(timerID); + }; + }); + + function tick() { + setDate(new Date()); + } + + return ( +
    +

    It is {date.toLocaleTimeString()}.

    +
    + ); +} +``` +```` + +The code block will be rendered as an interactive editor. Changes to the code will reflect on the result panel live. + +```mdx-code-block + +``` + +```jsx live +function Clock(props) { + const [date, setDate] = useState(new Date()); + useEffect(() => { + const timerID = setInterval(() => tick(), 1000); + + return function cleanup() { + clearInterval(timerID); + }; + }); + + function tick() { + setDate(new Date()); + } + + return ( +
    +

    It is {date.toLocaleTimeString()}.

    +
    + ); +} +``` + +```mdx-code-block +
    +``` + +### Imports {#imports} + +:::warning react-live and imports + +It is not possible to import components directly from the react-live code editor, you have to define available imports upfront. + +::: + +By default, all React imports are available. If you need more imports available, swizzle the react-live scope: + +```bash npm2yarn +npm run swizzle @docusaurus/theme-live-codeblock ReactLiveScope -- --eject +``` + +```jsx title="src/theme/ReactLiveScope/index.js" +import React from 'react'; + +// highlight-start +const ButtonExample = (props) => ( +