@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/cli.d.ts CHANGED
@@ -5,4 +5,4 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import type { PathOptions, SidebarOptions } from '@docusaurus/plugin-content-docs';
8
- export declare function cliDocsVersionCommand(version: string | null | undefined, siteDir: string, pluginId: string, options: PathOptions & SidebarOptions): void;
8
+ export declare function cliDocsVersionCommand(version: string | null | undefined, siteDir: string, pluginId: string, options: PathOptions & SidebarOptions): Promise<void>;
package/lib/cli.js CHANGED
@@ -14,21 +14,24 @@ const path_1 = (0, tslib_1.__importDefault)(require("path"));
14
14
  const sidebars_1 = require("./sidebars");
15
15
  const utils_1 = require("@docusaurus/utils");
16
16
  const logger_1 = (0, tslib_1.__importDefault)(require("@docusaurus/logger"));
17
- function createVersionedSidebarFile({ siteDir, pluginId, sidebarPath, version, }) {
17
+ async function createVersionedSidebarFile({ siteDir, pluginId, sidebarPath, version, }) {
18
18
  // Load current sidebar and create a new versioned sidebars file (if needed).
19
- // Note: we don't need the sidebars file to be normalized: it's ok to let plugin option changes to impact older, versioned sidebars
20
- const sidebars = (0, sidebars_1.loadSidebarsFile)(sidebarPath);
21
- // Do not create a useless versioned sidebars file if sidebars file is empty or sidebars are disabled/false)
19
+ // Note: we don't need the sidebars file to be normalized: it's ok to let
20
+ // plugin option changes to impact older, versioned sidebars
21
+ // We don't validate here, assuming the user has already built the version
22
+ const sidebars = await (0, sidebars_1.loadSidebarsFileUnsafe)(sidebarPath);
23
+ // Do not create a useless versioned sidebars file if sidebars file is empty
24
+ // or sidebars are disabled/false)
22
25
  const shouldCreateVersionedSidebarFile = Object.keys(sidebars).length > 0;
23
26
  if (shouldCreateVersionedSidebarFile) {
24
27
  const versionedSidebarsDir = (0, versions_1.getVersionedSidebarsDirPath)(siteDir, pluginId);
25
28
  const newSidebarFile = path_1.default.join(versionedSidebarsDir, `version-${version}-sidebars.json`);
26
- fs_extra_1.default.ensureDirSync(path_1.default.dirname(newSidebarFile));
27
- fs_extra_1.default.writeFileSync(newSidebarFile, `${JSON.stringify(sidebars, null, 2)}\n`, 'utf8');
29
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(newSidebarFile));
30
+ await fs_extra_1.default.writeFile(newSidebarFile, `${JSON.stringify(sidebars, null, 2)}\n`, 'utf8');
28
31
  }
29
32
  }
30
33
  // Tests depend on non-default export for mocking.
31
- function cliDocsVersionCommand(version, siteDir, pluginId, options) {
34
+ async function cliDocsVersionCommand(version, siteDir, pluginId, options) {
32
35
  // It wouldn't be very user-friendly to show a [default] log prefix,
33
36
  // so we use [docs] instead of [default]
34
37
  const pluginIdLogPrefix = pluginId === utils_1.DEFAULT_PLUGIN_ID ? '[docs]' : `[${pluginId}]`;
@@ -53,8 +56,8 @@ function cliDocsVersionCommand(version, siteDir, pluginId, options) {
53
56
  // Load existing versions.
54
57
  let versions = [];
55
58
  const versionsJSONFile = (0, versions_1.getVersionsFilePath)(siteDir, pluginId);
56
- if (fs_extra_1.default.existsSync(versionsJSONFile)) {
57
- versions = JSON.parse(fs_extra_1.default.readFileSync(versionsJSONFile, 'utf8'));
59
+ if (await fs_extra_1.default.pathExists(versionsJSONFile)) {
60
+ versions = JSON.parse(await fs_extra_1.default.readFile(versionsJSONFile, 'utf8'));
58
61
  }
59
62
  // Check if version already exists.
60
63
  if (versions.includes(version)) {
@@ -63,15 +66,16 @@ function cliDocsVersionCommand(version, siteDir, pluginId, options) {
63
66
  const { path: docsPath, sidebarPath } = options;
64
67
  // Copy docs files.
65
68
  const docsDir = path_1.default.join(siteDir, docsPath);
66
- if (fs_extra_1.default.existsSync(docsDir) && fs_extra_1.default.readdirSync(docsDir).length > 0) {
69
+ if ((await fs_extra_1.default.pathExists(docsDir)) &&
70
+ (await fs_extra_1.default.readdir(docsDir)).length > 0) {
67
71
  const versionedDir = (0, versions_1.getVersionedDocsDirPath)(siteDir, pluginId);
68
72
  const newVersionDir = path_1.default.join(versionedDir, `version-${version}`);
69
- fs_extra_1.default.copySync(docsDir, newVersionDir);
73
+ await fs_extra_1.default.copy(docsDir, newVersionDir);
70
74
  }
71
75
  else {
72
76
  throw new Error(`${pluginIdLogPrefix}: there is no docs to version!`);
73
77
  }
74
- createVersionedSidebarFile({
78
+ await createVersionedSidebarFile({
75
79
  siteDir,
76
80
  pluginId,
77
81
  version,
@@ -79,8 +83,8 @@ function cliDocsVersionCommand(version, siteDir, pluginId, options) {
79
83
  });
80
84
  // Update versions.json file.
81
85
  versions.unshift(version);
82
- fs_extra_1.default.ensureDirSync(path_1.default.dirname(versionsJSONFile));
83
- fs_extra_1.default.writeFileSync(versionsJSONFile, `${JSON.stringify(versions, null, 2)}\n`);
86
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(versionsJSONFile));
87
+ await fs_extra_1.default.writeFile(versionsJSONFile, `${JSON.stringify(versions, null, 2)}\n`);
84
88
  logger_1.default.success `name=${pluginIdLogPrefix}: version name=${version} created!`;
85
89
  }
86
90
  exports.cliDocsVersionCommand = cliDocsVersionCommand;
@@ -14,7 +14,7 @@ const router_1 = require("@docusaurus/router");
14
14
  // it is useful to support multiple docs plugin instances
15
15
  function getActivePlugin(allPluginDatas, pathname, options = {}) {
16
16
  const activeEntry = Object.entries(allPluginDatas)
17
- // A quick route sorting: '/android/foo' should match '/android' instead of '/'
17
+ // Route sorting: '/android/foo' should match '/android' instead of '/'
18
18
  .sort((a, b) => b[1].path.localeCompare(a[1].path))
19
19
  .find(([, pluginData]) => !!(0, router_1.matchPath)(pathname, {
20
20
  path: pluginData.path,
@@ -39,7 +39,7 @@ exports.getLatestVersion = getLatestVersion;
39
39
  const getActiveVersion = (data, pathname) => {
40
40
  const lastVersion = (0, exports.getLatestVersion)(data);
41
41
  // Last version is a route like /docs/*,
42
- // we need to try to match it last or it would match /docs/version-1.0/* as well
42
+ // we need to match it last or it would match /docs/version-1.0/* as well
43
43
  const orderedVersionsMetadata = [
44
44
  ...data.versions.filter((version) => version !== lastVersion),
45
45
  lastVersion,
@@ -4,4 +4,16 @@
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 './globalDataHooks';
7
+ import type { GlobalPluginData, GlobalVersion, ActivePlugin, ActiveDocContext, DocVersionSuggestions, GetActivePluginOptions } from '@docusaurus/plugin-content-docs/client';
8
+ export declare const useAllDocsData: () => Record<string, GlobalPluginData>;
9
+ export declare const useDocsData: (pluginId: string | undefined) => GlobalPluginData;
10
+ export declare const useActivePlugin: (options?: GetActivePluginOptions) => ActivePlugin | undefined;
11
+ export declare const useActivePluginAndVersion: (options?: GetActivePluginOptions) => {
12
+ activePlugin: ActivePlugin;
13
+ activeVersion: GlobalVersion | undefined;
14
+ } | undefined;
15
+ export declare const useVersions: (pluginId: string | undefined) => GlobalVersion[];
16
+ export declare const useLatestVersion: (pluginId: string | undefined) => GlobalVersion;
17
+ export declare const useActiveVersion: (pluginId: string | undefined) => GlobalVersion | undefined;
18
+ export declare const useActiveDocContext: (pluginId: string | undefined) => ActiveDocContext;
19
+ export declare const useDocVersionSuggestions: (pluginId: string | undefined) => DocVersionSuggestions;
@@ -6,5 +6,70 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.useDocVersionSuggestions = exports.useActiveDocContext = exports.useActiveVersion = exports.useLatestVersion = exports.useVersions = exports.useActivePluginAndVersion = exports.useActivePlugin = exports.useDocsData = exports.useAllDocsData = void 0;
9
10
  const tslib_1 = require("tslib");
10
- (0, tslib_1.__exportStar)(require("./globalDataHooks"), exports);
11
+ const router_1 = require("@docusaurus/router");
12
+ const useGlobalData_1 = (0, tslib_1.__importStar)(require("@docusaurus/useGlobalData"));
13
+ const docsClientUtils_1 = require("./docsClientUtils");
14
+ // Important to use a constant object to avoid React useEffect executions etc.
15
+ // see https://github.com/facebook/docusaurus/issues/5089
16
+ const StableEmptyObject = {};
17
+ // Not using useAllPluginInstancesData() because in blog-only mode, docs hooks
18
+ // are still used by the theme. We need a fail-safe fallback when the docs
19
+ // plugin is not in use
20
+ const useAllDocsData = () => { var _a; return (_a = (0, useGlobalData_1.default)()['docusaurus-plugin-content-docs']) !== null && _a !== void 0 ? _a : StableEmptyObject; };
21
+ exports.useAllDocsData = useAllDocsData;
22
+ const useDocsData = (pluginId) => (0, useGlobalData_1.usePluginData)('docusaurus-plugin-content-docs', pluginId);
23
+ exports.useDocsData = useDocsData;
24
+ // TODO this feature should be provided by docusaurus core
25
+ const useActivePlugin = (options = {}) => {
26
+ const data = (0, exports.useAllDocsData)();
27
+ const { pathname } = (0, router_1.useLocation)();
28
+ return (0, docsClientUtils_1.getActivePlugin)(data, pathname, options);
29
+ };
30
+ exports.useActivePlugin = useActivePlugin;
31
+ const useActivePluginAndVersion = (options = {}) => {
32
+ const activePlugin = (0, exports.useActivePlugin)(options);
33
+ const { pathname } = (0, router_1.useLocation)();
34
+ if (activePlugin) {
35
+ const activeVersion = (0, docsClientUtils_1.getActiveVersion)(activePlugin.pluginData, pathname);
36
+ return {
37
+ activePlugin,
38
+ activeVersion,
39
+ };
40
+ }
41
+ return undefined;
42
+ };
43
+ exports.useActivePluginAndVersion = useActivePluginAndVersion;
44
+ // versions are returned ordered (most recent first)
45
+ const useVersions = (pluginId) => {
46
+ const data = (0, exports.useDocsData)(pluginId);
47
+ return data.versions;
48
+ };
49
+ exports.useVersions = useVersions;
50
+ const useLatestVersion = (pluginId) => {
51
+ const data = (0, exports.useDocsData)(pluginId);
52
+ return (0, docsClientUtils_1.getLatestVersion)(data);
53
+ };
54
+ exports.useLatestVersion = useLatestVersion;
55
+ // Note: return undefined on doc-unrelated pages,
56
+ // because there's no version currently considered as active
57
+ const useActiveVersion = (pluginId) => {
58
+ const data = (0, exports.useDocsData)(pluginId);
59
+ const { pathname } = (0, router_1.useLocation)();
60
+ return (0, docsClientUtils_1.getActiveVersion)(data, pathname);
61
+ };
62
+ exports.useActiveVersion = useActiveVersion;
63
+ const useActiveDocContext = (pluginId) => {
64
+ const data = (0, exports.useDocsData)(pluginId);
65
+ const { pathname } = (0, router_1.useLocation)();
66
+ return (0, docsClientUtils_1.getActiveDocContext)(data, pathname);
67
+ };
68
+ exports.useActiveDocContext = useActiveDocContext;
69
+ // Useful to say "hey, you are not on the latest docs version, please switch"
70
+ const useDocVersionSuggestions = (pluginId) => {
71
+ const data = (0, exports.useDocsData)(pluginId);
72
+ const { pathname } = (0, router_1.useLocation)();
73
+ return (0, docsClientUtils_1.getDocVersionSuggestions)(data, pathname);
74
+ };
75
+ exports.useDocVersionSuggestions = useDocVersionSuggestions;
@@ -24,6 +24,7 @@ const DocFrontMatterSchema = utils_validation_1.JoiFrontMatter.object({
24
24
  sidebar_label: utils_validation_1.JoiFrontMatter.string(),
25
25
  sidebar_position: utils_validation_1.JoiFrontMatter.number(),
26
26
  sidebar_class_name: utils_validation_1.JoiFrontMatter.string(),
27
+ sidebar_custom_props: utils_validation_1.JoiFrontMatter.object().unknown(),
27
28
  displayed_sidebar: utils_validation_1.JoiFrontMatter.string().allow(null),
28
29
  tags: utils_validation_1.FrontMatterTagsSchema,
29
30
  pagination_label: utils_validation_1.JoiFrontMatter.string(),
package/lib/docs.d.ts CHANGED
@@ -32,7 +32,8 @@ export declare function getMainDocId({ docs, sidebarsUtils, }: {
32
32
  export declare const isCategoryIndex: CategoryIndexMatcher;
33
33
  export declare function toCategoryIndexMatcherParam({ source, sourceDirName, }: Pick<DocMetadataBase, 'source' | 'sourceDirName'>): CategoryIndexMatcherParam;
34
34
  /**
35
- * guides/sidebar/autogenerated.md -> 'autogenerated', '.md', ['sidebar', 'guides']
35
+ * `guides/sidebar/autogenerated.md` ->
36
+ * `'autogenerated', '.md', ['sidebar', 'guides']`
36
37
  */
37
38
  export declare function splitPath(str: string): {
38
39
  /**
package/lib/docs.js CHANGED
@@ -11,7 +11,6 @@ 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 logger_1 = (0, tslib_1.__importDefault)(require("@docusaurus/logger"));
14
- const lodash_1 = require("lodash");
15
14
  const utils_1 = require("@docusaurus/utils");
16
15
  const lastUpdate_1 = require("./lastUpdate");
17
16
  const slug_1 = (0, tslib_1.__importDefault)(require("./slug"));
@@ -65,7 +64,8 @@ function doProcessDocMetadata({ docFile, versionMetadata, context, options, }) {
65
64
  const { frontMatter: unsafeFrontMatter, contentTitle, excerpt, } = (0, utils_1.parseMarkdownString)(content);
66
65
  const frontMatter = (0, docFrontMatter_1.validateDocFrontMatter)(unsafeFrontMatter);
67
66
  const { custom_edit_url: customEditURL,
68
- // Strip number prefixes by default (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc) by default,
67
+ // Strip number prefixes by default
68
+ // (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
69
69
  // but allow to disable this behavior with front matter
70
70
  parse_number_prefixes: parseNumberPrefixes = true, } = frontMatter;
71
71
  // ex: api/plugins/myDoc -> myDoc
@@ -81,7 +81,8 @@ function doProcessDocMetadata({ docFile, versionMetadata, context, options, }) {
81
81
  if (baseID.includes('/')) {
82
82
  throw new Error(`Document id "${baseID}" cannot include slash.`);
83
83
  }
84
- // For autogenerated sidebars, sidebar position can come from filename number prefix or front matter
84
+ // For autogenerated sidebars, sidebar position can come from filename number
85
+ // prefix or front matter
85
86
  const sidebarPosition = (_b = frontMatter.sidebar_position) !== null && _b !== void 0 ? _b : numberPrefix;
86
87
  // TODO legacy retrocompatibility
87
88
  // The same doc in 2 distinct version could keep the same id,
@@ -114,8 +115,9 @@ function doProcessDocMetadata({ docFile, versionMetadata, context, options, }) {
114
115
  stripDirNumberPrefixes: parseNumberPrefixes,
115
116
  numberPrefixParser: options.numberPrefixParser,
116
117
  });
117
- // Note: the title is used by default for page title, sidebar label, pagination buttons...
118
- // frontMatter.title should be used in priority over contentTitle (because it can contain markdown/JSX syntax)
118
+ // Note: the title is used by default for page title, sidebar label,
119
+ // pagination buttons... frontMatter.title should be used in priority over
120
+ // contentTitle (because it can contain markdown/JSX syntax)
119
121
  const title = (_d = (_c = frontMatter.title) !== null && _c !== void 0 ? _c : contentTitle) !== null && _d !== void 0 ? _d : baseID;
120
122
  const description = (_f = (_e = frontMatter.description) !== null && _e !== void 0 ? _e : excerpt) !== null && _f !== void 0 ? _f : '';
121
123
  const permalink = (0, utils_1.normalizeUrl)([versionMetadata.versionPath, docSlug]);
@@ -137,9 +139,7 @@ function doProcessDocMetadata({ docFile, versionMetadata, context, options, }) {
137
139
  : versionMetadata.versionEditUrl;
138
140
  return (0, utils_1.getEditUrl)(relativeFilePath, baseVersionEditUrl);
139
141
  }
140
- else {
141
- return undefined;
142
- }
142
+ return undefined;
143
143
  }
144
144
  // Assign all of object properties during instantiation (if possible) for
145
145
  // NodeJS optimization.
@@ -170,9 +170,9 @@ function processDocMetadata(args) {
170
170
  try {
171
171
  return doProcessDocMetadata(args);
172
172
  }
173
- catch (e) {
173
+ catch (err) {
174
174
  logger_1.default.error `Can't process doc metadata for doc at path path=${args.docFile.filePath} in version name=${args.versionMetadata.versionName}`;
175
- throw e;
175
+ throw err;
176
176
  }
177
177
  }
178
178
  exports.processDocMetadata = processDocMetadata;
@@ -225,9 +225,7 @@ function getMainDocId({ docs, sidebarsUtils, }) {
225
225
  return docs.find((doc) => doc.id === firstDocIdOfFirstSidebar ||
226
226
  doc.unversionedId === firstDocIdOfFirstSidebar);
227
227
  }
228
- else {
229
- return docs[0];
230
- }
228
+ return docs[0];
231
229
  }
232
230
  return getMainDoc().unversionedId;
233
231
  }
@@ -262,7 +260,8 @@ function toCategoryIndexMatcherParam({ source, sourceDirName, }) {
262
260
  }
263
261
  exports.toCategoryIndexMatcherParam = toCategoryIndexMatcherParam;
264
262
  /**
265
- * guides/sidebar/autogenerated.md -> 'autogenerated', '.md', ['sidebar', 'guides']
263
+ * `guides/sidebar/autogenerated.md` ->
264
+ * `'autogenerated', '.md', ['sidebar', 'guides']`
266
265
  */
267
266
  function splitPath(str) {
268
267
  return {
@@ -273,19 +272,21 @@ function splitPath(str) {
273
272
  }
274
273
  exports.splitPath = splitPath;
275
274
  // Return both doc ids
276
- // TODO legacy retro-compatibility due to old versioned sidebars using versioned doc ids
277
- // ("id" should be removed & "versionedId" should be renamed to "id")
275
+ // TODO legacy retro-compatibility due to old versioned sidebars using
276
+ // versioned doc ids ("id" should be removed & "versionedId" should be renamed
277
+ // to "id")
278
278
  function getDocIds(doc) {
279
279
  return [doc.unversionedId, doc.id];
280
280
  }
281
281
  exports.getDocIds = getDocIds;
282
282
  // docs are indexed by both versioned and unversioned ids at the same time
283
- // TODO legacy retro-compatibility due to old versioned sidebars using versioned doc ids
284
- // ("id" should be removed & "versionedId" should be renamed to "id")
283
+ // TODO legacy retro-compatibility due to old versioned sidebars using
284
+ // versioned doc ids ("id" should be removed & "versionedId" should be renamed
285
+ // to "id")
285
286
  function createDocsByIdIndex(docs) {
286
- return {
287
- ...(0, lodash_1.keyBy)(docs, (doc) => doc.unversionedId),
288
- ...(0, lodash_1.keyBy)(docs, (doc) => doc.id),
289
- };
287
+ return Object.fromEntries(docs.flatMap((doc) => [
288
+ [doc.unversionedId, doc],
289
+ [doc.id, doc],
290
+ ]));
290
291
  }
291
292
  exports.createDocsByIdIndex = createDocsByIdIndex;
package/lib/globalData.js CHANGED
@@ -7,7 +7,8 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.toGlobalDataVersion = exports.toGlobalSidebars = exports.toGlobalDataGeneratedIndex = exports.toGlobalDataDoc = void 0;
10
- const lodash_1 = require("lodash");
10
+ const tslib_1 = require("tslib");
11
+ const lodash_1 = (0, tslib_1.__importDefault)(require("lodash"));
11
12
  const utils_1 = require("@docusaurus/utils");
12
13
  const utils_2 = require("./sidebars/utils");
13
14
  function toGlobalDataDoc(doc) {
@@ -28,7 +29,7 @@ function toGlobalDataGeneratedIndex(doc) {
28
29
  exports.toGlobalDataGeneratedIndex = toGlobalDataGeneratedIndex;
29
30
  function toGlobalSidebars(sidebars, version) {
30
31
  const { getFirstLink } = (0, utils_2.createSidebarsUtils)(sidebars);
31
- return (0, lodash_1.mapValues)(sidebars, (sidebar, sidebarId) => {
32
+ return lodash_1.default.mapValues(sidebars, (sidebar, sidebarId) => {
32
33
  const firstLink = getFirstLink(sidebarId);
33
34
  if (!firstLink) {
34
35
  return {};
package/lib/index.js CHANGED
@@ -16,7 +16,6 @@ const docs_1 = require("./docs");
16
16
  const versions_1 = require("./versions");
17
17
  const cli_1 = require("./cli");
18
18
  const constants_1 = require("./constants");
19
- const lodash_1 = require("lodash");
20
19
  const globalData_1 = require("./globalData");
21
20
  const props_1 = require("./props");
22
21
  const translations_1 = require("./translations");
@@ -119,9 +118,9 @@ async function pluginContentDocs(context, options) {
119
118
  try {
120
119
  return await doLoadVersion(versionMetadata);
121
120
  }
122
- catch (e) {
121
+ catch (err) {
123
122
  logger_1.default.error `Loading of version failed for version name=${versionMetadata.versionName}`;
124
- throw e;
123
+ throw err;
125
124
  }
126
125
  }
127
126
  return {
@@ -133,7 +132,7 @@ async function pluginContentDocs(context, options) {
133
132
  },
134
133
  async contentLoaded({ content, actions }) {
135
134
  const { loadedVersions } = content;
136
- const { docLayoutComponent, docItemComponent, docCategoryGeneratedIndexComponent, } = options;
135
+ const { docLayoutComponent, docItemComponent, docCategoryGeneratedIndexComponent, breadcrumbs, } = options;
137
136
  const { addRoute, createData, setGlobalData } = actions;
138
137
  async function createVersionTagsRoutes(version) {
139
138
  const versionTags = (0, tags_1.getVersionTags)(version.docs);
@@ -191,6 +190,7 @@ async function pluginContentDocs(context, options) {
191
190
  setGlobalData({
192
191
  path: (0, utils_1.normalizeUrl)([baseUrl, options.routeBasePath]),
193
192
  versions: loadedVersions.map(globalData_1.toGlobalDataVersion),
193
+ breadcrumbs,
194
194
  });
195
195
  },
196
196
  configureWebpack(_config, isServer, utils, content) {
@@ -198,7 +198,7 @@ async function pluginContentDocs(context, options) {
198
198
  const { rehypePlugins, remarkPlugins, beforeDefaultRehypePlugins, beforeDefaultRemarkPlugins, } = options;
199
199
  function getSourceToPermalink() {
200
200
  const allDocs = content.loadedVersions.flatMap((v) => v.docs);
201
- return (0, lodash_1.mapValues)((0, lodash_1.keyBy)(allDocs, (d) => d.source), (d) => d.permalink);
201
+ return Object.fromEntries(allDocs.map(({ source, permalink }) => [source, permalink]));
202
202
  }
203
203
  const docsMarkdownOptions = {
204
204
  siteDir,
@@ -214,7 +214,7 @@ async function pluginContentDocs(context, options) {
214
214
  function createMDXLoaderRule() {
215
215
  const contentDirs = versionsMetadata.flatMap(versions_1.getDocsDirPaths);
216
216
  return {
217
- test: /(\.mdx?)$/,
217
+ test: /\.mdx?$/i,
218
218
  include: contentDirs
219
219
  // Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
220
220
  .map(utils_1.addTrailingPathSeparator),
@@ -236,6 +236,11 @@ async function pluginContentDocs(context, options) {
236
236
  const aliasedPath = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
237
237
  return path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedPath)}.json`);
238
238
  },
239
+ // Assets allow to convert some relative images paths to
240
+ // require(...) calls
241
+ createAssets: ({ frontMatter, }) => ({
242
+ image: frontMatter.image,
243
+ }),
239
244
  },
240
245
  },
241
246
  {
package/lib/lastUpdate.js CHANGED
@@ -8,44 +8,31 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.getFileLastUpdate = void 0;
10
10
  const tslib_1 = require("tslib");
11
- const shelljs_1 = (0, tslib_1.__importDefault)(require("shelljs"));
12
11
  const logger_1 = (0, tslib_1.__importDefault)(require("@docusaurus/logger"));
13
- const GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX = /^(\d+),(.+)$/;
12
+ const utils_1 = require("@docusaurus/utils");
14
13
  let showedGitRequirementError = false;
15
14
  async function getFileLastUpdate(filePath) {
16
15
  if (!filePath) {
17
16
  return null;
18
17
  }
19
- function getTimestampAndAuthor(str) {
20
- if (!str) {
21
- return null;
22
- }
23
- const temp = str.match(GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX);
24
- return !temp || temp.length < 3
25
- ? null
26
- : { timestamp: +temp[1], author: temp[2] };
27
- }
28
18
  // Wrap in try/catch in case the shell commands fail
29
19
  // (e.g. project doesn't use Git, etc).
30
20
  try {
31
- if (!shelljs_1.default.which('git')) {
32
- if (!showedGitRequirementError) {
33
- showedGitRequirementError = true;
34
- logger_1.default.warn('Sorry, the docs plugin last update options require Git.');
35
- }
36
- return null;
37
- }
38
- const result = shelljs_1.default.exec(`git log -1 --format=%ct,%an "${filePath}"`, {
39
- silent: true,
21
+ const result = (0, utils_1.getFileCommitDate)(filePath, {
22
+ age: 'newest',
23
+ includeAuthor: true,
40
24
  });
41
- if (result.code !== 0) {
42
- throw new Error(`Retrieval of git history failed at "${filePath}" with exit code ${result.code}: ${result.stderr}`);
43
- }
44
- return getTimestampAndAuthor(result.stdout.trim());
25
+ return { timestamp: result.timestamp, author: result.author };
45
26
  }
46
- catch (e) {
47
- logger_1.default.error(e);
27
+ catch (err) {
28
+ if (err instanceof utils_1.GitNotFoundError && !showedGitRequirementError) {
29
+ logger_1.default.warn('Sorry, the docs plugin last update options require Git.');
30
+ showedGitRequirementError = true;
31
+ }
32
+ else {
33
+ logger_1.default.error(err);
34
+ }
35
+ return null;
48
36
  }
49
- return null;
50
37
  }
51
38
  exports.getFileLastUpdate = getFileLastUpdate;
@@ -8,14 +8,15 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.stripPathNumberPrefixes = exports.stripNumberPrefix = exports.DisabledNumberPrefixParser = exports.DefaultNumberPrefixParser = void 0;
10
10
  // Best-effort to avoid parsing some patterns as number prefix
11
- const IgnoredPrefixPatterns = (function () {
11
+ const IgnoredPrefixPatterns = (() => {
12
12
  // ignore common date-like patterns: https://github.com/facebook/docusaurus/issues/4640
13
- const DateLikePrefixRegex = /^((\d{2}|\d{4})[-_.]\d{2}([-_.](\d{2}|\d{4}))?)(.*)$/;
13
+ const DateLikePrefixRegex = /^(?:\d{2}|\d{4})[-_.]\d{2}(?:[-_.](?:\d{2}|\d{4}))?.*$/;
14
14
  // ignore common versioning patterns: https://github.com/facebook/docusaurus/issues/4653
15
- // note: we could try to parse float numbers in filenames but that is probably not worth it
16
- // as a version such as "8.0" can be interpreted as both a version and a float
17
- // User can configure his own NumberPrefixParser if he wants 8.0 to be interpreted as a float
18
- const VersionLikePrefixRegex = /^(\d+[-_.]\d+)(.*)$/;
15
+ // note: we could try to parse float numbers in filenames but that is
16
+ // probably not worth it as a version such as "8.0" can be interpreted as both
17
+ // a version and a float. User can configure her own NumberPrefixParser if
18
+ // she wants 8.0 to be interpreted as a float
19
+ const VersionLikePrefixRegex = /^\d+[-_.]\d+.*$/;
19
20
  return new RegExp(`${DateLikePrefixRegex.source}|${VersionLikePrefixRegex.source}`);
20
21
  })();
21
22
  const NumberPrefixRegex = /^(?<numberPrefix>\d+)(?<separator>\s*[-_.]+\s*)(?<suffix>.*)$/;
package/lib/options.js CHANGED
@@ -42,6 +42,7 @@ exports.DEFAULT_OPTIONS = {
42
42
  editLocalizedFiles: false,
43
43
  sidebarCollapsible: true,
44
44
  sidebarCollapsed: true,
45
+ breadcrumbs: true,
45
46
  };
46
47
  const VersionOptionsSchema = utils_validation_1.Joi.object({
47
48
  path: utils_validation_1.Joi.string().allow('').optional(),
@@ -98,12 +99,14 @@ exports.OptionsSchema = utils_validation_1.Joi.object({
98
99
  disableVersioning: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.disableVersioning),
99
100
  lastVersion: utils_validation_1.Joi.string().optional(),
100
101
  versions: VersionsOptionsSchema,
102
+ breadcrumbs: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.breadcrumbs),
101
103
  });
102
104
  function validateOptions({ validate, options: userOptions, }) {
103
105
  let options = userOptions;
104
106
  if (options.sidebarCollapsible === false) {
105
- // When sidebarCollapsible=false and sidebarCollapsed=undefined, we don't want to have the inconsistency warning
106
- // We let options.sidebarCollapsible become the default value for options.sidebarCollapsed
107
+ // When sidebarCollapsible=false and sidebarCollapsed=undefined, we don't
108
+ // want to have the inconsistency warning. We let options.sidebarCollapsible
109
+ // become the default value for options.sidebarCollapsed
107
110
  if (typeof options.sidebarCollapsed === 'undefined') {
108
111
  options = {
109
112
  ...options,
package/lib/props.js CHANGED
@@ -7,7 +7,8 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.toTagDocListProp = exports.toVersionMetadataProp = exports.toSidebarsProp = void 0;
10
- const lodash_1 = require("lodash");
10
+ const tslib_1 = require("tslib");
11
+ const lodash_1 = (0, tslib_1.__importDefault)(require("lodash"));
11
12
  const docs_1 = require("./docs");
12
13
  function toSidebarsProp(loadedVersion) {
13
14
  const docsById = (0, docs_1.createDocsByIdIndex)(loadedVersion.docs);
@@ -21,6 +22,7 @@ Available document ids are:
21
22
  return docMetadata;
22
23
  }
23
24
  const convertDocLink = (item) => {
25
+ var _a;
24
26
  const docMetadata = getDocById(item.id);
25
27
  const { title, permalink, frontMatter: { sidebar_label: sidebarLabel }, } = docMetadata;
26
28
  return {
@@ -28,7 +30,7 @@ Available document ids are:
28
30
  label: sidebarLabel || item.label || title,
29
31
  href: permalink,
30
32
  className: item.className,
31
- customProps: item.customProps,
33
+ customProps: (_a = item.customProps) !== null && _a !== void 0 ? _a : docMetadata.frontMatter.sidebar_custom_props,
32
34
  docId: docMetadata.unversionedId,
33
35
  };
34
36
  };
@@ -62,16 +64,19 @@ Available document ids are:
62
64
  // Transform the sidebar so that all sidebar item will be in the
63
65
  // form of 'link' or 'category' only.
64
66
  // This is what will be passed as props to the UI component.
65
- return (0, lodash_1.mapValues)(loadedVersion.sidebars, (items) => items.map(normalizeItem));
67
+ return lodash_1.default.mapValues(loadedVersion.sidebars, (items) => items.map(normalizeItem));
66
68
  }
67
69
  exports.toSidebarsProp = toSidebarsProp;
68
70
  function toVersionDocsProp(loadedVersion) {
69
- return (0, lodash_1.mapValues)((0, lodash_1.keyBy)(loadedVersion.docs, (doc) => doc.unversionedId), (doc) => ({
70
- id: doc.unversionedId,
71
- title: doc.title,
72
- description: doc.description,
73
- sidebar: doc.sidebar,
74
- }));
71
+ return Object.fromEntries(loadedVersion.docs.map((doc) => [
72
+ doc.unversionedId,
73
+ {
74
+ id: doc.unversionedId,
75
+ title: doc.title,
76
+ description: doc.description,
77
+ sidebar: doc.sidebar,
78
+ },
79
+ ]));
75
80
  }
76
81
  function toVersionMetadataProp(pluginId, loadedVersion) {
77
82
  return {
@@ -89,7 +94,7 @@ function toVersionMetadataProp(pluginId, loadedVersion) {
89
94
  exports.toVersionMetadataProp = toVersionMetadataProp;
90
95
  function toTagDocListProp({ allTagsPath, tag, docs, }) {
91
96
  function toDocListProp() {
92
- const list = (0, lodash_1.compact)(tag.docIds.map((id) => docs.find((doc) => doc.id === id)));
97
+ const list = lodash_1.default.compact(tag.docIds.map((id) => docs.find((doc) => doc.id === id)));
93
98
  // Sort docs by title
94
99
  list.sort((doc1, doc2) => doc1.title.localeCompare(doc2.title));
95
100
  return list.map((doc) => ({
package/lib/routes.js CHANGED
@@ -36,7 +36,8 @@ async function createCategoryGeneratedIndexRoutes({ version, actions, docCategor
36
36
  modules: {
37
37
  categoryGeneratedIndex: aliasedSource(propData),
38
38
  },
39
- // Same as doc, this sidebar route attribute permits to associate this subpage to the given sidebar
39
+ // Same as doc, this sidebar route attribute permits to associate this
40
+ // subpage to the given sidebar
40
41
  ...(sidebar && { sidebar }),
41
42
  };
42
43
  }
@@ -57,7 +58,8 @@ async function createDocRoutes({ docs, actions, docItemComponent, }) {
57
58
  content: metadataItem.source,
58
59
  },
59
60
  // Because the parent (DocPage) comp need to access it easily
60
- // This permits to render the sidebar once without unmount/remount when navigating (and preserve sidebar state)
61
+ // This permits to render the sidebar once without unmount/remount when
62
+ // navigating (and preserve sidebar state)
61
63
  ...(metadataItem.sidebar && {
62
64
  sidebar: metadataItem.sidebar,
63
65
  }),
@@ -100,9 +102,9 @@ async function createVersionRoutes({ loadedVersion, actions, docItemComponent, d
100
102
  try {
101
103
  return await doCreateVersionRoutes(loadedVersion);
102
104
  }
103
- catch (e) {
105
+ catch (err) {
104
106
  logger_1.default.error `Can't create version routes for version name=${loadedVersion.versionName}`;
105
- throw e;
107
+ throw err;
106
108
  }
107
109
  }
108
110
  exports.createVersionRoutes = createVersionRoutes;
@@ -0,0 +1,8 @@
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
+ export { CURRENT_VERSION_NAME, VERSIONED_DOCS_DIR, VERSIONED_SIDEBARS_DIR, VERSIONS_JSON_FILE, } from './constants';
8
+ export { filterVersions, getDefaultVersionBanner, getVersionBadge, getVersionBanner, getVersionsFilePath, readVersionsFile, readVersionNames, } from './versions';