@docusaurus/core 2.0.0-beta.1decd6f80 → 2.0.0-beta.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/bin/beforeCli.mjs +138 -0
  2. package/bin/docusaurus.mjs +228 -0
  3. package/lib/babel/preset.d.ts +8 -3
  4. package/lib/babel/preset.js +8 -7
  5. package/lib/client/.eslintrc.js +2 -4
  6. package/lib/client/App.d.ts +2 -3
  7. package/lib/client/App.js +30 -27
  8. package/lib/client/BaseUrlIssueBanner/index.d.ts +27 -0
  9. package/lib/client/{baseUrlIssueBanner/BaseUrlIssueBanner.js → BaseUrlIssueBanner/index.js} +24 -14
  10. package/lib/client/{baseUrlIssueBanner → BaseUrlIssueBanner}/styles.module.css +0 -0
  11. package/lib/client/ClientLifecyclesDispatcher.d.ts +16 -0
  12. package/lib/client/ClientLifecyclesDispatcher.js +39 -0
  13. package/lib/client/LinksCollector.d.ts +3 -3
  14. package/lib/client/LinksCollector.js +8 -13
  15. package/lib/client/PendingNavigation.d.ts +17 -3
  16. package/lib/client/PendingNavigation.js +39 -72
  17. package/lib/client/{baseUrlIssueBanner/BaseUrlIssueBanner.d.ts → SiteMetadataDefaults.d.ts} +1 -2
  18. package/lib/client/SiteMetadataDefaults.js +19 -0
  19. package/lib/{choosePort.d.ts → client/browserContext.d.ts} +5 -5
  20. package/lib/client/browserContext.js +22 -0
  21. package/lib/client/clientEntry.js +14 -9
  22. package/lib/client/docusaurus.d.ts +11 -5
  23. package/lib/client/docusaurus.js +29 -42
  24. package/lib/client/docusaurusContext.d.ts +12 -0
  25. package/lib/client/docusaurusContext.js +25 -0
  26. package/lib/client/exports/BrowserOnly.d.ts +3 -5
  27. package/lib/client/exports/BrowserOnly.js +14 -7
  28. package/lib/client/exports/ComponentCreator.d.ts +1 -2
  29. package/lib/client/exports/ComponentCreator.js +67 -41
  30. package/lib/client/exports/ErrorBoundary.d.ts +18 -0
  31. package/lib/client/exports/ErrorBoundary.js +35 -0
  32. package/lib/client/exports/Head.d.ts +2 -3
  33. package/lib/client/exports/Head.js +3 -4
  34. package/lib/client/exports/Interpolate.d.ts +2 -2
  35. package/lib/client/exports/Interpolate.js +20 -49
  36. package/lib/client/exports/Link.d.ts +4 -10
  37. package/lib/client/exports/Link.js +44 -38
  38. package/lib/client/exports/Translate.d.ts +1 -1
  39. package/lib/client/exports/Translate.js +14 -9
  40. package/lib/client/exports/constants.js +1 -11
  41. package/lib/client/exports/isInternalUrl.js +1 -1
  42. package/lib/client/exports/renderRoutes.d.ts +1 -2
  43. package/lib/client/exports/renderRoutes.js +1 -2
  44. package/lib/client/exports/router.d.ts +1 -1
  45. package/lib/client/exports/router.js +1 -1
  46. package/lib/client/exports/useBaseUrl.js +11 -14
  47. package/lib/client/exports/useDocusaurusContext.d.ts +2 -3
  48. package/lib/client/exports/useDocusaurusContext.js +3 -9
  49. package/lib/client/exports/useGlobalData.d.ts +4 -3
  50. package/lib/client/exports/useGlobalData.js +9 -13
  51. package/lib/{server/versions/__tests/index.test.d.ts → client/exports/useIsBrowser.d.ts} +1 -1
  52. package/lib/client/exports/useIsBrowser.js +11 -0
  53. package/lib/client/exports/useRouteContext.d.ts +8 -0
  54. package/lib/client/exports/useRouteContext.js +15 -0
  55. package/lib/client/flat.d.ts +12 -2
  56. package/lib/client/flat.js +19 -15
  57. package/lib/client/normalizeLocation.d.ts +2 -5
  58. package/lib/client/normalizeLocation.js +14 -10
  59. package/lib/client/prefetch.d.ts +1 -2
  60. package/lib/client/prefetch.js +11 -31
  61. package/lib/client/preload.d.ts +3 -4
  62. package/lib/client/preload.js +7 -12
  63. package/lib/client/routeContext.d.ts +13 -0
  64. package/lib/client/routeContext.js +31 -0
  65. package/lib/client/serverEntry.d.ts +10 -0
  66. package/lib/client/serverEntry.js +91 -132
  67. package/lib/client/theme-fallback/Error/index.d.ts +10 -0
  68. package/lib/client/theme-fallback/Error/index.js +45 -0
  69. package/lib/client/theme-fallback/Layout/index.d.ts +10 -0
  70. package/lib/client/theme-fallback/Layout/index.js +2 -26
  71. package/lib/client/theme-fallback/Loading/index.d.ts +9 -0
  72. package/lib/client/theme-fallback/Loading/index.js +49 -115
  73. package/lib/client/{exports/context.js → theme-fallback/NotFound/index.d.ts} +2 -2
  74. package/lib/client/theme-fallback/NotFound/index.js +19 -18
  75. package/lib/client/theme-fallback/Root/index.d.ts +10 -0
  76. package/lib/client/theme-fallback/Root/index.js +2 -6
  77. package/lib/{server/html-tags/htmlTags.d.ts → client/theme-fallback/SiteMetadata/index.d.ts} +2 -1
  78. package/lib/client/theme-fallback/SiteMetadata/index.js +10 -0
  79. package/lib/commands/build.d.ts +6 -2
  80. package/lib/commands/build.js +77 -61
  81. package/lib/commands/clear.d.ts +7 -1
  82. package/lib/commands/clear.js +32 -20
  83. package/lib/commands/deploy.d.ts +5 -2
  84. package/lib/commands/deploy.js +91 -71
  85. package/lib/commands/external.d.ts +2 -2
  86. package/lib/commands/external.js +6 -11
  87. package/lib/commands/serve.d.ts +7 -2
  88. package/lib/commands/serve.js +31 -18
  89. package/lib/commands/start.d.ts +8 -2
  90. package/lib/commands/start.js +105 -91
  91. package/lib/commands/swizzle/actions.d.ts +23 -0
  92. package/lib/commands/swizzle/actions.js +102 -0
  93. package/lib/commands/swizzle/common.d.ts +33 -0
  94. package/lib/commands/swizzle/common.js +56 -0
  95. package/lib/commands/swizzle/components.d.ts +29 -0
  96. package/lib/commands/swizzle/components.js +200 -0
  97. package/lib/commands/swizzle/config.d.ts +10 -0
  98. package/lib/commands/swizzle/config.js +83 -0
  99. package/lib/{server/client-modules/index.d.ts → commands/swizzle/context.d.ts} +2 -2
  100. package/lib/commands/swizzle/context.js +24 -0
  101. package/lib/commands/swizzle/index.d.ts +8 -0
  102. package/lib/commands/swizzle/index.js +116 -0
  103. package/lib/commands/swizzle/prompts.d.ts +12 -0
  104. package/lib/commands/swizzle/prompts.js +110 -0
  105. package/lib/{client/exports/context.d.ts → commands/swizzle/tables.d.ts} +3 -4
  106. package/lib/commands/swizzle/tables.js +113 -0
  107. package/lib/commands/swizzle/themes.d.ts +20 -0
  108. package/lib/commands/swizzle/themes.js +106 -0
  109. package/lib/commands/writeHeadingIds.d.ts +2 -6
  110. package/lib/commands/writeHeadingIds.js +21 -81
  111. package/lib/commands/writeTranslations.d.ts +4 -5
  112. package/lib/commands/writeTranslations.js +41 -23
  113. package/lib/index.d.ts +9 -9
  114. package/lib/index.js +14 -14
  115. package/lib/server/brokenLinks.d.ts +4 -17
  116. package/lib/server/brokenLinks.js +65 -54
  117. package/lib/server/clientModules.d.ts +12 -0
  118. package/lib/server/clientModules.js +20 -0
  119. package/lib/server/config.d.ts +5 -2
  120. package/lib/server/config.js +14 -6
  121. package/lib/server/configValidation.d.ts +4 -2
  122. package/lib/server/configValidation.js +96 -39
  123. package/lib/server/getHostPort.d.ts +14 -0
  124. package/lib/server/getHostPort.js +79 -0
  125. package/lib/server/htmlTags.d.ts +12 -0
  126. package/lib/server/htmlTags.js +62 -0
  127. package/lib/server/i18n.d.ts +3 -13
  128. package/lib/server/i18n.js +19 -55
  129. package/lib/server/index.d.ts +28 -6
  130. package/lib/server/index.js +82 -171
  131. package/lib/server/plugins/configs.d.ts +51 -0
  132. package/lib/server/plugins/configs.js +101 -0
  133. package/lib/server/plugins/index.d.ts +10 -10
  134. package/lib/server/plugins/index.js +74 -125
  135. package/lib/server/plugins/init.d.ts +6 -9
  136. package/lib/server/plugins/init.js +43 -108
  137. package/lib/server/plugins/moduleShorthand.d.ts +9 -0
  138. package/lib/server/plugins/moduleShorthand.js +46 -0
  139. package/lib/server/plugins/pluginIds.d.ts +6 -2
  140. package/lib/server/plugins/pluginIds.js +12 -7
  141. package/lib/server/plugins/presets.d.ts +12 -0
  142. package/lib/server/plugins/presets.js +49 -0
  143. package/lib/server/plugins/routeConfig.d.ts +11 -0
  144. package/lib/server/plugins/routeConfig.js +54 -0
  145. package/lib/server/plugins/synthetic.d.ts +20 -0
  146. package/lib/server/plugins/synthetic.js +112 -0
  147. package/lib/server/routes.d.ts +39 -7
  148. package/lib/server/routes.js +185 -95
  149. package/lib/server/siteMetadata.d.ts +12 -0
  150. package/lib/server/siteMetadata.js +81 -0
  151. package/lib/server/translations/translations.d.ts +13 -17
  152. package/lib/server/translations/translations.js +37 -61
  153. package/lib/server/translations/translationsExtractor.d.ts +10 -5
  154. package/lib/server/translations/translationsExtractor.js +159 -121
  155. package/lib/server/utils.d.ts +9 -3
  156. package/lib/server/utils.js +7 -9
  157. package/lib/webpack/aliases/index.d.ts +34 -0
  158. package/lib/webpack/aliases/index.js +106 -0
  159. package/lib/webpack/base.d.ts +3 -4
  160. package/lib/webpack/base.js +53 -55
  161. package/lib/webpack/client.d.ts +3 -3
  162. package/lib/webpack/client.js +12 -19
  163. package/lib/webpack/plugins/ChunkAssetPlugin.d.ts +13 -3
  164. package/lib/webpack/plugins/ChunkAssetPlugin.js +24 -17
  165. package/lib/webpack/plugins/CleanWebpackPlugin.d.ts +8 -8
  166. package/lib/webpack/plugins/CleanWebpackPlugin.js +10 -16
  167. package/lib/webpack/plugins/LogPlugin.d.ts +1 -1
  168. package/lib/webpack/plugins/LogPlugin.js +4 -5
  169. package/lib/webpack/plugins/WaitPlugin.d.ts +3 -3
  170. package/lib/webpack/plugins/WaitPlugin.js +1 -1
  171. package/lib/webpack/server.d.ts +5 -5
  172. package/lib/webpack/server.js +18 -8
  173. package/lib/{client → webpack}/templates/index.html.template.ejs +0 -0
  174. package/lib/webpack/templates/ssr.html.template.d.ts +8 -0
  175. package/lib/{client → webpack}/templates/ssr.html.template.js +5 -4
  176. package/lib/webpack/utils.d.ts +16 -31
  177. package/lib/webpack/utils.js +59 -177
  178. package/package.json +77 -73
  179. package/bin/docusaurus.js +0 -326
  180. package/lib/.tsbuildinfo +0 -5682
  181. package/lib/choosePort.js +0 -105
  182. package/lib/client/.tsbuildinfo +0 -4127
  183. package/lib/client/client-lifecycles-dispatcher.d.ts +0 -12
  184. package/lib/client/client-lifecycles-dispatcher.js +0 -27
  185. package/lib/client/nprogress.css +0 -36
  186. package/lib/commands/buildRemoteBranchUrl.d.ts +0 -7
  187. package/lib/commands/buildRemoteBranchUrl.js +0 -27
  188. package/lib/commands/commandUtils.d.ts +0 -3
  189. package/lib/commands/commandUtils.js +0 -21
  190. package/lib/commands/swizzle.d.ts +0 -9
  191. package/lib/commands/swizzle.js +0 -245
  192. package/lib/constants.d.ts +0 -18
  193. package/lib/constants.js +0 -23
  194. package/lib/server/client-modules/index.js +0 -14
  195. package/lib/server/duplicateRoutes.d.ts +0 -10
  196. package/lib/server/duplicateRoutes.js +0 -38
  197. package/lib/server/html-tags/htmlTags.js +0 -39
  198. package/lib/server/html-tags/index.d.ts +0 -9
  199. package/lib/server/html-tags/index.js +0 -43
  200. package/lib/server/loadSetup.d.ts +0 -9
  201. package/lib/server/loadSetup.js +0 -25
  202. package/lib/server/presets/index.d.ts +0 -11
  203. package/lib/server/presets/index.js +0 -48
  204. package/lib/server/themes/alias.d.ts +0 -8
  205. package/lib/server/themes/alias.js +0 -39
  206. package/lib/server/themes/index.d.ts +0 -8
  207. package/lib/server/themes/index.js +0 -35
  208. package/lib/server/versions/__fixtures__/dummy-plugin.js +0 -0
  209. package/lib/server/versions/__fixtures__/package.json +0 -3
  210. package/lib/server/versions/__tests/index.test.js +0 -25
  211. package/lib/server/versions/index.d.ts +0 -10
  212. package/lib/server/versions/index.js +0 -50
  213. package/lib/webpack/react-dev-utils-webpack5/README.md +0 -11
  214. package/lib/webpack/react-dev-utils-webpack5/evalSourceMapMiddleware.js +0 -57
  215. package/lib/webpack/react-dev-utils-webpack5/formatWebpackMessages.js +0 -138
  216. package/lib/webpack/react-dev-utils-webpack5/webpackHotDevClient.js +0 -285
  217. package/lib/webpack/sharedModuleAliases.d.ts +0 -10
  218. package/lib/webpack/sharedModuleAliases.js +0 -18
  219. package/tsconfig.client.json +0 -13
  220. package/tsconfig.json +0 -13
@@ -10,68 +10,94 @@ import Loading from '@theme/Loading';
10
10
  import routesChunkNames from '@generated/routesChunkNames';
11
11
  import registry from '@generated/registry';
12
12
  import flat from '../flat';
13
- function ComponentCreator(path, hash) {
13
+ import { RouteContextProvider } from '../routeContext';
14
+ export default function ComponentCreator(path, hash) {
14
15
  // 404 page
15
16
  if (path === '*') {
16
17
  return Loadable({
17
18
  loading: Loading,
18
- loader: () => import('@theme/NotFound'),
19
+ loader: () => import('@theme/NotFound').then(({ default: NotFound }) => (props) => (<RouteContextProvider
20
+ // Do we want a better name than native-default?
21
+ value={{ plugin: { name: 'native', id: 'default' } }}>
22
+ <NotFound {...props}/>
23
+ </RouteContextProvider>)),
19
24
  });
20
25
  }
21
- const chunkNamesKey = `${path}-${hash}`;
22
- const chunkNames = routesChunkNames[chunkNamesKey];
23
- const optsModules = [];
26
+ const chunkNames = routesChunkNames[`${path}-${hash}`];
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ const loader = {};
29
+ const modules = [];
24
30
  const optsWebpack = [];
25
- const optsLoader = {};
26
- /* Prepare opts data that react-loadable needs
27
- https://github.com/jamiebuilds/react-loadable#declaring-which-modules-are-being-loaded
28
- Example:
29
- - optsLoader:
30
- {
31
- component: () => import('./Pages.js'),
32
- content.foo: () => import('./doc1.md'),
33
- }
34
- - optsModules: ['./Pages.js', './doc1.md']
35
- - optsWebpack: [require.resolveWeak('./Pages.js'), require.resolveWeak('./doc1.md')]
36
- */
31
+ // A map from prop names to chunk names.
32
+ // e.g. Suppose the plugin added this as route:
33
+ // { __comp: "...", prop: { foo: "..." }, items: ["...", "..."] }
34
+ // It will become:
35
+ // { __comp: "...", "prop.foo": "...", "items.0": "...", "items.1": ... }
36
+ // Loadable.Map will _map_ over `loader` and load each key.
37
37
  const flatChunkNames = flat(chunkNames);
38
- Object.keys(flatChunkNames).forEach((key) => {
39
- const chunkRegistry = registry[flatChunkNames[key]];
38
+ Object.entries(flatChunkNames).forEach(([keyPath, chunkName]) => {
39
+ const chunkRegistry = registry[chunkName];
40
40
  if (chunkRegistry) {
41
- /* eslint-disable prefer-destructuring */
42
- optsLoader[key] = chunkRegistry[0];
43
- optsModules.push(chunkRegistry[1]);
41
+ // eslint-disable-next-line prefer-destructuring
42
+ loader[keyPath] = chunkRegistry[0];
43
+ modules.push(chunkRegistry[1]);
44
44
  optsWebpack.push(chunkRegistry[2]);
45
- /* eslint-enable prefer-destructuring */
46
45
  }
47
46
  });
48
47
  return Loadable.Map({
49
48
  loading: Loading,
50
- loader: optsLoader,
51
- modules: optsModules,
49
+ loader,
50
+ modules,
52
51
  webpack: () => optsWebpack,
53
52
  render: (loaded, props) => {
54
- // Clone the original object since we don't want to alter the original.
53
+ // `loaded` will be a map from key path (as returned from the flattened
54
+ // chunk names) to the modules loaded from the loaders. We now have to
55
+ // restore the chunk names' previous shape from this flat record.
56
+ // We do so by taking advantage of the existing `chunkNames` and replacing
57
+ // each chunk name with its loaded module, so we don't create another
58
+ // object from scratch.
55
59
  const loadedModules = JSON.parse(JSON.stringify(chunkNames));
56
- Object.keys(loaded).forEach((key) => {
57
- let val = loadedModules;
58
- const keyPath = key.split('.');
59
- for (let i = 0; i < keyPath.length - 1; i += 1) {
60
- val = val[keyPath[i]];
60
+ Object.entries(loaded).forEach(([keyPath, loadedModule]) => {
61
+ // JSON modules are also loaded as `{ default: ... }` (`import()`
62
+ // semantics) but we just want to pass the actual value to props.
63
+ const chunk = loadedModule.default;
64
+ // One loaded chunk can only be one of two things: a module (props) or a
65
+ // component. Modules are always JSON, so `default` always exists. This
66
+ // could only happen with a user-defined component.
67
+ if (!chunk) {
68
+ throw new Error(`The page component at ${path} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);
61
69
  }
62
- val[keyPath[keyPath.length - 1]] = loaded[key].default;
63
- const nonDefaultKeys = Object.keys(loaded[key]).filter((k) => k !== 'default');
64
- if (nonDefaultKeys && nonDefaultKeys.length) {
65
- nonDefaultKeys.forEach((nonDefaultKey) => {
66
- val[keyPath[keyPath.length - 1]][nonDefaultKey] =
67
- loaded[key][nonDefaultKey];
70
+ // A module can be a primitive, for example, if the user stored a string
71
+ // as a prop. However, there seems to be a bug with swc-loader's CJS
72
+ // logic, in that it would load a JSON module with content "foo" as
73
+ // `{ default: "foo", 0: "f", 1: "o", 2: "o" }`. Just to be safe, we
74
+ // first make sure that the chunk is non-primitive.
75
+ if (typeof chunk === 'object' || typeof chunk === 'function') {
76
+ Object.keys(loadedModule)
77
+ .filter((k) => k !== 'default')
78
+ .forEach((nonDefaultKey) => {
79
+ chunk[nonDefaultKey] = loadedModule[nonDefaultKey];
68
80
  });
69
81
  }
82
+ // We now have this chunk prepared. Go down the key path and replace the
83
+ // chunk name with the actual chunk.
84
+ let val = loadedModules;
85
+ const keyPaths = keyPath.split('.');
86
+ keyPaths.slice(0, -1).forEach((k) => {
87
+ val = val[k];
88
+ });
89
+ val[keyPaths[keyPaths.length - 1]] = chunk;
70
90
  });
71
- const Component = loadedModules.component;
72
- delete loadedModules.component;
73
- return React.createElement(Component, Object.assign({}, loadedModules, props));
91
+ /* eslint-disable no-underscore-dangle */
92
+ const Component = loadedModules.__comp;
93
+ delete loadedModules.__comp;
94
+ const routeContext = loadedModules.__context;
95
+ delete loadedModules.__context;
96
+ /* eslint-enable no-underscore-dangle */
97
+ // Is there any way to put this RouteContextProvider upper in the tree?
98
+ return (<RouteContextProvider value={routeContext}>
99
+ <Component {...loadedModules} {...props}/>
100
+ </RouteContextProvider>);
74
101
  },
75
102
  });
76
103
  }
77
- export default ComponentCreator;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ /// <reference types="@docusaurus/module-type-aliases" />
8
+ import React, { type ReactNode } from 'react';
9
+ import type { Props } from '@docusaurus/ErrorBoundary';
10
+ declare type State = {
11
+ error: Error | null;
12
+ };
13
+ export default class ErrorBoundary extends React.Component<Props, State> {
14
+ constructor(props: Props);
15
+ componentDidCatch(error: Error): void;
16
+ render(): ReactNode;
17
+ }
18
+ export {};
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import React from 'react';
8
+ import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
9
+ import DefaultFallback from '@theme/Error';
10
+ export default class ErrorBoundary extends React.Component {
11
+ constructor(props) {
12
+ super(props);
13
+ this.state = { error: null };
14
+ }
15
+ componentDidCatch(error) {
16
+ // Catch errors in any components below and re-render with error message
17
+ if (ExecutionEnvironment.canUseDOM) {
18
+ this.setState({ error });
19
+ }
20
+ }
21
+ render() {
22
+ const { children } = this.props;
23
+ const { error } = this.state;
24
+ if (error) {
25
+ const fallback = this.props.fallback ?? DefaultFallback;
26
+ return fallback({
27
+ error,
28
+ tryAgain: () => this.setState({ error: null }),
29
+ });
30
+ }
31
+ return (children ??
32
+ // See https://github.com/facebook/docusaurus/issues/6337#issuecomment-1012913647
33
+ null);
34
+ }
35
+ }
@@ -6,6 +6,5 @@
6
6
  */
7
7
  /// <reference types="@docusaurus/module-type-aliases" />
8
8
  /// <reference types="react" />
9
- import type { HeadProps } from '@docusaurus/Head';
10
- declare function Head(props: HeadProps): JSX.Element;
11
- export default Head;
9
+ import type { Props } from '@docusaurus/Head';
10
+ export default function Head(props: Props): JSX.Element;
@@ -5,8 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React from 'react';
8
- import { Helmet } from 'react-helmet';
9
- function Head(props) {
10
- return React.createElement(Helmet, Object.assign({}, props));
8
+ import { Helmet } from 'react-helmet-async';
9
+ export default function Head(props) {
10
+ return <Helmet {...props}/>;
11
11
  }
12
- export default Head;
@@ -5,8 +5,8 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  /// <reference types="@docusaurus/module-type-aliases" />
8
- import { ReactNode } from 'react';
8
+ import { type ReactNode } from 'react';
9
9
  import type { InterpolateProps, InterpolateValues } from '@docusaurus/Interpolate';
10
10
  export declare function interpolate<Str extends string>(text: Str, values?: InterpolateValues<Str, string | number>): string;
11
11
  export declare function interpolate<Str extends string, Value extends ReactNode>(text: Str, values?: InterpolateValues<Str, Value>): ReactNode;
12
- export default function Interpolate<Str extends string>({ children, values, }: InterpolateProps<Str>): ReactNode;
12
+ export default function Interpolate<Str extends string>({ children, values, }: InterpolateProps<Str>): JSX.Element;
@@ -4,59 +4,30 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import React from 'react';
8
- /*
9
- Minimal implementation of a React interpolate component.
10
- We don't ship a markdown parser nor a feature-complete i18n library on purpose.
11
- More details here: https://github.com/facebook/docusaurus/pull/4295
12
- */
13
- const ValueRegexp = /{\w+}/g;
14
- const ValueFoundMarker = '{}'; // does not care much
7
+ import React, { isValidElement } from 'react';
15
8
  export function interpolate(text, values) {
16
- const elements = [];
17
- const processedText = text.replace(ValueRegexp, (match) => {
18
- // remove {{ and }} around the placeholder
19
- const key = match.substr(1, match.length - 2);
20
- const value = values === null || values === void 0 ? void 0 : values[key];
21
- if (typeof value !== 'undefined') {
22
- const element = React.isValidElement(value)
23
- ? value
24
- : // For non-React elements: basic primitive->string conversion
25
- String(value);
26
- elements.push(element);
27
- return ValueFoundMarker;
28
- }
29
- else {
30
- return match; // no match? add warning?
9
+ // eslint-disable-next-line prefer-named-capture-group
10
+ const segments = text.split(/(\{\w+\})/).map((seg, index) => {
11
+ // Odd indices (1, 3, 5...) of the segments are (potentially) interpolatable
12
+ if (index % 2 === 1) {
13
+ const value = values?.[seg.slice(1, -1)];
14
+ if (value !== undefined) {
15
+ return value;
16
+ }
17
+ // No match: add warning? There's no way to "escape" interpolation though
31
18
  }
19
+ return seg;
32
20
  });
33
- // No interpolation to be done: just return the text
34
- if (elements.length === 0) {
35
- return text;
36
- }
37
- // Basic string interpolation: returns interpolated string
38
- else if (elements.every((el) => typeof el === 'string')) {
39
- return processedText
40
- .split(ValueFoundMarker)
41
- .reduce((str, value, index) => {
42
- var _a;
43
- return str.concat(value).concat((_a = elements[index]) !== null && _a !== void 0 ? _a : '');
44
- }, '');
45
- }
46
- // JSX interpolation: returns ReactNode
47
- else {
48
- return processedText
49
- .split(ValueFoundMarker)
50
- .reduce((array, value, index) => {
51
- return [
52
- ...array,
53
- React.createElement(React.Fragment, { key: index },
54
- value,
55
- elements[index]),
56
- ];
57
- }, []);
21
+ if (segments.some((seg) => isValidElement(seg))) {
22
+ return segments
23
+ .map((seg, index) => isValidElement(seg) ? React.cloneElement(seg, { key: index }) : seg)
24
+ .filter((seg) => seg !== '');
58
25
  }
26
+ return segments.join('');
59
27
  }
60
28
  export default function Interpolate({ children, values, }) {
61
- return interpolate(children, values);
29
+ if (typeof children !== 'string') {
30
+ throw new Error(`The Docusaurus <Interpolate> component only accept simple string values. Received: ${isValidElement(children) ? 'React element' : typeof children}`);
31
+ }
32
+ return <>{interpolate(children, values)}</>;
62
33
  }
@@ -5,13 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  /// <reference types="@docusaurus/module-type-aliases" />
8
- /// <reference types="react" />
9
- import type { LinkProps } from '@docusaurus/Link';
10
- import type docusaurus from '../docusaurus';
11
- declare global {
12
- interface Window {
13
- docusaurus: typeof docusaurus;
14
- }
15
- }
16
- declare function Link({ isNavLink, to, href, activeClassName, isActive, 'data-noBrokenLinkCheck': noBrokenLinkCheck, autoAddBaseUrl, ...props }: LinkProps): JSX.Element;
17
- export default Link;
8
+ import React from 'react';
9
+ import type { Props } from '@docusaurus/Link';
10
+ declare const _default: React.ForwardRefExoticComponent<Pick<Props, "children" | "replace" | "slot" | "style" | "title" | "location" | "component" | "exact" | "sensitive" | "strict" | "type" | "key" | "id" | "lang" | "dir" | "rel" | "href" | "isNavLink" | "className" | "to" | "innerRef" | "download" | "hrefLang" | "media" | "ping" | "target" | "referrerPolicy" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "draggable" | "hidden" | "placeholder" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "activeClassName" | "activeStyle" | "isActive" | "data-noBrokenLinkCheck" | "autoAddBaseUrl"> & React.RefAttributes<HTMLAnchorElement>>;
11
+ export default _default;
@@ -4,22 +4,26 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import React, { useEffect, useRef } from 'react';
7
+ import React, { useEffect, useImperativeHandle, useRef, } from 'react';
8
8
  import { NavLink, Link as RRLink } from 'react-router-dom';
9
+ import useDocusaurusContext from './useDocusaurusContext';
9
10
  import isInternalUrl from './isInternalUrl';
10
11
  import ExecutionEnvironment from './ExecutionEnvironment';
11
12
  import { useLinksCollector } from '../LinksCollector';
12
13
  import { useBaseUrlUtils } from './useBaseUrl';
14
+ import { applyTrailingSlash } from '@docusaurus/utils-common';
13
15
  // TODO all this wouldn't be necessary if we used ReactRouter basename feature
14
16
  // We don't automatically add base urls to all links,
15
17
  // only the "safe" ones, starting with / (like /docs/introduction)
16
18
  // this is because useBaseUrl() actually transforms relative links
17
19
  // like "introduction" to "/baseUrl/introduction" => bad behavior to fix
18
20
  const shouldAddBaseUrlAutomatically = (to) => to.startsWith('/');
19
- function Link({ isNavLink, to, href, activeClassName, isActive, 'data-noBrokenLinkCheck': noBrokenLinkCheck, autoAddBaseUrl = true, ...props }) {
20
- var _a;
21
+ function Link({ isNavLink, to, href, activeClassName, isActive, 'data-noBrokenLinkCheck': noBrokenLinkCheck, autoAddBaseUrl = true, ...props }, forwardedRef) {
22
+ const { siteConfig: { trailingSlash, baseUrl }, } = useDocusaurusContext();
21
23
  const { withBaseUrl } = useBaseUrlUtils();
22
24
  const linksCollector = useLinksCollector();
25
+ const innerRef = useRef(null);
26
+ useImperativeHandle(forwardedRef, () => innerRef.current);
23
27
  // IMPORTANT: using to or href should not change anything
24
28
  // For example, MDX links will ALWAYS give us the href props
25
29
  // Using one prop or the other should not be used to distinguish
@@ -37,41 +41,40 @@ function Link({ isNavLink, to, href, activeClassName, isActive, 'data-noBrokenLi
37
41
  // see https://github.com/facebook/docusaurus/issues/3309
38
42
  // note: we want baseUrl to be appended (see issue for details)
39
43
  // TODO read routes and automatically detect internal/external links?
40
- const targetLinkWithoutPathnameProtocol = targetLinkUnprefixed === null || targetLinkUnprefixed === void 0 ? void 0 : targetLinkUnprefixed.replace('pathname://', '');
44
+ const targetLinkWithoutPathnameProtocol = targetLinkUnprefixed?.replace('pathname://', '');
41
45
  // TODO we should use ReactRouter basename feature instead!
42
46
  // Automatically apply base url in links that start with /
43
- const targetLink = typeof targetLinkWithoutPathnameProtocol !== 'undefined'
47
+ let targetLink = typeof targetLinkWithoutPathnameProtocol !== 'undefined'
44
48
  ? maybeAddBaseUrl(targetLinkWithoutPathnameProtocol)
45
49
  : undefined;
50
+ if (targetLink && isInternal) {
51
+ targetLink = applyTrailingSlash(targetLink, { trailingSlash, baseUrl });
52
+ }
46
53
  const preloaded = useRef(false);
47
- const LinkComponent = isNavLink ? NavLink : RRLink;
54
+ const LinkComponent = (isNavLink ? NavLink : RRLink);
48
55
  const IOSupported = ExecutionEnvironment.canUseIntersectionObserver;
49
- let io;
50
- const handleIntersection = (el, cb) => {
51
- io = new window.IntersectionObserver((entries) => {
52
- entries.forEach((entry) => {
53
- if (el === entry.target) {
54
- // If element is in viewport, stop listening/observing and run callback.
55
- // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
56
- if (entry.isIntersecting || entry.intersectionRatio > 0) {
57
- io.unobserve(el);
58
- io.disconnect();
59
- cb();
56
+ const ioRef = useRef();
57
+ const handleRef = (el) => {
58
+ innerRef.current = el;
59
+ if (IOSupported && el && isInternal) {
60
+ // If IO supported and element reference found, set up Observer.
61
+ ioRef.current = new window.IntersectionObserver((entries) => {
62
+ entries.forEach((entry) => {
63
+ if (el === entry.target) {
64
+ // If element is in viewport, stop observing and run callback.
65
+ // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
66
+ if (entry.isIntersecting || entry.intersectionRatio > 0) {
67
+ ioRef.current.unobserve(el);
68
+ ioRef.current.disconnect();
69
+ if (targetLink != null) {
70
+ window.docusaurus.prefetch(targetLink);
71
+ }
72
+ }
60
73
  }
61
- }
62
- });
63
- });
64
- // Add element to the observer.
65
- io.observe(el);
66
- };
67
- const handleRef = (ref) => {
68
- if (IOSupported && ref && isInternal) {
69
- // If IO supported and element reference found, setup Observer functionality.
70
- handleIntersection(ref, () => {
71
- if (targetLink != null) {
72
- window.docusaurus.prefetch(targetLink);
73
- }
74
+ });
74
75
  });
76
+ // Add element to the observer.
77
+ ioRef.current.observe(el);
75
78
  }
76
79
  };
77
80
  const onMouseEnter = () => {
@@ -89,19 +92,22 @@ function Link({ isNavLink, to, href, activeClassName, isActive, 'data-noBrokenLi
89
92
  }
90
93
  // When unmounting, stop intersection observer from watching.
91
94
  return () => {
92
- if (IOSupported && io) {
93
- io.disconnect();
95
+ if (IOSupported && ioRef.current) {
96
+ ioRef.current.disconnect();
94
97
  }
95
98
  };
96
- }, [targetLink, IOSupported, isInternal]);
97
- const isAnchorLink = (_a = targetLink === null || targetLink === void 0 ? void 0 : targetLink.startsWith('#')) !== null && _a !== void 0 ? _a : false;
99
+ }, [ioRef, targetLink, IOSupported, isInternal]);
100
+ const isAnchorLink = targetLink?.startsWith('#') ?? false;
98
101
  const isRegularHtmlLink = !targetLink || !isInternal || isAnchorLink;
99
- if (targetLink && isInternal && !isAnchorLink && !noBrokenLinkCheck) {
102
+ if (!isRegularHtmlLink && !noBrokenLinkCheck) {
100
103
  linksCollector.collectLink(targetLink);
101
104
  }
102
105
  return isRegularHtmlLink ? (
103
106
  // eslint-disable-next-line jsx-a11y/anchor-has-content
104
- React.createElement("a", Object.assign({ href: targetLink }, (targetLinkUnprefixed &&
105
- !isInternal && { target: '_blank', rel: 'noopener noreferrer' }), props))) : (React.createElement(LinkComponent, Object.assign({}, props, { onMouseEnter: onMouseEnter, innerRef: handleRef, to: targetLink || '' }, (isNavLink && { isActive, activeClassName }))));
107
+ <a ref={innerRef} href={targetLink} {...(targetLinkUnprefixed &&
108
+ !isInternal && { target: '_blank', rel: 'noopener noreferrer' })} {...props}/>) : (<LinkComponent {...props} onMouseEnter={onMouseEnter} innerRef={handleRef} to={targetLink}
109
+ // Avoid "React does not recognize the `activeClassName` prop on a DOM
110
+ // element"
111
+ {...(isNavLink && { isActive, activeClassName })}/>);
106
112
  }
107
- export default Link;
113
+ export default React.forwardRef(Link);
@@ -6,7 +6,7 @@
6
6
  */
7
7
  /// <reference types="@docusaurus/module-type-aliases" />
8
8
  /// <reference types="react" />
9
- import { InterpolateValues } from '@docusaurus/Interpolate';
9
+ import { type InterpolateValues } from '@docusaurus/Interpolate';
10
10
  import type { TranslateParam, TranslateProps } from '@docusaurus/Translate';
11
11
  export declare function translate<Str extends string>({ message, id }: TranslateParam<Str>, values?: InterpolateValues<Str, string | number>): string;
12
12
  export default function Translate<Str extends string>({ children, id, values, }: TranslateProps<Str>): JSX.Element;
@@ -5,25 +5,30 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React from 'react';
8
- import Interpolate, { interpolate, } from '@docusaurus/Interpolate';
8
+ import { interpolate } from '@docusaurus/Interpolate';
9
9
  // Can't read it from context, due to exposing imperative API
10
10
  import codeTranslations from '@generated/codeTranslations';
11
11
  function getLocalizedMessage({ id, message, }) {
12
- var _a;
13
- return (_a = codeTranslations[id !== null && id !== void 0 ? id : message]) !== null && _a !== void 0 ? _a : message;
12
+ if (typeof id === 'undefined' && typeof message === 'undefined') {
13
+ throw new Error('Docusaurus translation declarations must have at least a translation id or a default translation message');
14
+ }
15
+ return codeTranslations[(id ?? message)] ?? message ?? id;
14
16
  }
15
17
  // Imperative translation API is useful for some edge-cases:
16
18
  // - translating page titles (meta)
17
19
  // - translating string props (input placeholders, image alt, aria labels...)
18
20
  export function translate({ message, id }, values) {
19
- var _a;
20
- const localizedMessage = (_a = getLocalizedMessage({ message, id })) !== null && _a !== void 0 ? _a : message;
21
+ const localizedMessage = getLocalizedMessage({ message, id });
21
22
  return interpolate(localizedMessage, values);
22
23
  }
23
24
  // Maybe we'll want to improve this component with additional features
24
- // Like toggling a translation mode that adds a little translation button near the text?
25
+ // Like toggling a translation mode that adds a little translation button near
26
+ // the text?
25
27
  export default function Translate({ children, id, values, }) {
26
- var _a;
27
- const localizedMessage = (_a = getLocalizedMessage({ message: children, id })) !== null && _a !== void 0 ? _a : children;
28
- return React.createElement(Interpolate, { values: values }, localizedMessage);
28
+ if (children && typeof children !== 'string') {
29
+ console.warn('Illegal <Translate> children', children);
30
+ throw new Error('The Docusaurus <Translate> component only accept simple string values');
31
+ }
32
+ const localizedMessage = getLocalizedMessage({ message: children, id });
33
+ return <>{interpolate(localizedMessage, values)}</>;
29
34
  }
@@ -4,15 +4,5 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- /*
8
- // eslint-disable-next-line no-restricted-imports
9
- export {
10
- // constants were only available on node
11
- // this makes some useful constants available to frontend/themes too
12
- // import {DEFAULT_PLUGIN_ID} '@docusaurus/constants'
13
- DEFAULT_PLUGIN_ID,
14
- } from '../../constants';
15
- */
16
- // Not duplicating the constants seems to produce
17
- // weird TS compilation side-effects
7
+ // Constants used on the client-side: duplicated from server-side code
18
8
  export const DEFAULT_PLUGIN_ID = 'default';
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  export function hasProtocol(url) {
8
- return /^(\w*:|\/\/)/.test(url) === true;
8
+ return /^(?:\w*:|\/\/)/.test(url) === true;
9
9
  }
10
10
  export default function isInternalUrl(url) {
11
11
  return typeof url !== 'undefined' && !hasProtocol(url);
@@ -4,5 +4,4 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import { renderRoutes } from 'react-router-config';
8
- export default renderRoutes;
7
+ export { renderRoutes as default } from 'react-router-config';
@@ -4,5 +4,4 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import { renderRoutes } from 'react-router-config';
8
- export default renderRoutes;
7
+ export { renderRoutes as default } from 'react-router-config';
@@ -4,4 +4,4 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- export * from 'react-router-dom';
7
+ export { useHistory, useLocation, Redirect, matchPath } from 'react-router-dom';
@@ -4,4 +4,4 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- export * from 'react-router-dom';
7
+ export { useHistory, useLocation, Redirect, matchPath } from 'react-router-dom';
@@ -7,19 +7,18 @@
7
7
  import useDocusaurusContext from './useDocusaurusContext';
8
8
  import { hasProtocol } from './isInternalUrl';
9
9
  function addBaseUrl(siteUrl, baseUrl, url, { forcePrependBaseUrl = false, absolute = false } = {}) {
10
- if (!url) {
11
- return url;
12
- }
13
- // it never makes sense to add a base url to a local anchor url
14
- if (url.startsWith('#')) {
15
- return url;
16
- }
17
- // it never makes sense to add a base url to an url with a protocol
18
- if (hasProtocol(url)) {
10
+ // It never makes sense to add base url to a local anchor url, or one with a
11
+ // protocol
12
+ if (!url || url.startsWith('#') || hasProtocol(url)) {
19
13
  return url;
20
14
  }
21
15
  if (forcePrependBaseUrl) {
22
- return baseUrl + url;
16
+ return baseUrl + url.replace(/^\//, '');
17
+ }
18
+ // /baseUrl -> /baseUrl/
19
+ // https://github.com/facebook/docusaurus/issues/6315
20
+ if (url === baseUrl.replace(/\/$/, '')) {
21
+ return baseUrl;
23
22
  }
24
23
  // We should avoid adding the baseurl twice if it's already there
25
24
  const shouldAddBaseUrl = !url.startsWith(baseUrl);
@@ -27,11 +26,9 @@ function addBaseUrl(siteUrl, baseUrl, url, { forcePrependBaseUrl = false, absolu
27
26
  return absolute ? siteUrl + basePath : basePath;
28
27
  }
29
28
  export function useBaseUrlUtils() {
30
- const { siteConfig: { baseUrl = '/', url: siteUrl } = {}, } = useDocusaurusContext();
29
+ const { siteConfig: { baseUrl, url: siteUrl }, } = useDocusaurusContext();
31
30
  return {
32
- withBaseUrl: (url, options) => {
33
- return addBaseUrl(siteUrl, baseUrl, url, options);
34
- },
31
+ withBaseUrl: (url, options) => addBaseUrl(siteUrl, baseUrl, url, options),
35
32
  };
36
33
  }
37
34
  export default function useBaseUrl(url, options = {}) {