@docusaurus/plugin-content-docs 2.0.0-beta.15 → 2.0.0-beta.16

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 (69) hide show
  1. package/lib/cli.d.ts +1 -1
  2. package/lib/cli.js +18 -14
  3. package/lib/client/docsClientUtils.js +2 -2
  4. package/lib/client/index.d.ts +13 -1
  5. package/lib/client/index.js +66 -1
  6. package/lib/docFrontMatter.js +1 -0
  7. package/lib/docs.d.ts +2 -1
  8. package/lib/docs.js +23 -22
  9. package/lib/globalData.js +3 -2
  10. package/lib/index.js +11 -6
  11. package/lib/lastUpdate.js +14 -27
  12. package/lib/numberPrefix.js +7 -6
  13. package/lib/options.js +5 -2
  14. package/lib/props.js +15 -10
  15. package/lib/routes.js +6 -4
  16. package/lib/server-export.d.ts +8 -0
  17. package/lib/server-export.js +23 -0
  18. package/lib/sidebars/generator.d.ts +1 -9
  19. package/lib/sidebars/generator.js +26 -50
  20. package/lib/sidebars/index.d.ts +2 -5
  21. package/lib/sidebars/index.js +35 -20
  22. package/lib/sidebars/normalization.d.ts +2 -3
  23. package/lib/sidebars/normalization.js +17 -39
  24. package/lib/sidebars/postProcessor.d.ts +8 -0
  25. package/lib/sidebars/postProcessor.js +72 -0
  26. package/lib/sidebars/processor.d.ts +2 -13
  27. package/lib/sidebars/processor.js +25 -33
  28. package/lib/sidebars/types.d.ts +44 -10
  29. package/lib/sidebars/utils.js +53 -61
  30. package/lib/sidebars/validation.d.ts +2 -3
  31. package/lib/sidebars/validation.js +25 -30
  32. package/lib/slug.js +6 -8
  33. package/lib/tags.js +3 -2
  34. package/lib/translations.js +18 -17
  35. package/lib/types.d.ts +3 -6
  36. package/lib/versions.d.ts +25 -1
  37. package/lib/versions.js +25 -29
  38. package/package.json +19 -18
  39. package/src/cli.ts +25 -16
  40. package/src/client/docsClientUtils.ts +2 -2
  41. package/src/client/index.ts +97 -1
  42. package/src/docFrontMatter.ts +1 -0
  43. package/src/docs.ts +25 -20
  44. package/src/globalData.ts +2 -2
  45. package/src/index.ts +17 -7
  46. package/src/lastUpdate.ts +12 -33
  47. package/src/numberPrefix.ts +7 -6
  48. package/src/options.ts +5 -2
  49. package/src/plugin-content-docs.d.ts +16 -60
  50. package/src/props.ts +17 -12
  51. package/src/routes.ts +6 -4
  52. package/src/server-export.ts +24 -0
  53. package/src/sidebars/README.md +9 -0
  54. package/src/sidebars/generator.ts +50 -94
  55. package/src/sidebars/index.ts +50 -32
  56. package/src/sidebars/normalization.ts +22 -50
  57. package/src/sidebars/postProcessor.ts +94 -0
  58. package/src/sidebars/processor.ts +37 -66
  59. package/src/sidebars/types.ts +68 -10
  60. package/src/sidebars/utils.ts +63 -68
  61. package/src/sidebars/validation.ts +53 -53
  62. package/src/slug.ts +9 -10
  63. package/src/tags.ts +2 -2
  64. package/src/translations.ts +19 -16
  65. package/src/types.ts +3 -10
  66. package/src/versions.ts +30 -34
  67. package/lib/client/globalDataHooks.d.ts +0 -19
  68. package/lib/client/globalDataHooks.js +0 -76
  69. package/src/client/globalDataHooks.ts +0 -107
package/lib/versions.js CHANGED
@@ -6,22 +6,19 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.getDocsDirPaths = exports.readVersionsMetadata = exports.getVersionsFilePath = exports.getVersionedSidebarsDirPath = exports.getVersionedDocsDirPath = void 0;
9
+ exports.getDocsDirPaths = exports.readVersionsMetadata = exports.filterVersions = exports.getVersionBadge = exports.getVersionBanner = exports.getDefaultVersionBanner = exports.readVersionNames = exports.readVersionsFile = exports.getVersionsFilePath = exports.getVersionedSidebarsDirPath = exports.getVersionedDocsDirPath = void 0;
10
10
  const tslib_1 = require("tslib");
11
11
  const path_1 = (0, tslib_1.__importDefault)(require("path"));
12
12
  const fs_extra_1 = (0, tslib_1.__importDefault)(require("fs-extra"));
13
13
  const constants_1 = require("./constants");
14
14
  const utils_1 = require("@docusaurus/utils");
15
- const lodash_1 = require("lodash");
15
+ const lodash_1 = (0, tslib_1.__importDefault)(require("lodash"));
16
16
  const sidebars_1 = require("./sidebars");
17
17
  // retro-compatibility: no prefix for the default plugin id
18
18
  function addPluginIdPrefix(fileOrDir, pluginId) {
19
- if (pluginId === utils_1.DEFAULT_PLUGIN_ID) {
20
- return fileOrDir;
21
- }
22
- else {
23
- return `${pluginId}_${fileOrDir}`;
24
- }
19
+ return pluginId === utils_1.DEFAULT_PLUGIN_ID
20
+ ? fileOrDir
21
+ : `${pluginId}_${fileOrDir}`;
25
22
  }
26
23
  function getVersionedDocsDirPath(siteDir, pluginId) {
27
24
  return path_1.default.join(siteDir, addPluginIdPrefix(constants_1.VERSIONED_DOCS_DIR, pluginId));
@@ -57,10 +54,9 @@ async function readVersionsFile(siteDir, pluginId) {
57
54
  ensureValidVersionArray(content);
58
55
  return content;
59
56
  }
60
- else {
61
- return null;
62
- }
57
+ return null;
63
58
  }
59
+ exports.readVersionsFile = readVersionsFile;
64
60
  async function readVersionNames(siteDir, options) {
65
61
  const versionFileContent = await readVersionsFile(siteDir, options.id);
66
62
  if (!versionFileContent && options.disableVersioning) {
@@ -79,6 +75,7 @@ async function readVersionNames(siteDir, options) {
79
75
  }
80
76
  return versions;
81
77
  }
78
+ exports.readVersionNames = readVersionNames;
82
79
  function getDocsDirPathLocalized({ siteDir, locale, pluginId, versionName, }) {
83
80
  return (0, utils_1.getPluginI18nPath)({
84
81
  siteDir,
@@ -149,14 +146,13 @@ function getDefaultVersionBanner({ versionName, versionNames, lastVersionName, }
149
146
  return null;
150
147
  }
151
148
  // Upcoming versions: unreleased banner
152
- else if (versionNames.indexOf(versionName) < versionNames.indexOf(lastVersionName)) {
149
+ if (versionNames.indexOf(versionName) < versionNames.indexOf(lastVersionName)) {
153
150
  return 'unreleased';
154
151
  }
155
152
  // Older versions: display unmaintained banner
156
- else {
157
- return 'unmaintained';
158
- }
153
+ return 'unmaintained';
159
154
  }
155
+ exports.getDefaultVersionBanner = getDefaultVersionBanner;
160
156
  function getVersionBanner({ versionName, versionNames, lastVersionName, options, }) {
161
157
  var _a;
162
158
  const versionBannerOption = (_a = options.versions[versionName]) === null || _a === void 0 ? void 0 : _a.banner;
@@ -169,6 +165,7 @@ function getVersionBanner({ versionName, versionNames, lastVersionName, options,
169
165
  lastVersionName,
170
166
  });
171
167
  }
168
+ exports.getVersionBanner = getVersionBanner;
172
169
  function getVersionBadge({ versionName, versionNames, options, }) {
173
170
  var _a;
174
171
  const versionBadgeOption = (_a = options.versions[versionName]) === null || _a === void 0 ? void 0 : _a.badge;
@@ -178,6 +175,7 @@ function getVersionBadge({ versionName, versionNames, options, }) {
178
175
  const versionBadgeDefault = versionNames.length !== 1;
179
176
  return versionBadgeOption !== null && versionBadgeOption !== void 0 ? versionBadgeOption : versionBadgeDefault;
180
177
  }
178
+ exports.getVersionBadge = getVersionBadge;
181
179
  function getVersionClassName({ versionName, options, }) {
182
180
  var _a;
183
181
  const versionClassNameOption = (_a = options.versions[versionName]) === null || _a === void 0 ? void 0 : _a.className;
@@ -238,20 +236,21 @@ function createVersionMetadata({ versionName, versionNames, lastVersionName, con
238
236
  contentPathLocalized,
239
237
  };
240
238
  }
241
- function checkVersionMetadataPaths({ versionMetadata, context, }) {
239
+ async function checkVersionMetadataPaths({ versionMetadata, context, }) {
242
240
  const { versionName, contentPath, sidebarFilePath } = versionMetadata;
243
241
  const { siteDir } = context;
244
242
  const isCurrentVersion = versionName === constants_1.CURRENT_VERSION_NAME;
245
- if (!fs_extra_1.default.existsSync(contentPath)) {
243
+ if (!(await fs_extra_1.default.pathExists(contentPath))) {
246
244
  throw new Error(`The docs folder does not exist for version "${versionName}". A docs folder is expected to be found at ${path_1.default.relative(siteDir, contentPath)}.`);
247
245
  }
248
- // If the current version defines a path to a sidebar file that does not exist, we throw!
249
- // Note: for versioned sidebars, the file may not exist (as we prefer to not create it rather than to create an empty file)
246
+ // If the current version defines a path to a sidebar file that does not
247
+ // exist, we throw! Note: for versioned sidebars, the file may not exist (as
248
+ // we prefer to not create it rather than to create an empty file)
250
249
  // See https://github.com/facebook/docusaurus/issues/3366
251
250
  // See https://github.com/facebook/docusaurus/pull/4775
252
251
  if (isCurrentVersion &&
253
252
  typeof sidebarFilePath === 'string' &&
254
- !fs_extra_1.default.existsSync(sidebarFilePath)) {
253
+ !(await fs_extra_1.default.pathExists(sidebarFilePath))) {
255
254
  throw new Error(`The path to the sidebar file does not exist at "${path_1.default.relative(siteDir, sidebarFilePath)}".
256
255
  Please set the docs "sidebarPath" field in your config file to:
257
256
  - a sidebars path that exists
@@ -266,9 +265,7 @@ function getDefaultLastVersionName(versionNames) {
266
265
  if (versionNames.length === 1) {
267
266
  return versionNames[0];
268
267
  }
269
- else {
270
- return versionNames.filter((versionName) => versionName !== constants_1.CURRENT_VERSION_NAME)[0];
271
- }
268
+ return versionNames.filter((versionName) => versionName !== constants_1.CURRENT_VERSION_NAME)[0];
272
269
  }
273
270
  function checkVersionsOptions(availableVersionNames, options) {
274
271
  const availableVersionNamesMsg = `Available version names are: ${availableVersionNames.join(', ')}`;
@@ -276,7 +273,7 @@ function checkVersionsOptions(availableVersionNames, options) {
276
273
  !availableVersionNames.includes(options.lastVersion)) {
277
274
  throw new Error(`Docs option lastVersion: ${options.lastVersion} is invalid. ${availableVersionNamesMsg}`);
278
275
  }
279
- const unknownVersionConfigNames = (0, lodash_1.difference)(Object.keys(options.versions), availableVersionNames);
276
+ const unknownVersionConfigNames = lodash_1.default.difference(Object.keys(options.versions), availableVersionNames);
280
277
  if (unknownVersionConfigNames.length > 0) {
281
278
  throw new Error(`Invalid docs option "versions": unknown versions (${unknownVersionConfigNames.join(',')}) found. ${availableVersionNamesMsg}`);
282
279
  }
@@ -284,7 +281,7 @@ function checkVersionsOptions(availableVersionNames, options) {
284
281
  if (options.onlyIncludeVersions.length === 0) {
285
282
  throw new Error(`Invalid docs option "onlyIncludeVersions": an empty array is not allowed, at least one version is needed.`);
286
283
  }
287
- const unknownOnlyIncludeVersionNames = (0, lodash_1.difference)(options.onlyIncludeVersions, availableVersionNames);
284
+ const unknownOnlyIncludeVersionNames = lodash_1.default.difference(options.onlyIncludeVersions, availableVersionNames);
288
285
  if (unknownOnlyIncludeVersionNames.length > 0) {
289
286
  throw new Error(`Invalid docs option "onlyIncludeVersions": unknown versions (${unknownOnlyIncludeVersionNames.join(',')}) found. ${availableVersionNamesMsg}`);
290
287
  }
@@ -303,10 +300,9 @@ function filterVersions(versionNamesUnfiltered, options) {
303
300
  if (options.onlyIncludeVersions) {
304
301
  return versionNamesUnfiltered.filter((name) => (options.onlyIncludeVersions || []).includes(name));
305
302
  }
306
- else {
307
- return versionNamesUnfiltered;
308
- }
303
+ return versionNamesUnfiltered;
309
304
  }
305
+ exports.filterVersions = filterVersions;
310
306
  async function readVersionsMetadata({ context, options, }) {
311
307
  var _a;
312
308
  const versionNamesUnfiltered = await readVersionNames(context.siteDir, options);
@@ -320,7 +316,7 @@ async function readVersionsMetadata({ context, options, }) {
320
316
  context,
321
317
  options,
322
318
  }));
323
- versionsMetadata.forEach((versionMetadata) => checkVersionMetadataPaths({ versionMetadata, context }));
319
+ await Promise.all(versionsMetadata.map((versionMetadata) => checkVersionMetadataPaths({ versionMetadata, context })));
324
320
  return versionsMetadata;
325
321
  }
326
322
  exports.readVersionsMetadata = readVersionsMetadata;
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@docusaurus/plugin-content-docs",
3
- "version": "2.0.0-beta.15",
3
+ "version": "2.0.0-beta.16",
4
4
  "description": "Docs plugin for Docusaurus.",
5
5
  "main": "lib/index.js",
6
6
  "exports": {
7
7
  "./client": "./lib/client/index.js",
8
+ "./server": "./lib/server-export.js",
8
9
  ".": "./lib/index.js"
9
10
  },
10
11
  "types": "src/plugin-content-docs.d.ts",
@@ -22,30 +23,30 @@
22
23
  },
23
24
  "license": "MIT",
24
25
  "dependencies": {
25
- "@docusaurus/core": "2.0.0-beta.15",
26
- "@docusaurus/logger": "2.0.0-beta.15",
27
- "@docusaurus/mdx-loader": "2.0.0-beta.15",
28
- "@docusaurus/utils": "2.0.0-beta.15",
29
- "@docusaurus/utils-validation": "2.0.0-beta.15",
26
+ "@docusaurus/core": "2.0.0-beta.16",
27
+ "@docusaurus/logger": "2.0.0-beta.16",
28
+ "@docusaurus/mdx-loader": "2.0.0-beta.16",
29
+ "@docusaurus/utils": "2.0.0-beta.16",
30
+ "@docusaurus/utils-validation": "2.0.0-beta.16",
30
31
  "combine-promises": "^1.1.0",
31
- "fs-extra": "^10.0.0",
32
- "import-fresh": "^3.2.2",
33
- "js-yaml": "^4.0.0",
34
- "lodash": "^4.17.20",
32
+ "fs-extra": "^10.0.1",
33
+ "import-fresh": "^3.3.0",
34
+ "js-yaml": "^4.1.0",
35
+ "lodash": "^4.17.21",
35
36
  "remark-admonitions": "^1.2.1",
36
- "shelljs": "^0.8.4",
37
37
  "tslib": "^2.3.1",
38
38
  "utility-types": "^3.10.0",
39
- "webpack": "^5.61.0"
39
+ "webpack": "^5.69.1"
40
40
  },
41
41
  "devDependencies": {
42
- "@docusaurus/module-type-aliases": "2.0.0-beta.15",
43
- "@docusaurus/types": "2.0.0-beta.15",
44
- "@types/js-yaml": "^4.0.0",
45
- "@types/picomatch": "^2.2.1",
42
+ "@docusaurus/module-type-aliases": "2.0.0-beta.16",
43
+ "@docusaurus/types": "2.0.0-beta.16",
44
+ "@types/js-yaml": "^4.0.5",
45
+ "@types/picomatch": "^2.3.0",
46
46
  "commander": "^5.1.0",
47
47
  "escape-string-regexp": "^4.0.0",
48
- "picomatch": "^2.1.1",
48
+ "picomatch": "^2.3.1",
49
+ "shelljs": "^0.8.5",
49
50
  "utility-types": "^3.10.0"
50
51
  },
51
52
  "peerDependencies": {
@@ -55,5 +56,5 @@
55
56
  "engines": {
56
57
  "node": ">=14"
57
58
  },
58
- "gitHead": "6cfad16436c07d8d11e5c2e1486dc59afd483e33"
59
+ "gitHead": "eb43c4d4f95a4fb97dc9bb9dc615413e0dc2e1e7"
59
60
  }
package/src/cli.ts CHANGED
@@ -16,11 +16,11 @@ import type {
16
16
  PathOptions,
17
17
  SidebarOptions,
18
18
  } from '@docusaurus/plugin-content-docs';
19
- import {loadSidebarsFile, resolveSidebarPathOption} from './sidebars';
19
+ import {loadSidebarsFileUnsafe, resolveSidebarPathOption} from './sidebars';
20
20
  import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
21
21
  import logger from '@docusaurus/logger';
22
22
 
23
- function createVersionedSidebarFile({
23
+ async function createVersionedSidebarFile({
24
24
  siteDir,
25
25
  pluginId,
26
26
  sidebarPath,
@@ -32,10 +32,13 @@ function createVersionedSidebarFile({
32
32
  version: string;
33
33
  }) {
34
34
  // Load current sidebar and create a new versioned sidebars file (if needed).
35
- // Note: we don't need the sidebars file to be normalized: it's ok to let plugin option changes to impact older, versioned sidebars
36
- const sidebars = loadSidebarsFile(sidebarPath);
35
+ // Note: we don't need the sidebars file to be normalized: it's ok to let
36
+ // plugin option changes to impact older, versioned sidebars
37
+ // We don't validate here, assuming the user has already built the version
38
+ const sidebars = await loadSidebarsFileUnsafe(sidebarPath);
37
39
 
38
- // Do not create a useless versioned sidebars file if sidebars file is empty or sidebars are disabled/false)
40
+ // Do not create a useless versioned sidebars file if sidebars file is empty
41
+ // or sidebars are disabled/false)
39
42
  const shouldCreateVersionedSidebarFile = Object.keys(sidebars).length > 0;
40
43
 
41
44
  if (shouldCreateVersionedSidebarFile) {
@@ -44,8 +47,8 @@ function createVersionedSidebarFile({
44
47
  versionedSidebarsDir,
45
48
  `version-${version}-sidebars.json`,
46
49
  );
47
- fs.ensureDirSync(path.dirname(newSidebarFile));
48
- fs.writeFileSync(
50
+ await fs.ensureDir(path.dirname(newSidebarFile));
51
+ await fs.writeFile(
49
52
  newSidebarFile,
50
53
  `${JSON.stringify(sidebars, null, 2)}\n`,
51
54
  'utf8',
@@ -54,12 +57,12 @@ function createVersionedSidebarFile({
54
57
  }
55
58
 
56
59
  // Tests depend on non-default export for mocking.
57
- export function cliDocsVersionCommand(
60
+ export async function cliDocsVersionCommand(
58
61
  version: string | null | undefined,
59
62
  siteDir: string,
60
63
  pluginId: string,
61
64
  options: PathOptions & SidebarOptions,
62
- ): void {
65
+ ): Promise<void> {
63
66
  // It wouldn't be very user-friendly to show a [default] log prefix,
64
67
  // so we use [docs] instead of [default]
65
68
  const pluginIdLogPrefix =
@@ -101,8 +104,8 @@ export function cliDocsVersionCommand(
101
104
  // Load existing versions.
102
105
  let versions = [];
103
106
  const versionsJSONFile = getVersionsFilePath(siteDir, pluginId);
104
- if (fs.existsSync(versionsJSONFile)) {
105
- versions = JSON.parse(fs.readFileSync(versionsJSONFile, 'utf8'));
107
+ if (await fs.pathExists(versionsJSONFile)) {
108
+ versions = JSON.parse(await fs.readFile(versionsJSONFile, 'utf8'));
106
109
  }
107
110
 
108
111
  // Check if version already exists.
@@ -117,15 +120,18 @@ export function cliDocsVersionCommand(
117
120
  // Copy docs files.
118
121
  const docsDir = path.join(siteDir, docsPath);
119
122
 
120
- if (fs.existsSync(docsDir) && fs.readdirSync(docsDir).length > 0) {
123
+ if (
124
+ (await fs.pathExists(docsDir)) &&
125
+ (await fs.readdir(docsDir)).length > 0
126
+ ) {
121
127
  const versionedDir = getVersionedDocsDirPath(siteDir, pluginId);
122
128
  const newVersionDir = path.join(versionedDir, `version-${version}`);
123
- fs.copySync(docsDir, newVersionDir);
129
+ await fs.copy(docsDir, newVersionDir);
124
130
  } else {
125
131
  throw new Error(`${pluginIdLogPrefix}: there is no docs to version!`);
126
132
  }
127
133
 
128
- createVersionedSidebarFile({
134
+ await createVersionedSidebarFile({
129
135
  siteDir,
130
136
  pluginId,
131
137
  version,
@@ -134,8 +140,11 @@ export function cliDocsVersionCommand(
134
140
 
135
141
  // Update versions.json file.
136
142
  versions.unshift(version);
137
- fs.ensureDirSync(path.dirname(versionsJSONFile));
138
- fs.writeFileSync(versionsJSONFile, `${JSON.stringify(versions, null, 2)}\n`);
143
+ await fs.ensureDir(path.dirname(versionsJSONFile));
144
+ await fs.writeFile(
145
+ versionsJSONFile,
146
+ `${JSON.stringify(versions, null, 2)}\n`,
147
+ );
139
148
 
140
149
  logger.success`name=${pluginIdLogPrefix}: version name=${version} created!`;
141
150
  }
@@ -28,7 +28,7 @@ export function getActivePlugin(
28
28
  options: GetActivePluginOptions = {},
29
29
  ): ActivePlugin | undefined {
30
30
  const activeEntry = Object.entries(allPluginDatas)
31
- // A quick route sorting: '/android/foo' should match '/android' instead of '/'
31
+ // Route sorting: '/android/foo' should match '/android' instead of '/'
32
32
  .sort((a, b) => b[1].path.localeCompare(a[1].path))
33
33
  .find(
34
34
  ([, pluginData]) =>
@@ -67,7 +67,7 @@ export const getActiveVersion = (
67
67
  ): GlobalVersion | undefined => {
68
68
  const lastVersion = getLatestVersion(data);
69
69
  // Last version is a route like /docs/*,
70
- // we need to try to match it last or it would match /docs/version-1.0/* as well
70
+ // we need to match it last or it would match /docs/version-1.0/* as well
71
71
  const orderedVersionsMetadata = [
72
72
  ...data.versions.filter((version) => version !== lastVersion),
73
73
  lastVersion,
@@ -5,4 +5,100 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- export * from './globalDataHooks';
8
+ import {useLocation} from '@docusaurus/router';
9
+ import useGlobalData, {usePluginData} from '@docusaurus/useGlobalData';
10
+
11
+ import {
12
+ getActivePlugin,
13
+ getLatestVersion,
14
+ getActiveVersion,
15
+ getActiveDocContext,
16
+ getDocVersionSuggestions,
17
+ } from './docsClientUtils';
18
+ import type {
19
+ GlobalPluginData,
20
+ GlobalVersion,
21
+ ActivePlugin,
22
+ ActiveDocContext,
23
+ DocVersionSuggestions,
24
+ GetActivePluginOptions,
25
+ } from '@docusaurus/plugin-content-docs/client';
26
+
27
+ // Important to use a constant object to avoid React useEffect executions etc.
28
+ // see https://github.com/facebook/docusaurus/issues/5089
29
+ const StableEmptyObject = {};
30
+
31
+ // Not using useAllPluginInstancesData() because in blog-only mode, docs hooks
32
+ // are still used by the theme. We need a fail-safe fallback when the docs
33
+ // plugin is not in use
34
+ export const useAllDocsData = (): Record<string, GlobalPluginData> =>
35
+ useGlobalData()['docusaurus-plugin-content-docs'] ?? StableEmptyObject;
36
+
37
+ export const useDocsData = (pluginId: string | undefined): GlobalPluginData =>
38
+ usePluginData('docusaurus-plugin-content-docs', pluginId) as GlobalPluginData;
39
+
40
+ // TODO this feature should be provided by docusaurus core
41
+ export const useActivePlugin = (
42
+ options: GetActivePluginOptions = {},
43
+ ): ActivePlugin | undefined => {
44
+ const data = useAllDocsData();
45
+ const {pathname} = useLocation();
46
+ return getActivePlugin(data, pathname, options);
47
+ };
48
+
49
+ export const useActivePluginAndVersion = (
50
+ options: GetActivePluginOptions = {},
51
+ ):
52
+ | undefined
53
+ | {activePlugin: ActivePlugin; activeVersion: GlobalVersion | undefined} => {
54
+ const activePlugin = useActivePlugin(options);
55
+ const {pathname} = useLocation();
56
+ if (activePlugin) {
57
+ const activeVersion = getActiveVersion(activePlugin.pluginData, pathname);
58
+ return {
59
+ activePlugin,
60
+ activeVersion,
61
+ };
62
+ }
63
+ return undefined;
64
+ };
65
+
66
+ // versions are returned ordered (most recent first)
67
+ export const useVersions = (pluginId: string | undefined): GlobalVersion[] => {
68
+ const data = useDocsData(pluginId);
69
+ return data.versions;
70
+ };
71
+
72
+ export const useLatestVersion = (
73
+ pluginId: string | undefined,
74
+ ): GlobalVersion => {
75
+ const data = useDocsData(pluginId);
76
+ return getLatestVersion(data);
77
+ };
78
+
79
+ // Note: return undefined on doc-unrelated pages,
80
+ // because there's no version currently considered as active
81
+ export const useActiveVersion = (
82
+ pluginId: string | undefined,
83
+ ): GlobalVersion | undefined => {
84
+ const data = useDocsData(pluginId);
85
+ const {pathname} = useLocation();
86
+ return getActiveVersion(data, pathname);
87
+ };
88
+
89
+ export const useActiveDocContext = (
90
+ pluginId: string | undefined,
91
+ ): ActiveDocContext => {
92
+ const data = useDocsData(pluginId);
93
+ const {pathname} = useLocation();
94
+ return getActiveDocContext(data, pathname);
95
+ };
96
+
97
+ // Useful to say "hey, you are not on the latest docs version, please switch"
98
+ export const useDocVersionSuggestions = (
99
+ pluginId: string | undefined,
100
+ ): DocVersionSuggestions => {
101
+ const data = useDocsData(pluginId);
102
+ const {pathname} = useLocation();
103
+ return getDocVersionSuggestions(data, pathname);
104
+ };
@@ -30,6 +30,7 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
30
30
  sidebar_label: Joi.string(),
31
31
  sidebar_position: Joi.number(),
32
32
  sidebar_class_name: Joi.string(),
33
+ sidebar_custom_props: Joi.object().unknown(),
33
34
  displayed_sidebar: Joi.string().allow(null),
34
35
  tags: FrontMatterTagsSchema,
35
36
  pagination_label: Joi.string(),
package/src/docs.ts CHANGED
@@ -8,7 +8,6 @@
8
8
  import path from 'path';
9
9
  import fs from 'fs-extra';
10
10
  import logger from '@docusaurus/logger';
11
- import {keyBy} from 'lodash';
12
11
  import {
13
12
  aliasedSitePath,
14
13
  getEditUrl,
@@ -139,7 +138,8 @@ function doProcessDocMetadata({
139
138
  const {
140
139
  custom_edit_url: customEditURL,
141
140
 
142
- // Strip number prefixes by default (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc) by default,
141
+ // Strip number prefixes by default
142
+ // (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
143
143
  // but allow to disable this behavior with front matter
144
144
  parse_number_prefixes: parseNumberPrefixes = true,
145
145
  } = frontMatter;
@@ -164,7 +164,8 @@ function doProcessDocMetadata({
164
164
  throw new Error(`Document id "${baseID}" cannot include slash.`);
165
165
  }
166
166
 
167
- // For autogenerated sidebars, sidebar position can come from filename number prefix or front matter
167
+ // For autogenerated sidebars, sidebar position can come from filename number
168
+ // prefix or front matter
168
169
  const sidebarPosition: number | undefined =
169
170
  frontMatter.sidebar_position ?? numberPrefix;
170
171
 
@@ -205,8 +206,9 @@ function doProcessDocMetadata({
205
206
  numberPrefixParser: options.numberPrefixParser,
206
207
  });
207
208
 
208
- // Note: the title is used by default for page title, sidebar label, pagination buttons...
209
- // frontMatter.title should be used in priority over contentTitle (because it can contain markdown/JSX syntax)
209
+ // Note: the title is used by default for page title, sidebar label,
210
+ // pagination buttons... frontMatter.title should be used in priority over
211
+ // contentTitle (because it can contain markdown/JSX syntax)
210
212
  const title: string = frontMatter.title ?? contentTitle ?? baseID;
211
213
 
212
214
  const description: string = frontMatter.description ?? excerpt ?? '';
@@ -233,9 +235,8 @@ function doProcessDocMetadata({
233
235
  ? versionMetadata.versionEditUrlLocalized
234
236
  : versionMetadata.versionEditUrl;
235
237
  return getEditUrl(relativeFilePath, baseVersionEditUrl);
236
- } else {
237
- return undefined;
238
238
  }
239
+ return undefined;
239
240
  }
240
241
 
241
242
  // Assign all of object properties during instantiation (if possible) for
@@ -274,9 +275,9 @@ export function processDocMetadata(args: {
274
275
  }): DocMetadataBase {
275
276
  try {
276
277
  return doProcessDocMetadata(args);
277
- } catch (e) {
278
+ } catch (err) {
278
279
  logger.error`Can't process doc metadata for doc at path path=${args.docFile.filePath} in version name=${args.versionMetadata.versionName}`;
279
- throw e;
280
+ throw err;
280
281
  }
281
282
  }
282
283
 
@@ -361,9 +362,8 @@ export function getMainDocId({
361
362
  doc.id === firstDocIdOfFirstSidebar ||
362
363
  doc.unversionedId === firstDocIdOfFirstSidebar,
363
364
  )!;
364
- } else {
365
- return docs[0];
366
365
  }
366
+ return docs[0];
367
367
  }
368
368
 
369
369
  return getMainDoc().unversionedId;
@@ -407,7 +407,8 @@ export function toCategoryIndexMatcherParam({
407
407
  }
408
408
 
409
409
  /**
410
- * guides/sidebar/autogenerated.md -> 'autogenerated', '.md', ['sidebar', 'guides']
410
+ * `guides/sidebar/autogenerated.md` ->
411
+ * `'autogenerated', '.md', ['sidebar', 'guides']`
411
412
  */
412
413
  export function splitPath(str: string): {
413
414
  /**
@@ -428,20 +429,24 @@ export function splitPath(str: string): {
428
429
  }
429
430
 
430
431
  // Return both doc ids
431
- // TODO legacy retro-compatibility due to old versioned sidebars using versioned doc ids
432
- // ("id" should be removed & "versionedId" should be renamed to "id")
432
+ // TODO legacy retro-compatibility due to old versioned sidebars using
433
+ // versioned doc ids ("id" should be removed & "versionedId" should be renamed
434
+ // to "id")
433
435
  export function getDocIds(doc: DocMetadataBase): [string, string] {
434
436
  return [doc.unversionedId, doc.id];
435
437
  }
436
438
 
437
439
  // docs are indexed by both versioned and unversioned ids at the same time
438
- // TODO legacy retro-compatibility due to old versioned sidebars using versioned doc ids
439
- // ("id" should be removed & "versionedId" should be renamed to "id")
440
+ // TODO legacy retro-compatibility due to old versioned sidebars using
441
+ // versioned doc ids ("id" should be removed & "versionedId" should be renamed
442
+ // to "id")
440
443
  export function createDocsByIdIndex<
441
444
  Doc extends {id: string; unversionedId: string},
442
445
  >(docs: Doc[]): Record<string, Doc> {
443
- return {
444
- ...keyBy(docs, (doc) => doc.unversionedId),
445
- ...keyBy(docs, (doc) => doc.id),
446
- };
446
+ return Object.fromEntries(
447
+ docs.flatMap((doc) => [
448
+ [doc.unversionedId, doc],
449
+ [doc.id, doc],
450
+ ]),
451
+ );
447
452
  }
package/src/globalData.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import {mapValues} from 'lodash';
8
+ import _ from 'lodash';
9
9
  import {normalizeUrl} from '@docusaurus/utils';
10
10
  import type {Sidebars} from './sidebars/types';
11
11
  import {createSidebarsUtils} from './sidebars/utils';
@@ -43,7 +43,7 @@ export function toGlobalSidebars(
43
43
  version: LoadedVersion,
44
44
  ): Record<string, GlobalSidebar> {
45
45
  const {getFirstLink} = createSidebarsUtils(sidebars);
46
- return mapValues(sidebars, (sidebar, sidebarId) => {
46
+ return _.mapValues(sidebars, (sidebar, sidebarId) => {
47
47
  const firstLink = getFirstLink(sidebarId);
48
48
  if (!firstLink) {
49
49
  return {};
package/src/index.ts CHANGED
@@ -38,11 +38,11 @@ import type {
38
38
  DocFile,
39
39
  DocsMarkdownOption,
40
40
  VersionTag,
41
+ DocFrontMatter,
41
42
  } from './types';
42
43
  import type {RuleSetRule} from 'webpack';
43
44
  import {cliDocsVersionCommand} from './cli';
44
45
  import {VERSIONS_JSON_FILE} from './constants';
45
- import {keyBy, mapValues} from 'lodash';
46
46
  import {toGlobalDataVersion} from './globalData';
47
47
  import {toTagDocListProp} from './props';
48
48
  import {
@@ -196,9 +196,9 @@ export default async function pluginContentDocs(
196
196
  async function loadVersion(versionMetadata: VersionMetadata) {
197
197
  try {
198
198
  return await doLoadVersion(versionMetadata);
199
- } catch (e) {
199
+ } catch (err) {
200
200
  logger.error`Loading of version failed for version name=${versionMetadata.versionName}`;
201
- throw e;
201
+ throw err;
202
202
  }
203
203
  }
204
204
 
@@ -217,6 +217,7 @@ export default async function pluginContentDocs(
217
217
  docLayoutComponent,
218
218
  docItemComponent,
219
219
  docCategoryGeneratedIndexComponent,
220
+ breadcrumbs,
220
221
  } = options;
221
222
  const {addRoute, createData, setGlobalData} = actions;
222
223
 
@@ -295,6 +296,7 @@ export default async function pluginContentDocs(
295
296
  setGlobalData<GlobalPluginData>({
296
297
  path: normalizeUrl([baseUrl, options.routeBasePath]),
297
298
  versions: loadedVersions.map(toGlobalDataVersion),
299
+ breadcrumbs,
298
300
  });
299
301
  },
300
302
 
@@ -309,9 +311,8 @@ export default async function pluginContentDocs(
309
311
 
310
312
  function getSourceToPermalink(): SourceToPermalink {
311
313
  const allDocs = content.loadedVersions.flatMap((v) => v.docs);
312
- return mapValues(
313
- keyBy(allDocs, (d) => d.source),
314
- (d) => d.permalink,
314
+ return Object.fromEntries(
315
+ allDocs.map(({source, permalink}) => [source, permalink]),
315
316
  );
316
317
  }
317
318
 
@@ -333,7 +334,7 @@ export default async function pluginContentDocs(
333
334
  function createMDXLoaderRule(): RuleSetRule {
334
335
  const contentDirs = versionsMetadata.flatMap(getDocsDirPaths);
335
336
  return {
336
- test: /(\.mdx?)$/,
337
+ test: /\.mdx?$/i,
337
338
  include: contentDirs
338
339
  // Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
339
340
  .map(addTrailingPathSeparator),
@@ -360,6 +361,15 @@ export default async function pluginContentDocs(
360
361
  const aliasedPath = aliasedSitePath(mdxPath, siteDir);
361
362
  return path.join(dataDir, `${docuHash(aliasedPath)}.json`);
362
363
  },
364
+ // Assets allow to convert some relative images paths to
365
+ // require(...) calls
366
+ createAssets: ({
367
+ frontMatter,
368
+ }: {
369
+ frontMatter: DocFrontMatter;
370
+ }) => ({
371
+ image: frontMatter.image,
372
+ }),
363
373
  },
364
374
  },
365
375
  {