From ee9a213804d2bd7dd15d9bf3a041abfa56632e6e Mon Sep 17 00:00:00 2001 From: sebastienlorber Date: Thu, 17 Mar 2022 18:40:45 +0100 Subject: [PATCH 1/7] add useRouteContext --- .../src/index.d.ts | 6 ++ .../src/theme/Layout/index.tsx | 29 +++++++++ packages/docusaurus-types/src/index.d.ts | 10 ++++ .../src/client/exports/ComponentCreator.tsx | 14 ++++- .../src/client/exports/useRouteContext.tsx | 22 +++++++ .../docusaurus/src/client/routeContext.tsx | 60 +++++++++++++++++++ .../docusaurus/src/server/plugins/index.ts | 42 +++++++++---- .../__tests__/__snapshots__/base.test.ts.snap | 2 + project-words.txt | 1 + 9 files changed, 173 insertions(+), 13 deletions(-) create mode 100644 packages/docusaurus/src/client/exports/useRouteContext.tsx create mode 100644 packages/docusaurus/src/client/routeContext.tsx diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts index 31da0335637e..d8fbaa1b4b22 100644 --- a/packages/docusaurus-module-type-aliases/src/index.d.ts +++ b/packages/docusaurus-module-type-aliases/src/index.d.ts @@ -246,6 +246,12 @@ declare module '@docusaurus/useDocusaurusContext' { export default function useDocusaurusContext(): DocusaurusContext; } +declare module '@docusaurus/useRouteContext' { + import type {PluginRouteContext} from '@docusaurus/types'; + + export default function useRouteContext(): PluginRouteContext; +} + declare module '@docusaurus/useIsBrowser' { export default function useIsBrowser(): boolean; } diff --git a/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx b/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx index ce56fe8d01ec..e7bb0469e9df 100644 --- a/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx @@ -18,6 +18,33 @@ import type {Props} from '@theme/Layout'; import {ThemeClassNames, useKeyboardNavigation} from '@docusaurus/theme-common'; import ErrorPageContent from '@theme/ErrorPageContent'; import './styles.css'; +import useRouteContext from '@docusaurus/useRouteContext'; +import Head from '@docusaurus/Head'; + +function pluginNameToClassName(pluginName: string) { + return `plugin-${pluginName.replace( + new RegExp( + [ + 'docusaurus-plugin-content-', + 'docusaurus-plugin-', + 'docusaurus-theme-', + ].join('|'), + 'gi', + ), + '', + )}`; +} + +function PluginHtmlClassName() { + const routeContext = useRouteContext(); + const nameClass = pluginNameToClassName(routeContext.plugin.name); + const idClass = `plugin-id-${routeContext.plugin.id}`; + return ( + + + + ); +} export default function Layout(props: Props): JSX.Element { const {children, noFooter, wrapperClassName, pageClassName} = props; @@ -28,6 +55,8 @@ export default function Layout(props: Props): JSX.Element { + + diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index 7d86042aeea4..1fc0ac7d276f 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -377,6 +377,16 @@ export interface RouteConfig { [propName: string]: unknown; } +export interface RouteContext { + data: Data; // plugin-specific contextual data +} + +// Top-level plugin routes automatically add some context data to the route +// This permits to know which plugin is handling the current route +export interface PluginRouteContext extends RouteContext { + plugin: {id: string; name: string}; +} + export type Route = { readonly path: string; readonly component: ReturnType; diff --git a/packages/docusaurus/src/client/exports/ComponentCreator.tsx b/packages/docusaurus/src/client/exports/ComponentCreator.tsx index 1135df89b086..f5db37944c81 100644 --- a/packages/docusaurus/src/client/exports/ComponentCreator.tsx +++ b/packages/docusaurus/src/client/exports/ComponentCreator.tsx @@ -11,6 +11,7 @@ import Loading from '@theme/Loading'; import routesChunkNames from '@generated/routesChunkNames'; import registry from '@generated/registry'; import flat from '../flat'; +import {RouteContextProvider} from '../routeContext'; type OptsLoader = Record; @@ -84,7 +85,18 @@ export default function ComponentCreator( const Component = loadedModules.component; delete loadedModules.component; - return ; + + /* eslint-disable no-underscore-dangle */ + const routeContextModule = loadedModules.__routeContextModule; + delete loadedModules.__routeContextModule; + /* eslint-enable no-underscore-dangle */ + + // Is there any way to put this RouteContextProvider upper in the tree? + return ( + + ; + + ); }, }); } diff --git a/packages/docusaurus/src/client/exports/useRouteContext.tsx b/packages/docusaurus/src/client/exports/useRouteContext.tsx new file mode 100644 index 000000000000..2f9fdd7af161 --- /dev/null +++ b/packages/docusaurus/src/client/exports/useRouteContext.tsx @@ -0,0 +1,22 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import type {PluginRouteContext} from '@docusaurus/types'; +import {Context} from '../routeContext'; + +export default function useRouteContext< + Data = unknown, +>(): PluginRouteContext { + const context = React.useContext(Context); + if (!context) { + throw new Error( + 'Unexpected: no Docusaurus parent/current route context found', + ); + } + return context as PluginRouteContext; +} diff --git a/packages/docusaurus/src/client/routeContext.tsx b/packages/docusaurus/src/client/routeContext.tsx new file mode 100644 index 000000000000..58c8ef06fa06 --- /dev/null +++ b/packages/docusaurus/src/client/routeContext.tsx @@ -0,0 +1,60 @@ +/** + * 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, {useMemo, type ReactNode} from 'react'; +import type {PluginRouteContext, RouteContext} from '@docusaurus/types'; + +export const Context = React.createContext(null); + +function mergeContexts({ + parent, + value, +}: { + parent: PluginRouteContext | null; + value: PluginRouteContext | RouteContext | null; +}): PluginRouteContext { + if (!parent) { + if (!value) { + throw new Error( + 'Unexpected: no Docusaurus parent/current route context found', + ); + } else if (!('plugin' in value)) { + throw new Error( + 'Unexpected: Docusaurus parent route context has no plugin attribute', + ); + } else { + return value; + } + } + + // See TS issue https://stackoverflow.com/a/51193091/82609 + // eslint-disable-next-line prefer-object-spread + const data = Object.assign({}, parent.data, value?.data); + + return { + // nested routes are not supposed to override plugin attribute + plugin: parent.plugin, + data, + }; +} + +export function RouteContextProvider({ + children, + value, +}: { + children: ReactNode; + value: PluginRouteContext | null; +}): JSX.Element { + const parent = React.useContext(Context); + + const mergedValue = useMemo( + () => mergeContexts({parent, value}), + [parent, value], + ); + + return {children}; +} diff --git a/packages/docusaurus/src/server/plugins/index.ts b/packages/docusaurus/src/server/plugins/index.ts index b279b4d7a659..56142e8c66ae 100644 --- a/packages/docusaurus/src/server/plugins/index.ts +++ b/packages/docusaurus/src/server/plugins/index.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {generate} from '@docusaurus/utils'; +import {docuHash, generate} from '@docusaurus/utils'; import fs from 'fs-extra'; import path from 'path'; import type { @@ -18,6 +18,7 @@ import type { ThemeConfig, LoadedPlugin, InitializedPlugin, + PluginRouteContext, } from '@docusaurus/types'; import initPlugins from './init'; import logger from '@docusaurus/logger'; @@ -149,17 +150,6 @@ export async function loadPlugins({ const dataDirRoot = path.join(context.generatedFilesDir, plugin.name); const dataDir = path.join(dataDirRoot, pluginId); - const addRoute: PluginContentLoadedActions['addRoute'] = ( - initialRouteConfig, - ) => { - // Trailing slash behavior is handled in a generic way for all plugins - const finalRouteConfig = applyRouteTrailingSlash(initialRouteConfig, { - trailingSlash: context.siteConfig.trailingSlash, - baseUrl: context.siteConfig.baseUrl, - }); - pluginsRouteConfigs.push(finalRouteConfig); - }; - const createData: PluginContentLoadedActions['createData'] = async ( name, data, @@ -170,6 +160,34 @@ export async function loadPlugins({ return modulePath; }; + // TODO this would be better to do all that in the codegen phase + // TODO handle context for nested routes + const pluginRouteContext: PluginRouteContext = { + plugin: {name: plugin.name, id: pluginId}, + data: undefined, // TODO allow plugins to provide context data + }; + const pluginRouteContextModulePath = await createData( + `${docuHash('pluginRouteContextModule')}.json`, + JSON.stringify(pluginRouteContext, null, 2), + ); + + const addRoute: PluginContentLoadedActions['addRoute'] = ( + initialRouteConfig, + ) => { + // Trailing slash behavior is handled in a generic way for all plugins + const finalRouteConfig = applyRouteTrailingSlash(initialRouteConfig, { + trailingSlash: context.siteConfig.trailingSlash, + baseUrl: context.siteConfig.baseUrl, + }); + pluginsRouteConfigs.push({ + ...finalRouteConfig, + modules: { + ...finalRouteConfig.modules, + __routeContextModule: pluginRouteContextModulePath, + }, + }); + }; + // the plugins global data are namespaced to avoid data conflicts: // - by plugin name // - by plugin id (allow using multiple instances of the same plugin) diff --git a/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap b/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap index d0271d7c5b39..1e46aa3c5eda 100644 --- a/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap +++ b/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap @@ -21,6 +21,7 @@ exports[`base webpack config creates webpack aliases 1`] = ` "@docusaurus/useDocusaurusContext": "../../../../client/exports/useDocusaurusContext.ts", "@docusaurus/useGlobalData": "../../../../client/exports/useGlobalData.ts", "@docusaurus/useIsBrowser": "../../../../client/exports/useIsBrowser.ts", + "@docusaurus/useRouteContext": "../../../../client/exports/useRouteContext.tsx", "@generated": "../../../../../../..", "@site": "", "@theme-init/PluginThemeComponentEnhanced": "pluginThemeFolder/PluginThemeComponentEnhanced.js", @@ -68,5 +69,6 @@ exports[`getDocusaurusAliases() returns appropriate webpack aliases 1`] = ` "@docusaurus/useDocusaurusContext": "../../client/exports/useDocusaurusContext.ts", "@docusaurus/useGlobalData": "../../client/exports/useGlobalData.ts", "@docusaurus/useIsBrowser": "../../client/exports/useIsBrowser.ts", + "@docusaurus/useRouteContext": "../../client/exports/useRouteContext.tsx", } `; diff --git a/project-words.txt b/project-words.txt index 9e125c666550..458398a94018 100644 --- a/project-words.txt +++ b/project-words.txt @@ -40,6 +40,7 @@ chedeau cheng clément clsx +codegen codeql codesandbox codespaces From 840237cf221fd7f34dc2cb7ac834660aea3670a8 Mon Sep 17 00:00:00 2001 From: sebastienlorber Date: Thu, 17 Mar 2022 19:16:21 +0100 Subject: [PATCH 2/7] add HtmlClassNameProvider component + make it work for docs versions --- .../src/theme/DocPage/index.tsx | 11 ++-- .../src/theme/Layout/index.tsx | 29 --------- .../src/theme/LayoutProviders/index.tsx | 5 +- packages/docusaurus-theme-common/src/index.ts | 5 ++ .../src/utils/metadataUtilsTemp.tsx | 59 +++++++++++++++++++ 5 files changed, 72 insertions(+), 37 deletions(-) create mode 100644 packages/docusaurus-theme-common/src/utils/metadataUtilsTemp.tsx diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx index b2d2ebbe3251..be8ef387c7ac 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx @@ -20,14 +20,15 @@ import {translate} from '@docusaurus/Translate'; import clsx from 'clsx'; import styles from './styles.module.css'; + import { + HtmlClassNameProvider, ThemeClassNames, docVersionSearchTag, DocsSidebarProvider, useDocsSidebar, DocsVersionProvider, } from '@docusaurus/theme-common'; -import Head from '@docusaurus/Head'; type DocPageContentProps = { readonly currentDocRoute: DocumentRoute; @@ -160,11 +161,7 @@ export default function DocPage(props: Props): JSX.Element { : null; return ( - <> - - {/* TODO we should add a core addRoute({htmlClassName}) action */} - - + - > + ); } diff --git a/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx b/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx index e7bb0469e9df..ce56fe8d01ec 100644 --- a/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx @@ -18,33 +18,6 @@ import type {Props} from '@theme/Layout'; import {ThemeClassNames, useKeyboardNavigation} from '@docusaurus/theme-common'; import ErrorPageContent from '@theme/ErrorPageContent'; import './styles.css'; -import useRouteContext from '@docusaurus/useRouteContext'; -import Head from '@docusaurus/Head'; - -function pluginNameToClassName(pluginName: string) { - return `plugin-${pluginName.replace( - new RegExp( - [ - 'docusaurus-plugin-content-', - 'docusaurus-plugin-', - 'docusaurus-theme-', - ].join('|'), - 'gi', - ), - '', - )}`; -} - -function PluginHtmlClassName() { - const routeContext = useRouteContext(); - const nameClass = pluginNameToClassName(routeContext.plugin.name); - const idClass = `plugin-id-${routeContext.plugin.id}`; - return ( - - - - ); -} export default function Layout(props: Props): JSX.Element { const {children, noFooter, wrapperClassName, pageClassName} = props; @@ -55,8 +28,6 @@ export default function Layout(props: Props): JSX.Element { - - diff --git a/packages/docusaurus-theme-classic/src/theme/LayoutProviders/index.tsx b/packages/docusaurus-theme-classic/src/theme/LayoutProviders/index.tsx index 5d0d2bf859d0..601bea65eaa5 100644 --- a/packages/docusaurus-theme-classic/src/theme/LayoutProviders/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/LayoutProviders/index.tsx @@ -13,6 +13,7 @@ import { DocsPreferredVersionContextProvider, MobileSecondaryMenuProvider, ScrollControllerProvider, + PluginHtmlClassNameProvider, } from '@docusaurus/theme-common'; import type {Props} from '@theme/LayoutProviders'; @@ -24,7 +25,9 @@ export default function LayoutProviders({children}: Props): JSX.Element { - {children} + + {children} + diff --git a/packages/docusaurus-theme-common/src/index.ts b/packages/docusaurus-theme-common/src/index.ts index 96244f043209..98e215b4d78c 100644 --- a/packages/docusaurus-theme-common/src/index.ts +++ b/packages/docusaurus-theme-common/src/index.ts @@ -135,6 +135,11 @@ export {isRegexpStringMatch} from './utils/regexpUtils'; export {useHomePageRoute} from './utils/routesUtils'; +export { + HtmlClassNameProvider, + PluginHtmlClassNameProvider, +} from './utils/metadataUtilsTemp'; + export {useColorMode, ColorModeProvider} from './utils/colorModeUtils'; export { useTabGroupChoice, diff --git a/packages/docusaurus-theme-common/src/utils/metadataUtilsTemp.tsx b/packages/docusaurus-theme-common/src/utils/metadataUtilsTemp.tsx new file mode 100644 index 000000000000..029194ba6c1d --- /dev/null +++ b/packages/docusaurus-theme-common/src/utils/metadataUtilsTemp.tsx @@ -0,0 +1,59 @@ +/** + * 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 Head from '@docusaurus/Head'; +import clsx from 'clsx'; +import useRouteContext from '@docusaurus/useRouteContext'; + +const HtmlClassNameContext = React.createContext(undefined); + +// This annoying wrapper is necessary because Helmet does not "merge" classes +// See https://github.com/staylor/react-helmet-async/issues/161 +export function HtmlClassNameProvider({ + className: classNameProp, + children, +}: { + className: string; + children: ReactNode; +}): JSX.Element { + const classNameContext = React.useContext(HtmlClassNameContext); + const className = clsx(classNameContext, classNameProp); + return ( + + + + + {children} + + ); +} + +function pluginNameToClassName(pluginName: string) { + return `plugin-${pluginName.replace( + new RegExp( + [ + 'docusaurus-plugin-content-', + 'docusaurus-plugin-', + 'docusaurus-theme-', + ].join('|'), + 'gi', + ), + '', + )}`; +} + +export function PluginHtmlClassNameProvider({children}: {children: ReactNode}) { + const routeContext = useRouteContext(); + const nameClass = pluginNameToClassName(routeContext.plugin.name); + const idClass = `plugin-id-${routeContext.plugin.id}`; + return ( + + {children} + + ); +} From 032516e5ca1f3d0aae2335f015effbb0daf295d1 Mon Sep 17 00:00:00 2001 From: sebastienlorber Date: Thu, 17 Mar 2022 19:25:56 +0100 Subject: [PATCH 3/7] create html className for doc id --- .../src/plugin-content-docs.d.ts | 1 + .../src/theme/DocItem/index.tsx | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts index f14be0f462a8..5d7aa1e04d21 100644 --- a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts +++ b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts @@ -191,6 +191,7 @@ declare module '@theme/DocItem' { }; export type Metadata = { + readonly unversionedId?: string; readonly description?: string; readonly title?: string; readonly permalink?: string; diff --git a/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx index bfea8f72f60c..45b8dd52a78f 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx @@ -17,7 +17,11 @@ import TOC from '@theme/TOC'; import TOCCollapsible from '@theme/TOCCollapsible'; import Heading from '@theme/Heading'; import styles from './styles.module.css'; -import {ThemeClassNames, useWindowSize} from '@docusaurus/theme-common'; +import { + HtmlClassNameProvider, + ThemeClassNames, + useWindowSize, +} from '@docusaurus/theme-common'; import DocBreadcrumbs from '@theme/DocBreadcrumbs'; import MDXContent from '@theme/MDXContent'; @@ -49,7 +53,7 @@ export default function DocItem(props: Props): JSX.Element { canRenderTOC && (windowSize === 'desktop' || windowSize === 'ssr'); return ( - <> + @@ -107,6 +111,6 @@ export default function DocItem(props: Props): JSX.Element { )} - > + ); } From fb5d76698e23ab0b31a8dc94a1bfe3f433061216 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Fri, 18 Mar 2022 09:18:35 +0800 Subject: [PATCH 4/7] refactors --- .../src/utils/metadataUtilsTemp.tsx | 17 +++++++-------- packages/docusaurus-types/src/index.d.ts | 21 +++++++++++++------ .../docusaurus/src/client/routeContext.tsx | 7 ++----- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/packages/docusaurus-theme-common/src/utils/metadataUtilsTemp.tsx b/packages/docusaurus-theme-common/src/utils/metadataUtilsTemp.tsx index 029194ba6c1d..f55899063b53 100644 --- a/packages/docusaurus-theme-common/src/utils/metadataUtilsTemp.tsx +++ b/packages/docusaurus-theme-common/src/utils/metadataUtilsTemp.tsx @@ -12,7 +12,7 @@ import useRouteContext from '@docusaurus/useRouteContext'; const HtmlClassNameContext = React.createContext(undefined); -// This annoying wrapper is necessary because Helmet does not "merge" classes +// This wrapper is necessary because Helmet does not "merge" classes // See https://github.com/staylor/react-helmet-async/issues/161 export function HtmlClassNameProvider({ className: classNameProp, @@ -35,19 +35,16 @@ export function HtmlClassNameProvider({ function pluginNameToClassName(pluginName: string) { return `plugin-${pluginName.replace( - new RegExp( - [ - 'docusaurus-plugin-content-', - 'docusaurus-plugin-', - 'docusaurus-theme-', - ].join('|'), - 'gi', - ), + /docusaurus-(?:plugin|theme)-(?:content-)?/gi, '', )}`; } -export function PluginHtmlClassNameProvider({children}: {children: ReactNode}) { +export function PluginHtmlClassNameProvider({ + children, +}: { + children: ReactNode; +}): JSX.Element { const routeContext = useRouteContext(); const nameClass = pluginNameToClassName(routeContext.plugin.name); const idClass = `plugin-id-${routeContext.plugin.id}`; diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index 1fc0ac7d276f..fdb0f19820a9 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -377,14 +377,23 @@ export interface RouteConfig { [propName: string]: unknown; } -export interface RouteContext { - data: Data; // plugin-specific contextual data +export interface RouteContext { + /** + * Plugin-specific context data. + */ + data: Data; } -// Top-level plugin routes automatically add some context data to the route -// This permits to know which plugin is handling the current route -export interface PluginRouteContext extends RouteContext { - plugin: {id: string; name: string}; +/** + * Top-level plugin routes automatically add some context data to the route. + * This permits us to know which plugin is handling the current route. + */ +export interface PluginRouteContext + extends RouteContext { + plugin: { + id: string; + name: string; + }; } export type Route = { diff --git a/packages/docusaurus/src/client/routeContext.tsx b/packages/docusaurus/src/client/routeContext.tsx index 58c8ef06fa06..fcd2c8175340 100644 --- a/packages/docusaurus/src/client/routeContext.tsx +++ b/packages/docusaurus/src/client/routeContext.tsx @@ -26,14 +26,11 @@ function mergeContexts({ throw new Error( 'Unexpected: Docusaurus parent route context has no plugin attribute', ); - } else { - return value; } + return value; } - // See TS issue https://stackoverflow.com/a/51193091/82609 - // eslint-disable-next-line prefer-object-spread - const data = Object.assign({}, parent.data, value?.data); + const data = {...parent.data, ...value?.data}; return { // nested routes are not supposed to override plugin attribute From a52601ed46dd20b842db1dab9f6e93fb6346163f Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Fri, 18 Mar 2022 09:23:30 +0800 Subject: [PATCH 5/7] remove generic --- packages/docusaurus-types/src/index.d.ts | 7 +++---- packages/docusaurus/src/client/exports/useRouteContext.tsx | 6 ++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index fdb0f19820a9..090300de959d 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -377,19 +377,18 @@ export interface RouteConfig { [propName: string]: unknown; } -export interface RouteContext { +export interface RouteContext { /** * Plugin-specific context data. */ - data: Data; + data: object | undefined; } /** * Top-level plugin routes automatically add some context data to the route. * This permits us to know which plugin is handling the current route. */ -export interface PluginRouteContext - extends RouteContext { +export interface PluginRouteContext extends RouteContext { plugin: { id: string; name: string; diff --git a/packages/docusaurus/src/client/exports/useRouteContext.tsx b/packages/docusaurus/src/client/exports/useRouteContext.tsx index 2f9fdd7af161..79c57fa9ae2c 100644 --- a/packages/docusaurus/src/client/exports/useRouteContext.tsx +++ b/packages/docusaurus/src/client/exports/useRouteContext.tsx @@ -9,14 +9,12 @@ import React from 'react'; import type {PluginRouteContext} from '@docusaurus/types'; import {Context} from '../routeContext'; -export default function useRouteContext< - Data = unknown, ->(): PluginRouteContext { +export default function useRouteContext(): PluginRouteContext { const context = React.useContext(Context); if (!context) { throw new Error( 'Unexpected: no Docusaurus parent/current route context found', ); } - return context as PluginRouteContext; + return context; } From ef38c6c162180be900a24eb3c785542f1e5e0134 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Fri, 18 Mar 2022 09:26:04 +0800 Subject: [PATCH 6/7] refactor... --- packages/docusaurus/src/client/routeContext.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docusaurus/src/client/routeContext.tsx b/packages/docusaurus/src/client/routeContext.tsx index fcd2c8175340..b52771a5edc6 100644 --- a/packages/docusaurus/src/client/routeContext.tsx +++ b/packages/docusaurus/src/client/routeContext.tsx @@ -15,7 +15,7 @@ function mergeContexts({ value, }: { parent: PluginRouteContext | null; - value: PluginRouteContext | RouteContext | null; + value: RouteContext | null; }): PluginRouteContext { if (!parent) { if (!value) { From 89978eaabef861505609dc1f05447f8acb4546ba Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Fri, 18 Mar 2022 09:58:27 +0800 Subject: [PATCH 7/7] fix build failure --- packages/docusaurus-types/src/index.d.ts | 2 +- .../src/client/exports/ComponentCreator.tsx | 11 ++++++++++- packages/docusaurus/src/client/routeContext.tsx | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index 090300de959d..e5ef1a919b25 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -381,7 +381,7 @@ export interface RouteContext { /** * Plugin-specific context data. */ - data: object | undefined; + data?: object | undefined; } /** diff --git a/packages/docusaurus/src/client/exports/ComponentCreator.tsx b/packages/docusaurus/src/client/exports/ComponentCreator.tsx index f5db37944c81..da50d1b3cfbe 100644 --- a/packages/docusaurus/src/client/exports/ComponentCreator.tsx +++ b/packages/docusaurus/src/client/exports/ComponentCreator.tsx @@ -23,7 +23,16 @@ export default function ComponentCreator( if (path === '*') { return Loadable({ loading: Loading, - loader: () => import('@theme/NotFound'), + loader: async () => { + const NotFound = (await import('@theme/NotFound')).default; + return (props) => ( + // Is there a better API for this? + + + + ); + }, }); } diff --git a/packages/docusaurus/src/client/routeContext.tsx b/packages/docusaurus/src/client/routeContext.tsx index b52771a5edc6..78e87a5a65a4 100644 --- a/packages/docusaurus/src/client/routeContext.tsx +++ b/packages/docusaurus/src/client/routeContext.tsx @@ -30,6 +30,7 @@ function mergeContexts({ return value; } + // TODO deep merge this const data = {...parent.data, ...value?.data}; return {