/** * 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 {ParsedUrlQueryInput} from 'querystring'; import type {PluginIdentifier} from './plugin'; /** * A "module" represents a unit of serialized data emitted from the plugin. It * will be imported on client-side and passed as props, context, etc. * * If it's a string, it's a file path that the bundler can `require`; if it's * an object, it can also contain `query` or other metadata. */ export type Module = | { /** * A marker that tells the route generator this is an import and not a * nested object to recurse. */ __import?: boolean; path: string; query?: ParsedUrlQueryInput; } | string; /** * Represents the data attached to each route. Since the routes.js is a * monolithic data file, any data (like props) should be serialized separately * and registered here as file paths (a {@link Module}), so that we could * code-split. */ export type RouteModules = { [propName: string]: Module | RouteModules | RouteModules[]; }; /** * 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 * * `undefined` means we haven't tried to compute the value for this route. * This is usually the case for routes created by third-party plugins that do * not need this metadata. * * `null` means we already tried to compute a lastUpdatedAt, but we know for * sure there isn't any. This usually happens for untracked Git files. */ lastUpdatedAt?: number | null; }; /** * Represents a "slice" of the final route structure returned from the plugin * `addRoute` action. */ 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; /** * Optional props object; will be converted to a module and injected as props * into the route component. */ props?: {[propName: string]: unknown}; /** * Extra route attribute; will be available on the client side route object. */ [attributeName: string]: unknown; }; export type PluginRouteConfig = RouteConfig & { /** * Routes are always created by Docusaurus plugins * A plugin identifier is available at the top of a routing tree * (child routes are implicitly created by the same plugin as their parent) */ plugin: PluginIdentifier; }; export type RouteContext = { /** * Plugin-specific context data. */ data?: {[key: string]: unknown}; }; /** * 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 type PluginRouteContext = RouteContext & { plugin: { id: string; name: string; }; }; /** * The shape would be isomorphic to {@link RouteModules}: * {@link Module} -> `string`, `RouteModules[]` -> `ChunkNames[]`. * * Each `string` chunk name will correlate with one key in the {@link Registry}. */ export type ChunkNames = { [propName: string]: string | ChunkNames | ChunkNames[]; }; /** * A map from route paths (with a hash) to the chunk names of each module, which * the bundler will collect. * * Chunk keys are routes with a hash, because 2 routes can conflict with each * other if they have the same path, e.g.: parent=/docs, child=/docs * * @see https://github.com/facebook/docusaurus/issues/2917 */ export type RouteChunkNames = { [routePathHashed: string]: ChunkNames; }; /** * Each key is the chunk name, which you can get from `routeChunkNames` (see * {@link RouteChunkNames}). The values are the opts data that react-loadable * needs. For example: * * ```js * const options = { * optsLoader: { * component: () => import('./Pages.js'), * content.foo: () => import('./doc1.md'), * }, * optsModules: ['./Pages.js', './doc1.md'], * optsWebpack: [ * require.resolveWeak('./Pages.js'), * require.resolveWeak('./doc1.md'), * ], * } * ``` * * @see https://github.com/jamiebuilds/react-loadable#declaring-which-modules-are-being-loaded */ export type Registry = { readonly [chunkName: string]: [ // eslint-disable-next-line @typescript-eslint/no-explicit-any Loader: () => Promise, ModuleName: string, ResolvedModuleName: string, ]; };