@docusaurus/plugin-content-docs 0.0.0-5264 → 0.0.0-5265

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.
package/lib/index.js CHANGED
@@ -19,10 +19,7 @@ const versions_1 = require("./versions");
19
19
  const cli_1 = require("./cli");
20
20
  const constants_1 = require("./constants");
21
21
  const globalData_1 = require("./globalData");
22
- const props_1 = require("./props");
23
- const categoryGeneratedIndex_1 = require("./categoryGeneratedIndex");
24
22
  const translations_1 = require("./translations");
25
- const tags_1 = require("./tags");
26
23
  const routes_1 = require("./routes");
27
24
  const utils_2 = require("./sidebars/utils");
28
25
  async function pluginContentDocs(context, options) {
@@ -125,77 +122,18 @@ async function pluginContentDocs(context, options) {
125
122
  return (0, translations_1.translateLoadedContent)(content, translationFiles);
126
123
  },
127
124
  async contentLoaded({ content, actions }) {
128
- const { loadedVersions } = content;
129
- const { docLayoutComponent, docItemComponent, docCategoryGeneratedIndexComponent, breadcrumbs, } = options;
130
- const { addRoute, createData, setGlobalData } = actions;
131
- const versions = loadedVersions.map((version) => {
132
- const sidebarsUtils = (0, utils_2.createSidebarsUtils)(version.sidebars);
133
- return {
134
- ...version,
135
- sidebarsUtils,
136
- categoryGeneratedIndices: (0, categoryGeneratedIndex_1.getCategoryGeneratedIndexMetadataList)({
137
- docs: version.docs,
138
- sidebarsUtils,
139
- }),
140
- };
141
- });
142
- async function createVersionTagsRoutes(version) {
143
- const versionTags = (0, tags_1.getVersionTags)(version.docs);
144
- // TODO tags should be a sub route of the version route
145
- async function createTagsListPage() {
146
- const tagsProp = Object.values(versionTags).map((tagValue) => ({
147
- label: tagValue.label,
148
- permalink: tagValue.permalink,
149
- count: tagValue.docIds.length,
150
- }));
151
- // Only create /tags page if there are tags.
152
- if (tagsProp.length > 0) {
153
- const tagsPropPath = await createData(`${(0, utils_1.docuHash)(`tags-list-${version.versionName}-prop`)}.json`, JSON.stringify(tagsProp, null, 2));
154
- addRoute({
155
- path: version.tagsPath,
156
- exact: true,
157
- component: options.docTagsListComponent,
158
- modules: {
159
- tags: aliasedSource(tagsPropPath),
160
- },
161
- });
162
- }
163
- }
164
- // TODO tags should be a sub route of the version route
165
- async function createTagDocListPage(tag) {
166
- const tagProps = (0, props_1.toTagDocListProp)({
167
- allTagsPath: version.tagsPath,
168
- tag,
169
- docs: version.docs,
170
- });
171
- const tagPropPath = await createData(`${(0, utils_1.docuHash)(`tag-${tag.permalink}`)}.json`, JSON.stringify(tagProps, null, 2));
172
- addRoute({
173
- path: tag.permalink,
174
- component: options.docTagDocListComponent,
175
- exact: true,
176
- modules: {
177
- tag: aliasedSource(tagPropPath),
178
- },
179
- });
180
- }
181
- await createTagsListPage();
182
- await Promise.all(Object.values(versionTags).map(createTagDocListPage));
183
- }
184
- await Promise.all(versions.map((version) => (0, routes_1.createVersionRoutes)({
185
- version,
186
- docItemComponent,
187
- docLayoutComponent,
188
- docCategoryGeneratedIndexComponent,
189
- pluginId,
190
- aliasedSource,
125
+ const versions = content.loadedVersions.map(versions_1.toFullVersion);
126
+ await (0, routes_1.createAllRoutes)({
127
+ baseUrl,
128
+ versions,
129
+ options,
191
130
  actions,
192
- })));
193
- // TODO tags should be a sub route of the version route
194
- await Promise.all(versions.map(createVersionTagsRoutes));
195
- setGlobalData({
131
+ aliasedSource,
132
+ });
133
+ actions.setGlobalData({
196
134
  path: (0, utils_1.normalizeUrl)([baseUrl, options.routeBasePath]),
197
135
  versions: versions.map(globalData_1.toGlobalDataVersion),
198
- breadcrumbs,
136
+ breadcrumbs: options.breadcrumbs,
199
137
  });
200
138
  },
201
139
  configureWebpack(_config, isServer, utils, content) {
package/lib/options.js CHANGED
@@ -21,7 +21,9 @@ exports.DEFAULT_OPTIONS = {
21
21
  exclude: utils_1.GlobExcludeDefault,
22
22
  sidebarItemsGenerator: generator_1.DefaultSidebarItemsGenerator,
23
23
  numberPrefixParser: numberPrefix_1.DefaultNumberPrefixParser,
24
- docLayoutComponent: '@theme/DocPage',
24
+ docsRootComponent: '@theme/DocsRoot',
25
+ docVersionRootComponent: '@theme/DocVersionRoot',
26
+ docRootComponent: '@theme/DocRoot',
25
27
  docItemComponent: '@theme/DocItem',
26
28
  docTagDocListComponent: '@theme/DocTagDocListPage',
27
29
  docTagsListComponent: '@theme/DocTagsListPage',
@@ -81,7 +83,9 @@ const OptionsSchema = utils_validation_1.Joi.object({
81
83
  then: utils_validation_1.Joi.custom((val) => val ? numberPrefix_1.DefaultNumberPrefixParser : numberPrefix_1.DisabledNumberPrefixParser),
82
84
  }))
83
85
  .default(() => exports.DEFAULT_OPTIONS.numberPrefixParser),
84
- docLayoutComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.docLayoutComponent),
86
+ docsRootComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.docsRootComponent),
87
+ docVersionRootComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.docVersionRootComponent),
88
+ docRootComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.docRootComponent),
85
89
  docItemComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.docItemComponent),
86
90
  docTagsListComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.docTagsListComponent),
87
91
  docTagDocListComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.docTagDocListComponent),
package/lib/props.d.ts CHANGED
@@ -4,8 +4,8 @@
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 type { VersionTag } from './types';
8
- import type { PropSidebars, PropVersionMetadata, PropTagDocList, DocMetadata, LoadedVersion } from '@docusaurus/plugin-content-docs';
7
+ import type { VersionTag, VersionTags } from './types';
8
+ import type { PropSidebars, PropVersionMetadata, PropTagDocList, PropTagsListPage, DocMetadata, LoadedVersion } from '@docusaurus/plugin-content-docs';
9
9
  export declare function toSidebarsProp(loadedVersion: LoadedVersion): PropSidebars;
10
10
  export declare function toVersionMetadataProp(pluginId: string, loadedVersion: LoadedVersion): PropVersionMetadata;
11
11
  export declare function toTagDocListProp({ allTagsPath, tag, docs, }: {
@@ -13,3 +13,4 @@ export declare function toTagDocListProp({ allTagsPath, tag, docs, }: {
13
13
  tag: VersionTag;
14
14
  docs: DocMetadata[];
15
15
  }): PropTagDocList;
16
+ export declare function toTagsListTagsProp(versionTags: VersionTags): PropTagsListPage['tags'];
package/lib/props.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.toTagDocListProp = exports.toVersionMetadataProp = exports.toSidebarsProp = void 0;
9
+ exports.toTagsListTagsProp = exports.toTagDocListProp = exports.toVersionMetadataProp = exports.toSidebarsProp = void 0;
10
10
  const tslib_1 = require("tslib");
11
11
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
12
12
  const docs_1 = require("./docs");
@@ -127,3 +127,11 @@ function toTagDocListProp({ allTagsPath, tag, docs, }) {
127
127
  };
128
128
  }
129
129
  exports.toTagDocListProp = toTagDocListProp;
130
+ function toTagsListTagsProp(versionTags) {
131
+ return Object.values(versionTags).map((tagValue) => ({
132
+ label: tagValue.label,
133
+ permalink: tagValue.permalink,
134
+ count: tagValue.docIds.length,
135
+ }));
136
+ }
137
+ exports.toTagsListTagsProp = toTagsListTagsProp;
package/lib/routes.d.ts CHANGED
@@ -6,24 +6,17 @@
6
6
  */
7
7
  import type { PluginContentLoadedActions, RouteConfig } from '@docusaurus/types';
8
8
  import type { FullVersion } from './types';
9
- import type { DocMetadata } from '@docusaurus/plugin-content-docs';
10
- export declare function createCategoryGeneratedIndexRoutes({ version, actions, docCategoryGeneratedIndexComponent, aliasedSource, }: {
11
- version: FullVersion;
9
+ import type { PluginOptions } from '@docusaurus/plugin-content-docs';
10
+ declare type BuildAllRoutesParam = Omit<CreateAllRoutesParam, 'actions'> & {
11
+ actions: Omit<PluginContentLoadedActions, 'addRoute' | 'setGlobalData'>;
12
+ };
13
+ export declare function buildAllRoutes(param: BuildAllRoutesParam): Promise<RouteConfig[]>;
14
+ declare type CreateAllRoutesParam = {
15
+ baseUrl: string;
16
+ versions: FullVersion[];
17
+ options: PluginOptions;
12
18
  actions: PluginContentLoadedActions;
13
- docCategoryGeneratedIndexComponent: string;
14
19
  aliasedSource: (str: string) => string;
15
- }): Promise<RouteConfig[]>;
16
- export declare function createDocRoutes({ docs, actions, docItemComponent, }: {
17
- docs: DocMetadata[];
18
- actions: PluginContentLoadedActions;
19
- docItemComponent: string;
20
- }): Promise<RouteConfig[]>;
21
- export declare function createVersionRoutes({ version, actions, docItemComponent, docLayoutComponent, docCategoryGeneratedIndexComponent, pluginId, aliasedSource, }: {
22
- version: FullVersion;
23
- actions: PluginContentLoadedActions;
24
- docLayoutComponent: string;
25
- docItemComponent: string;
26
- docCategoryGeneratedIndexComponent: string;
27
- pluginId: string;
28
- aliasedSource: (str: string) => string;
29
- }): Promise<void>;
20
+ };
21
+ export declare function createAllRoutes(param: CreateAllRoutesParam): Promise<void>;
22
+ export {};
package/lib/routes.js CHANGED
@@ -6,20 +6,22 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.createVersionRoutes = exports.createDocRoutes = exports.createCategoryGeneratedIndexRoutes = void 0;
9
+ exports.createAllRoutes = exports.buildAllRoutes = void 0;
10
10
  const tslib_1 = require("tslib");
11
+ const lodash_1 = tslib_1.__importDefault(require("lodash"));
11
12
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
12
13
  const utils_1 = require("@docusaurus/utils");
13
14
  const props_1 = require("./props");
14
- async function createCategoryGeneratedIndexRoutes({ version, actions, docCategoryGeneratedIndexComponent, aliasedSource, }) {
15
+ const tags_1 = require("./tags");
16
+ async function buildVersionCategoryGeneratedIndexRoutes({ version, actions, options, aliasedSource, }) {
15
17
  const slugs = (0, utils_1.createSlugger)();
16
- async function createCategoryGeneratedIndexRoute(categoryGeneratedIndex) {
18
+ async function buildCategoryGeneratedIndexRoute(categoryGeneratedIndex) {
17
19
  const { sidebar, ...prop } = categoryGeneratedIndex;
18
20
  const propFileName = slugs.slug(`${version.path}-${categoryGeneratedIndex.sidebar}-category-${categoryGeneratedIndex.title}`);
19
21
  const propData = await actions.createData(`${(0, utils_1.docuHash)(`category/${propFileName}`)}.json`, JSON.stringify(prop, null, 2));
20
22
  return {
21
23
  path: categoryGeneratedIndex.permalink,
22
- component: docCategoryGeneratedIndexComponent,
24
+ component: options.docCategoryGeneratedIndexComponent,
23
25
  exact: true,
24
26
  modules: {
25
27
  categoryGeneratedIndex: aliasedSource(propData),
@@ -29,23 +31,22 @@ async function createCategoryGeneratedIndexRoutes({ version, actions, docCategor
29
31
  ...(sidebar && { sidebar }),
30
32
  };
31
33
  }
32
- return Promise.all(version.categoryGeneratedIndices.map(createCategoryGeneratedIndexRoute));
34
+ return Promise.all(version.categoryGeneratedIndices.map(buildCategoryGeneratedIndexRoute));
33
35
  }
34
- exports.createCategoryGeneratedIndexRoutes = createCategoryGeneratedIndexRoutes;
35
- async function createDocRoutes({ docs, actions, docItemComponent, }) {
36
- return Promise.all(docs.map(async (metadataItem) => {
36
+ async function buildVersionDocRoutes({ version, actions, options, }) {
37
+ return Promise.all(version.docs.map(async (metadataItem) => {
37
38
  await actions.createData(
38
39
  // Note that this created data path must be in sync with
39
40
  // metadataPath provided to mdx-loader.
40
41
  `${(0, utils_1.docuHash)(metadataItem.source)}.json`, JSON.stringify(metadataItem, null, 2));
41
42
  const docRoute = {
42
43
  path: metadataItem.permalink,
43
- component: docItemComponent,
44
+ component: options.docItemComponent,
44
45
  exact: true,
45
46
  modules: {
46
47
  content: metadataItem.source,
47
48
  },
48
- // Because the parent (DocPage) comp need to access it easily
49
+ // Because the parent (DocRoot) comp need to access it easily
49
50
  // This permits to render the sidebar once without unmount/remount when
50
51
  // navigating (and preserve sidebar state)
51
52
  ...(metadataItem.sidebar && {
@@ -55,42 +56,113 @@ async function createDocRoutes({ docs, actions, docItemComponent, }) {
55
56
  return docRoute;
56
57
  }));
57
58
  }
58
- exports.createDocRoutes = createDocRoutes;
59
- async function createVersionRoutes({ version, actions, docItemComponent, docLayoutComponent, docCategoryGeneratedIndexComponent, pluginId, aliasedSource, }) {
60
- async function doCreateVersionRoutes() {
61
- const versionMetadata = (0, props_1.toVersionMetadataProp)(pluginId, version);
62
- const versionMetadataPropPath = await actions.createData(`${(0, utils_1.docuHash)(`version-${version.versionName}-metadata-prop`)}.json`, JSON.stringify(versionMetadata, null, 2));
63
- async function createVersionSubRoutes() {
64
- const [docRoutes, sidebarsRoutes] = await Promise.all([
65
- createDocRoutes({ docs: version.docs, actions, docItemComponent }),
66
- createCategoryGeneratedIndexRoutes({
67
- version,
68
- actions,
69
- docCategoryGeneratedIndexComponent,
70
- aliasedSource,
71
- }),
72
- ]);
73
- const routes = [...docRoutes, ...sidebarsRoutes];
74
- return routes.sort((a, b) => a.path.localeCompare(b.path));
59
+ async function buildVersionSidebarRoute(param) {
60
+ const [docRoutes, categoryGeneratedIndexRoutes] = await Promise.all([
61
+ buildVersionDocRoutes(param),
62
+ buildVersionCategoryGeneratedIndexRoutes(param),
63
+ ]);
64
+ const subRoutes = [...docRoutes, ...categoryGeneratedIndexRoutes];
65
+ return {
66
+ path: param.version.path,
67
+ exact: false,
68
+ component: param.options.docRootComponent,
69
+ routes: subRoutes,
70
+ };
71
+ }
72
+ async function buildVersionTagsRoutes(param) {
73
+ const { version, options, actions, aliasedSource } = param;
74
+ const versionTags = (0, tags_1.getVersionTags)(version.docs);
75
+ async function buildTagsListRoute() {
76
+ // Don't create a tags list page if there's no tag
77
+ if (Object.keys(versionTags).length === 0) {
78
+ return null;
75
79
  }
76
- actions.addRoute({
80
+ const tagsProp = (0, props_1.toTagsListTagsProp)(versionTags);
81
+ const tagsPropPath = await actions.createData(`${(0, utils_1.docuHash)(`tags-list-${version.versionName}-prop`)}.json`, JSON.stringify(tagsProp, null, 2));
82
+ return {
83
+ path: version.tagsPath,
84
+ exact: true,
85
+ component: options.docTagsListComponent,
86
+ modules: {
87
+ tags: aliasedSource(tagsPropPath),
88
+ },
89
+ };
90
+ }
91
+ async function buildTagDocListRoute(tag) {
92
+ const tagProps = (0, props_1.toTagDocListProp)({
93
+ allTagsPath: version.tagsPath,
94
+ tag,
95
+ docs: version.docs,
96
+ });
97
+ const tagPropPath = await actions.createData(`${(0, utils_1.docuHash)(`tag-${tag.permalink}`)}.json`, JSON.stringify(tagProps, null, 2));
98
+ return {
99
+ path: tag.permalink,
100
+ component: options.docTagDocListComponent,
101
+ exact: true,
102
+ modules: {
103
+ tag: aliasedSource(tagPropPath),
104
+ },
105
+ };
106
+ }
107
+ const [tagsListRoute, allTagsDocListRoutes] = await Promise.all([
108
+ buildTagsListRoute(),
109
+ Promise.all(Object.values(versionTags).map(buildTagDocListRoute)),
110
+ ]);
111
+ return lodash_1.default.compact([tagsListRoute, ...allTagsDocListRoutes]);
112
+ }
113
+ async function buildVersionRoutes(param) {
114
+ const { version, actions, options, aliasedSource } = param;
115
+ async function buildVersionSubRoutes() {
116
+ const [sidebarRoute, tagsRoutes] = await Promise.all([
117
+ buildVersionSidebarRoute(param),
118
+ buildVersionTagsRoutes(param),
119
+ ]);
120
+ return [sidebarRoute, ...tagsRoutes];
121
+ }
122
+ async function doBuildVersionRoutes() {
123
+ const versionProp = (0, props_1.toVersionMetadataProp)(options.id, version);
124
+ const versionPropPath = await actions.createData(`${(0, utils_1.docuHash)(`version-${version.versionName}-metadata-prop`)}.json`, JSON.stringify(versionProp, null, 2));
125
+ const subRoutes = await buildVersionSubRoutes();
126
+ return {
77
127
  path: version.path,
78
- // Allow matching /docs/* since this is the wrapping route
79
128
  exact: false,
80
- component: docLayoutComponent,
81
- routes: await createVersionSubRoutes(),
129
+ component: options.docVersionRootComponent,
130
+ routes: subRoutes,
82
131
  modules: {
83
- versionMetadata: aliasedSource(versionMetadataPropPath),
132
+ version: aliasedSource(versionPropPath),
84
133
  },
85
134
  priority: version.routePriority,
86
- });
135
+ };
87
136
  }
88
137
  try {
89
- return await doCreateVersionRoutes();
138
+ return await doBuildVersionRoutes();
90
139
  }
91
140
  catch (err) {
92
141
  logger_1.default.error `Can't create version routes for version name=${version.versionName}`;
93
142
  throw err;
94
143
  }
95
144
  }
96
- exports.createVersionRoutes = createVersionRoutes;
145
+ // TODO we want this buildAllRoutes function to be easily testable
146
+ // Ideally, we should avoid side effects here (ie not injecting actions)
147
+ async function buildAllRoutes(param) {
148
+ const subRoutes = await Promise.all(param.versions.map((version) => buildVersionRoutes({
149
+ ...param,
150
+ version,
151
+ })));
152
+ // all docs routes are wrapped under a single parent route, this ensures
153
+ // the theme layout never unmounts/remounts when navigating between versions
154
+ return [
155
+ {
156
+ path: (0, utils_1.normalizeUrl)([param.baseUrl, param.options.routeBasePath]),
157
+ exact: false,
158
+ component: param.options.docsRootComponent,
159
+ routes: subRoutes,
160
+ },
161
+ ];
162
+ }
163
+ exports.buildAllRoutes = buildAllRoutes;
164
+ async function createAllRoutes(param) {
165
+ const routes = await buildAllRoutes(param);
166
+ routes.forEach(param.actions.addRoute);
167
+ }
168
+ exports.createAllRoutes = createAllRoutes;
@@ -4,8 +4,9 @@
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 type { PluginOptions, VersionBanner, VersionMetadata } from '@docusaurus/plugin-content-docs';
7
+ import type { FullVersion } from '../types';
8
8
  import type { LoadContext } from '@docusaurus/types';
9
+ import type { LoadedVersion, PluginOptions, VersionBanner, VersionMetadata } from '@docusaurus/plugin-content-docs';
9
10
  export declare type VersionContext = {
10
11
  /** The version name to get banner of. */
11
12
  versionName: string;
@@ -35,3 +36,4 @@ export declare function readVersionsMetadata({ context, options, }: {
35
36
  context: LoadContext;
36
37
  options: PluginOptions;
37
38
  }): Promise<VersionMetadata[]>;
39
+ export declare function toFullVersion(version: LoadedVersion): FullVersion;
@@ -6,13 +6,15 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.readVersionsMetadata = exports.filterVersions = exports.getVersionNoIndex = exports.getVersionBadge = exports.getVersionBanner = exports.getDefaultVersionBanner = void 0;
9
+ exports.toFullVersion = exports.readVersionsMetadata = exports.filterVersions = exports.getVersionNoIndex = exports.getVersionBadge = exports.getVersionBanner = exports.getDefaultVersionBanner = void 0;
10
10
  const tslib_1 = require("tslib");
11
11
  const path_1 = tslib_1.__importDefault(require("path"));
12
12
  const utils_1 = require("@docusaurus/utils");
13
13
  const constants_1 = require("../constants");
14
14
  const validation_1 = require("./validation");
15
15
  const files_1 = require("./files");
16
+ const utils_2 = require("../sidebars/utils");
17
+ const categoryGeneratedIndex_1 = require("../categoryGeneratedIndex");
16
18
  function getVersionEditUrls({ contentPath, contentPathLocalized, context, options, }) {
17
19
  // If the user is using the functional form of editUrl,
18
20
  // she has total freedom and we can't compute a "version edit url"
@@ -157,3 +159,15 @@ async function readVersionsMetadata({ context, options, }) {
157
159
  return versionsMetadata;
158
160
  }
159
161
  exports.readVersionsMetadata = readVersionsMetadata;
162
+ function toFullVersion(version) {
163
+ const sidebarsUtils = (0, utils_2.createSidebarsUtils)(version.sidebars);
164
+ return {
165
+ ...version,
166
+ sidebarsUtils,
167
+ categoryGeneratedIndices: (0, categoryGeneratedIndex_1.getCategoryGeneratedIndexMetadataList)({
168
+ docs: version.docs,
169
+ sidebarsUtils,
170
+ }),
171
+ };
172
+ }
173
+ exports.toFullVersion = toFullVersion;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docusaurus/plugin-content-docs",
3
- "version": "0.0.0-5264",
3
+ "version": "0.0.0-5265",
4
4
  "description": "Docs plugin for Docusaurus.",
5
5
  "main": "lib/index.js",
6
6
  "sideEffects": false,
@@ -35,13 +35,13 @@
35
35
  },
36
36
  "license": "MIT",
37
37
  "dependencies": {
38
- "@docusaurus/core": "0.0.0-5264",
39
- "@docusaurus/logger": "0.0.0-5264",
40
- "@docusaurus/mdx-loader": "0.0.0-5264",
41
- "@docusaurus/module-type-aliases": "0.0.0-5264",
42
- "@docusaurus/types": "0.0.0-5264",
43
- "@docusaurus/utils": "0.0.0-5264",
44
- "@docusaurus/utils-validation": "0.0.0-5264",
38
+ "@docusaurus/core": "0.0.0-5265",
39
+ "@docusaurus/logger": "0.0.0-5265",
40
+ "@docusaurus/mdx-loader": "0.0.0-5265",
41
+ "@docusaurus/module-type-aliases": "0.0.0-5265",
42
+ "@docusaurus/types": "0.0.0-5265",
43
+ "@docusaurus/utils": "0.0.0-5265",
44
+ "@docusaurus/utils-validation": "0.0.0-5265",
45
45
  "@types/react-router-config": "^5.0.6",
46
46
  "combine-promises": "^1.1.0",
47
47
  "fs-extra": "^10.1.0",
@@ -67,5 +67,5 @@
67
67
  "engines": {
68
68
  "node": ">=16.14"
69
69
  },
70
- "gitHead": "4b2d0fc902b4ab1fcede0f6df98c45f060a4fbfc"
70
+ "gitHead": "ac59d7c969c795c2163c8e8843c11d94e210f87f"
71
71
  }
package/src/index.ts CHANGED
@@ -27,22 +27,18 @@ import {
27
27
  addDocNavigation,
28
28
  type DocEnv,
29
29
  } from './docs';
30
- import {readVersionsMetadata} from './versions';
30
+ import {readVersionsMetadata, toFullVersion} from './versions';
31
31
  import {cliDocsVersionCommand} from './cli';
32
32
  import {VERSIONS_JSON_FILE} from './constants';
33
33
  import {toGlobalDataVersion} from './globalData';
34
- import {toTagDocListProp} from './props';
35
- import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex';
36
34
  import {
37
35
  translateLoadedContent,
38
36
  getLoadedContentTranslationFiles,
39
37
  } from './translations';
40
- import {getVersionTags} from './tags';
41
- import {createVersionRoutes} from './routes';
38
+ import {createAllRoutes} from './routes';
42
39
  import {createSidebarsUtils} from './sidebars/utils';
43
40
 
44
41
  import type {
45
- PropTagsListPage,
46
42
  PluginOptions,
47
43
  DocMetadataBase,
48
44
  VersionMetadata,
@@ -55,7 +51,6 @@ import type {
55
51
  SourceToPermalink,
56
52
  DocFile,
57
53
  DocsMarkdownOption,
58
- VersionTag,
59
54
  FullVersion,
60
55
  } from './types';
61
56
  import type {RuleSetRule} from 'webpack';
@@ -209,102 +204,20 @@ export default async function pluginContentDocs(
209
204
  },
210
205
 
211
206
  async contentLoaded({content, actions}) {
212
- const {loadedVersions} = content;
213
- const {
214
- docLayoutComponent,
215
- docItemComponent,
216
- docCategoryGeneratedIndexComponent,
217
- breadcrumbs,
218
- } = options;
219
- const {addRoute, createData, setGlobalData} = actions;
220
- const versions: FullVersion[] = loadedVersions.map((version) => {
221
- const sidebarsUtils = createSidebarsUtils(version.sidebars);
222
- return {
223
- ...version,
224
- sidebarsUtils,
225
- categoryGeneratedIndices: getCategoryGeneratedIndexMetadataList({
226
- docs: version.docs,
227
- sidebarsUtils,
228
- }),
229
- };
207
+ const versions: FullVersion[] = content.loadedVersions.map(toFullVersion);
208
+
209
+ await createAllRoutes({
210
+ baseUrl,
211
+ versions,
212
+ options,
213
+ actions,
214
+ aliasedSource,
230
215
  });
231
216
 
232
- async function createVersionTagsRoutes(version: FullVersion) {
233
- const versionTags = getVersionTags(version.docs);
234
-
235
- // TODO tags should be a sub route of the version route
236
- async function createTagsListPage() {
237
- const tagsProp: PropTagsListPage['tags'] = Object.values(
238
- versionTags,
239
- ).map((tagValue) => ({
240
- label: tagValue.label,
241
- permalink: tagValue.permalink,
242
- count: tagValue.docIds.length,
243
- }));
244
-
245
- // Only create /tags page if there are tags.
246
- if (tagsProp.length > 0) {
247
- const tagsPropPath = await createData(
248
- `${docuHash(`tags-list-${version.versionName}-prop`)}.json`,
249
- JSON.stringify(tagsProp, null, 2),
250
- );
251
- addRoute({
252
- path: version.tagsPath,
253
- exact: true,
254
- component: options.docTagsListComponent,
255
- modules: {
256
- tags: aliasedSource(tagsPropPath),
257
- },
258
- });
259
- }
260
- }
261
-
262
- // TODO tags should be a sub route of the version route
263
- async function createTagDocListPage(tag: VersionTag) {
264
- const tagProps = toTagDocListProp({
265
- allTagsPath: version.tagsPath,
266
- tag,
267
- docs: version.docs,
268
- });
269
- const tagPropPath = await createData(
270
- `${docuHash(`tag-${tag.permalink}`)}.json`,
271
- JSON.stringify(tagProps, null, 2),
272
- );
273
- addRoute({
274
- path: tag.permalink,
275
- component: options.docTagDocListComponent,
276
- exact: true,
277
- modules: {
278
- tag: aliasedSource(tagPropPath),
279
- },
280
- });
281
- }
282
-
283
- await createTagsListPage();
284
- await Promise.all(Object.values(versionTags).map(createTagDocListPage));
285
- }
286
-
287
- await Promise.all(
288
- versions.map((version) =>
289
- createVersionRoutes({
290
- version,
291
- docItemComponent,
292
- docLayoutComponent,
293
- docCategoryGeneratedIndexComponent,
294
- pluginId,
295
- aliasedSource,
296
- actions,
297
- }),
298
- ),
299
- );
300
-
301
- // TODO tags should be a sub route of the version route
302
- await Promise.all(versions.map(createVersionTagsRoutes));
303
-
304
- setGlobalData({
217
+ actions.setGlobalData({
305
218
  path: normalizeUrl([baseUrl, options.routeBasePath]),
306
219
  versions: versions.map(toGlobalDataVersion),
307
- breadcrumbs,
220
+ breadcrumbs: options.breadcrumbs,
308
221
  });
309
222
  },
310
223
 
package/src/options.ts CHANGED
@@ -30,7 +30,9 @@ export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'> = {
30
30
  exclude: GlobExcludeDefault,
31
31
  sidebarItemsGenerator: DefaultSidebarItemsGenerator,
32
32
  numberPrefixParser: DefaultNumberPrefixParser,
33
- docLayoutComponent: '@theme/DocPage',
33
+ docsRootComponent: '@theme/DocsRoot',
34
+ docVersionRootComponent: '@theme/DocVersionRoot',
35
+ docRootComponent: '@theme/DocRoot',
34
36
  docItemComponent: '@theme/DocItem',
35
37
  docTagDocListComponent: '@theme/DocTagDocListPage',
36
38
  docTagsListComponent: '@theme/DocTagsListPage',
@@ -104,7 +106,11 @@ const OptionsSchema = Joi.object<PluginOptions>({
104
106
  }),
105
107
  )
106
108
  .default(() => DEFAULT_OPTIONS.numberPrefixParser),
107
- docLayoutComponent: Joi.string().default(DEFAULT_OPTIONS.docLayoutComponent),
109
+ docsRootComponent: Joi.string().default(DEFAULT_OPTIONS.docsRootComponent),
110
+ docVersionRootComponent: Joi.string().default(
111
+ DEFAULT_OPTIONS.docVersionRootComponent,
112
+ ),
113
+ docRootComponent: Joi.string().default(DEFAULT_OPTIONS.docRootComponent),
108
114
  docItemComponent: Joi.string().default(DEFAULT_OPTIONS.docItemComponent),
109
115
  docTagsListComponent: Joi.string().default(
110
116
  DEFAULT_OPTIONS.docTagsListComponent,
@@ -198,10 +198,24 @@ declare module '@docusaurus/plugin-content-docs' {
198
198
  */
199
199
  exclude: string[];
200
200
  /**
201
- * Root layout component of each doc page. Provides the version data
202
- * context, and is not unmounted when switching docs.
201
+ * Parent component of all the docs plugin pages (including all versions).
202
+ * Stays mounted when navigation between docs pages and versions.
203
203
  */
204
- docLayoutComponent: string;
204
+ docsRootComponent: string;
205
+ /**
206
+ * Parent component of all docs pages of an individual version:
207
+ * - docs pages with sidebars
208
+ * - tags pages
209
+ * Stays mounted when navigation between pages of that specific version.
210
+ */
211
+ docVersionRootComponent: string;
212
+ /**
213
+ * Parent component of all docs pages with sidebars:
214
+ * - regular docs pages
215
+ * - category generated index pages
216
+ * Stays mounted when navigation between such pages.
217
+ */
218
+ docRootComponent: string;
205
219
  /** Main doc container, with TOC, pagination, etc. */
206
220
  docItemComponent: string;
207
221
  /** Root component of the "docs containing tag X" page. */
@@ -610,14 +624,32 @@ declare module '@theme/DocBreadcrumbs' {
610
624
  export default function DocBreadcrumbs(): JSX.Element;
611
625
  }
612
626
 
613
- declare module '@theme/DocPage' {
627
+ declare module '@theme/DocsRoot' {
628
+ import type {RouteConfigComponentProps} from 'react-router-config';
629
+ import type {Required} from 'utility-types';
630
+
631
+ export interface Props extends Required<RouteConfigComponentProps, 'route'> {}
632
+
633
+ export default function DocsRoot(props: Props): JSX.Element;
634
+ }
635
+
636
+ declare module '@theme/DocVersionRoot' {
614
637
  import type {PropVersionMetadata} from '@docusaurus/plugin-content-docs';
615
638
  import type {RouteConfigComponentProps} from 'react-router-config';
616
639
  import type {Required} from 'utility-types';
617
640
 
618
641
  export interface Props extends Required<RouteConfigComponentProps, 'route'> {
619
- readonly versionMetadata: PropVersionMetadata;
642
+ readonly version: PropVersionMetadata;
620
643
  }
621
644
 
622
- export default function DocPage(props: Props): JSX.Element;
645
+ export default function DocVersionRoot(props: Props): JSX.Element;
646
+ }
647
+
648
+ declare module '@theme/DocRoot' {
649
+ import type {RouteConfigComponentProps} from 'react-router-config';
650
+ import type {Required} from 'utility-types';
651
+
652
+ export interface Props extends Required<RouteConfigComponentProps, 'route'> {}
653
+
654
+ export default function DocRoot(props: Props): JSX.Element;
623
655
  }
package/src/props.ts CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  import _ from 'lodash';
9
9
  import {createDocsByIdIndex} from './docs';
10
- import type {VersionTag} from './types';
10
+ import type {VersionTag, VersionTags} from './types';
11
11
  import type {
12
12
  SidebarItemDoc,
13
13
  SidebarItem,
@@ -21,6 +21,7 @@ import type {
21
21
  PropSidebarItemCategory,
22
22
  PropTagDocList,
23
23
  PropTagDocListDoc,
24
+ PropTagsListPage,
24
25
  PropSidebarItemLink,
25
26
  PropVersionDocs,
26
27
  DocMetadata,
@@ -181,3 +182,13 @@ export function toTagDocListProp({
181
182
  items: toDocListProp(),
182
183
  };
183
184
  }
185
+
186
+ export function toTagsListTagsProp(
187
+ versionTags: VersionTags,
188
+ ): PropTagsListPage['tags'] {
189
+ return Object.values(versionTags).map((tagValue) => ({
190
+ label: tagValue.label,
191
+ permalink: tagValue.permalink,
192
+ count: tagValue.docIds.length,
193
+ }));
194
+ }
package/src/routes.ts CHANGED
@@ -5,30 +5,32 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ import _ from 'lodash';
8
9
  import logger from '@docusaurus/logger';
9
- import {docuHash, createSlugger} from '@docusaurus/utils';
10
- import {toVersionMetadataProp} from './props';
10
+ import {docuHash, createSlugger, normalizeUrl} from '@docusaurus/utils';
11
+ import {
12
+ toTagDocListProp,
13
+ toTagsListTagsProp,
14
+ toVersionMetadataProp,
15
+ } from './props';
16
+ import {getVersionTags} from './tags';
11
17
  import type {PluginContentLoadedActions, RouteConfig} from '@docusaurus/types';
12
- import type {FullVersion} from './types';
18
+ import type {FullVersion, VersionTag} from './types';
13
19
  import type {
14
20
  CategoryGeneratedIndexMetadata,
15
- DocMetadata,
21
+ PluginOptions,
22
+ PropTagsListPage,
16
23
  } from '@docusaurus/plugin-content-docs';
17
24
 
18
- export async function createCategoryGeneratedIndexRoutes({
25
+ async function buildVersionCategoryGeneratedIndexRoutes({
19
26
  version,
20
27
  actions,
21
- docCategoryGeneratedIndexComponent,
28
+ options,
22
29
  aliasedSource,
23
- }: {
24
- version: FullVersion;
25
- actions: PluginContentLoadedActions;
26
- docCategoryGeneratedIndexComponent: string;
27
- aliasedSource: (str: string) => string;
28
- }): Promise<RouteConfig[]> {
30
+ }: BuildVersionRoutesParam): Promise<RouteConfig[]> {
29
31
  const slugs = createSlugger();
30
32
 
31
- async function createCategoryGeneratedIndexRoute(
33
+ async function buildCategoryGeneratedIndexRoute(
32
34
  categoryGeneratedIndex: CategoryGeneratedIndexMetadata,
33
35
  ): Promise<RouteConfig> {
34
36
  const {sidebar, ...prop} = categoryGeneratedIndex;
@@ -44,7 +46,7 @@ export async function createCategoryGeneratedIndexRoutes({
44
46
 
45
47
  return {
46
48
  path: categoryGeneratedIndex.permalink,
47
- component: docCategoryGeneratedIndexComponent,
49
+ component: options.docCategoryGeneratedIndexComponent,
48
50
  exact: true,
49
51
  modules: {
50
52
  categoryGeneratedIndex: aliasedSource(propData),
@@ -56,21 +58,17 @@ export async function createCategoryGeneratedIndexRoutes({
56
58
  }
57
59
 
58
60
  return Promise.all(
59
- version.categoryGeneratedIndices.map(createCategoryGeneratedIndexRoute),
61
+ version.categoryGeneratedIndices.map(buildCategoryGeneratedIndexRoute),
60
62
  );
61
63
  }
62
64
 
63
- export async function createDocRoutes({
64
- docs,
65
+ async function buildVersionDocRoutes({
66
+ version,
65
67
  actions,
66
- docItemComponent,
67
- }: {
68
- docs: DocMetadata[];
69
- actions: PluginContentLoadedActions;
70
- docItemComponent: string;
71
- }): Promise<RouteConfig[]> {
68
+ options,
69
+ }: BuildVersionRoutesParam): Promise<RouteConfig[]> {
72
70
  return Promise.all(
73
- docs.map(async (metadataItem) => {
71
+ version.docs.map(async (metadataItem) => {
74
72
  await actions.createData(
75
73
  // Note that this created data path must be in sync with
76
74
  // metadataPath provided to mdx-loader.
@@ -80,12 +78,12 @@ export async function createDocRoutes({
80
78
 
81
79
  const docRoute: RouteConfig = {
82
80
  path: metadataItem.permalink,
83
- component: docItemComponent,
81
+ component: options.docItemComponent,
84
82
  exact: true,
85
83
  modules: {
86
84
  content: metadataItem.source,
87
85
  },
88
- // Because the parent (DocPage) comp need to access it easily
86
+ // Because the parent (DocRoot) comp need to access it easily
89
87
  // This permits to render the sidebar once without unmount/remount when
90
88
  // navigating (and preserve sidebar state)
91
89
  ...(metadataItem.sidebar && {
@@ -98,62 +96,160 @@ export async function createDocRoutes({
98
96
  );
99
97
  }
100
98
 
101
- export async function createVersionRoutes({
102
- version,
103
- actions,
104
- docItemComponent,
105
- docLayoutComponent,
106
- docCategoryGeneratedIndexComponent,
107
- pluginId,
108
- aliasedSource,
109
- }: {
110
- version: FullVersion;
111
- actions: PluginContentLoadedActions;
112
- docLayoutComponent: string;
113
- docItemComponent: string;
114
- docCategoryGeneratedIndexComponent: string;
115
- pluginId: string;
116
- aliasedSource: (str: string) => string;
117
- }): Promise<void> {
118
- async function doCreateVersionRoutes(): Promise<void> {
119
- const versionMetadata = toVersionMetadataProp(pluginId, version);
120
- const versionMetadataPropPath = await actions.createData(
121
- `${docuHash(`version-${version.versionName}-metadata-prop`)}.json`,
122
- JSON.stringify(versionMetadata, null, 2),
123
- );
99
+ async function buildVersionSidebarRoute(param: BuildVersionRoutesParam) {
100
+ const [docRoutes, categoryGeneratedIndexRoutes] = await Promise.all([
101
+ buildVersionDocRoutes(param),
102
+ buildVersionCategoryGeneratedIndexRoutes(param),
103
+ ]);
104
+ const subRoutes = [...docRoutes, ...categoryGeneratedIndexRoutes];
105
+ return {
106
+ path: param.version.path,
107
+ exact: false,
108
+ component: param.options.docRootComponent,
109
+ routes: subRoutes,
110
+ };
111
+ }
124
112
 
125
- async function createVersionSubRoutes() {
126
- const [docRoutes, sidebarsRoutes] = await Promise.all([
127
- createDocRoutes({docs: version.docs, actions, docItemComponent}),
128
- createCategoryGeneratedIndexRoutes({
129
- version,
130
- actions,
131
- docCategoryGeneratedIndexComponent,
132
- aliasedSource,
133
- }),
134
- ]);
113
+ async function buildVersionTagsRoutes(
114
+ param: BuildVersionRoutesParam,
115
+ ): Promise<RouteConfig[]> {
116
+ const {version, options, actions, aliasedSource} = param;
117
+ const versionTags = getVersionTags(version.docs);
135
118
 
136
- const routes = [...docRoutes, ...sidebarsRoutes];
137
- return routes.sort((a, b) => a.path.localeCompare(b.path));
119
+ async function buildTagsListRoute(): Promise<RouteConfig | null> {
120
+ // Don't create a tags list page if there's no tag
121
+ if (Object.keys(versionTags).length === 0) {
122
+ return null;
138
123
  }
124
+ const tagsProp: PropTagsListPage['tags'] = toTagsListTagsProp(versionTags);
125
+ const tagsPropPath = await actions.createData(
126
+ `${docuHash(`tags-list-${version.versionName}-prop`)}.json`,
127
+ JSON.stringify(tagsProp, null, 2),
128
+ );
129
+ return {
130
+ path: version.tagsPath,
131
+ exact: true,
132
+ component: options.docTagsListComponent,
133
+ modules: {
134
+ tags: aliasedSource(tagsPropPath),
135
+ },
136
+ };
137
+ }
138
+
139
+ async function buildTagDocListRoute(tag: VersionTag): Promise<RouteConfig> {
140
+ const tagProps = toTagDocListProp({
141
+ allTagsPath: version.tagsPath,
142
+ tag,
143
+ docs: version.docs,
144
+ });
145
+ const tagPropPath = await actions.createData(
146
+ `${docuHash(`tag-${tag.permalink}`)}.json`,
147
+ JSON.stringify(tagProps, null, 2),
148
+ );
149
+ return {
150
+ path: tag.permalink,
151
+ component: options.docTagDocListComponent,
152
+ exact: true,
153
+ modules: {
154
+ tag: aliasedSource(tagPropPath),
155
+ },
156
+ };
157
+ }
158
+
159
+ const [tagsListRoute, allTagsDocListRoutes] = await Promise.all([
160
+ buildTagsListRoute(),
161
+ Promise.all(Object.values(versionTags).map(buildTagDocListRoute)),
162
+ ]);
163
+
164
+ return _.compact([tagsListRoute, ...allTagsDocListRoutes]);
165
+ }
166
+
167
+ type BuildVersionRoutesParam = Omit<BuildAllRoutesParam, 'versions'> & {
168
+ version: FullVersion;
169
+ };
170
+
171
+ async function buildVersionRoutes(
172
+ param: BuildVersionRoutesParam,
173
+ ): Promise<RouteConfig> {
174
+ const {version, actions, options, aliasedSource} = param;
139
175
 
140
- actions.addRoute({
176
+ async function buildVersionSubRoutes() {
177
+ const [sidebarRoute, tagsRoutes] = await Promise.all([
178
+ buildVersionSidebarRoute(param),
179
+ buildVersionTagsRoutes(param),
180
+ ]);
181
+
182
+ return [sidebarRoute, ...tagsRoutes];
183
+ }
184
+
185
+ async function doBuildVersionRoutes(): Promise<RouteConfig> {
186
+ const versionProp = toVersionMetadataProp(options.id, version);
187
+ const versionPropPath = await actions.createData(
188
+ `${docuHash(`version-${version.versionName}-metadata-prop`)}.json`,
189
+ JSON.stringify(versionProp, null, 2),
190
+ );
191
+ const subRoutes = await buildVersionSubRoutes();
192
+ return {
141
193
  path: version.path,
142
- // Allow matching /docs/* since this is the wrapping route
143
194
  exact: false,
144
- component: docLayoutComponent,
145
- routes: await createVersionSubRoutes(),
195
+ component: options.docVersionRootComponent,
196
+ routes: subRoutes,
146
197
  modules: {
147
- versionMetadata: aliasedSource(versionMetadataPropPath),
198
+ version: aliasedSource(versionPropPath),
148
199
  },
149
200
  priority: version.routePriority,
150
- });
201
+ };
151
202
  }
152
203
 
153
204
  try {
154
- return await doCreateVersionRoutes();
205
+ return await doBuildVersionRoutes();
155
206
  } catch (err) {
156
207
  logger.error`Can't create version routes for version name=${version.versionName}`;
157
208
  throw err;
158
209
  }
159
210
  }
211
+
212
+ type BuildAllRoutesParam = Omit<CreateAllRoutesParam, 'actions'> & {
213
+ actions: Omit<PluginContentLoadedActions, 'addRoute' | 'setGlobalData'>;
214
+ };
215
+
216
+ // TODO we want this buildAllRoutes function to be easily testable
217
+ // Ideally, we should avoid side effects here (ie not injecting actions)
218
+ export async function buildAllRoutes(
219
+ param: BuildAllRoutesParam,
220
+ ): Promise<RouteConfig[]> {
221
+ const subRoutes = await Promise.all(
222
+ param.versions.map((version) =>
223
+ buildVersionRoutes({
224
+ ...param,
225
+ version,
226
+ }),
227
+ ),
228
+ );
229
+
230
+ // all docs routes are wrapped under a single parent route, this ensures
231
+ // the theme layout never unmounts/remounts when navigating between versions
232
+ return [
233
+ {
234
+ path: normalizeUrl([param.baseUrl, param.options.routeBasePath]),
235
+ exact: false,
236
+ component: param.options.docsRootComponent,
237
+ routes: subRoutes,
238
+ },
239
+ ];
240
+ }
241
+
242
+ type CreateAllRoutesParam = {
243
+ baseUrl: string;
244
+ versions: FullVersion[];
245
+ options: PluginOptions;
246
+ actions: PluginContentLoadedActions;
247
+ aliasedSource: (str: string) => string;
248
+ };
249
+
250
+ export async function createAllRoutes(
251
+ param: CreateAllRoutesParam,
252
+ ): Promise<void> {
253
+ const routes = await buildAllRoutes(param);
254
+ routes.forEach(param.actions.addRoute);
255
+ }
@@ -14,12 +14,16 @@ import {
14
14
  getVersionMetadataPaths,
15
15
  readVersionNames,
16
16
  } from './files';
17
+ import {createSidebarsUtils} from '../sidebars/utils';
18
+ import {getCategoryGeneratedIndexMetadataList} from '../categoryGeneratedIndex';
19
+ import type {FullVersion} from '../types';
20
+ import type {LoadContext} from '@docusaurus/types';
17
21
  import type {
22
+ LoadedVersion,
18
23
  PluginOptions,
19
24
  VersionBanner,
20
25
  VersionMetadata,
21
26
  } from '@docusaurus/plugin-content-docs';
22
- import type {LoadContext} from '@docusaurus/types';
23
27
 
24
28
  export type VersionContext = {
25
29
  /** The version name to get banner of. */
@@ -252,3 +256,15 @@ export async function readVersionsMetadata({
252
256
  );
253
257
  return versionsMetadata;
254
258
  }
259
+
260
+ export function toFullVersion(version: LoadedVersion): FullVersion {
261
+ const sidebarsUtils = createSidebarsUtils(version.sidebars);
262
+ return {
263
+ ...version,
264
+ sidebarsUtils,
265
+ categoryGeneratedIndices: getCategoryGeneratedIndexMetadataList({
266
+ docs: version.docs,
267
+ sidebarsUtils,
268
+ }),
269
+ };
270
+ }