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

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 (213) hide show
  1. package/lib/categoryGeneratedIndex.d.ts +12 -0
  2. package/lib/categoryGeneratedIndex.js +38 -0
  3. package/lib/cli.d.ts +2 -2
  4. package/lib/cli.js +27 -44
  5. package/lib/client/docsClientUtils.d.ts +3 -25
  6. package/lib/client/docsClientUtils.js +25 -24
  7. package/lib/{theme/hooks/useDocs.d.ts → client/index.d.ts} +1 -2
  8. package/lib/{theme/hooks/useDocs.js → client/index.js} +26 -26
  9. package/lib/docFrontMatter.d.ts +1 -1
  10. package/lib/docFrontMatter.js +9 -3
  11. package/lib/docs.d.ts +39 -3
  12. package/lib/docs.js +157 -53
  13. package/lib/globalData.d.ts +5 -1
  14. package/lib/globalData.js +35 -2
  15. package/lib/index.d.ts +4 -3
  16. package/lib/index.js +110 -144
  17. package/lib/lastUpdate.js +15 -28
  18. package/lib/markdown/index.d.ts +3 -6
  19. package/lib/markdown/index.js +3 -3
  20. package/lib/markdown/linkify.d.ts +1 -1
  21. package/lib/markdown/linkify.js +2 -2
  22. package/lib/numberPrefix.d.ts +1 -1
  23. package/lib/numberPrefix.js +9 -9
  24. package/lib/options.d.ts +3 -3
  25. package/lib/options.js +50 -10
  26. package/lib/props.d.ts +7 -2
  27. package/lib/props.js +66 -11
  28. package/lib/routes.d.ts +28 -0
  29. package/lib/routes.js +110 -0
  30. package/lib/server-export.d.ts +8 -0
  31. package/lib/server-export.js +23 -0
  32. package/lib/{sidebarItemsGenerator.d.ts → sidebars/generator.d.ts} +1 -6
  33. package/lib/sidebars/generator.js +193 -0
  34. package/lib/sidebars/index.d.ts +13 -0
  35. package/lib/sidebars/index.js +88 -0
  36. package/lib/sidebars/normalization.d.ts +13 -0
  37. package/lib/sidebars/normalization.js +55 -0
  38. package/lib/sidebars/postProcessor.d.ts +8 -0
  39. package/lib/sidebars/postProcessor.js +70 -0
  40. package/lib/sidebars/processor.d.ts +8 -0
  41. package/lib/sidebars/processor.js +79 -0
  42. package/lib/sidebars/types.d.ts +166 -0
  43. package/{src/__tests__/__fixtures__/site-with-autogenerated-sidebar/partialAutogeneratedSidebars2.js → lib/sidebars/types.js} +2 -10
  44. package/lib/sidebars/utils.d.ts +43 -0
  45. package/lib/sidebars/utils.js +259 -0
  46. package/lib/sidebars/validation.d.ts +9 -0
  47. package/lib/sidebars/validation.js +137 -0
  48. package/lib/slug.d.ts +6 -4
  49. package/lib/slug.js +28 -17
  50. package/{src/__tests__/__fixtures__/site-with-doc-label/docusaurus.config.js → lib/tags.d.ts} +2 -8
  51. package/lib/tags.js +21 -0
  52. package/lib/translations.d.ts +2 -2
  53. package/lib/translations.js +91 -49
  54. package/lib/types.d.ts +40 -126
  55. package/lib/versions.d.ts +29 -4
  56. package/lib/versions.js +92 -87
  57. package/package.json +30 -27
  58. package/src/categoryGeneratedIndex.ts +59 -0
  59. package/src/cli.ts +34 -54
  60. package/src/client/docsClientUtils.ts +32 -57
  61. package/src/{theme/hooks/useDocs.ts → client/index.ts} +11 -10
  62. package/{types.d.ts → src/deps.d.ts} +0 -0
  63. package/src/docFrontMatter.ts +12 -5
  64. package/src/docs.ts +213 -47
  65. package/src/globalData.ts +53 -2
  66. package/src/index.ts +151 -197
  67. package/src/lastUpdate.ts +14 -37
  68. package/src/markdown/index.ts +9 -13
  69. package/src/markdown/linkify.ts +1 -1
  70. package/src/numberPrefix.ts +11 -8
  71. package/src/options.ts +59 -15
  72. package/src/plugin-content-docs.d.ts +249 -54
  73. package/src/props.ts +97 -18
  74. package/src/routes.ts +185 -0
  75. package/src/server-export.ts +24 -0
  76. package/src/sidebars/README.md +9 -0
  77. package/src/sidebars/generator.ts +269 -0
  78. package/src/sidebars/index.ts +113 -0
  79. package/src/sidebars/normalization.ts +85 -0
  80. package/src/sidebars/postProcessor.ts +94 -0
  81. package/src/sidebars/processor.ts +126 -0
  82. package/src/sidebars/types.ts +273 -0
  83. package/src/sidebars/utils.ts +392 -0
  84. package/src/sidebars/validation.ts +173 -0
  85. package/src/slug.ts +39 -21
  86. package/src/tags.ts +19 -0
  87. package/src/translations.ts +121 -62
  88. package/src/types.ts +46 -183
  89. package/src/versions.ts +136 -102
  90. package/lib/.tsbuildinfo +0 -1
  91. package/lib/sidebarItemsGenerator.js +0 -211
  92. package/lib/sidebars.d.ts +0 -43
  93. package/lib/sidebars.js +0 -320
  94. package/src/__tests__/__fixtures__/bad-id-site/docs/invalid-id.md +0 -5
  95. package/src/__tests__/__fixtures__/bad-slug-on-doc-home-site/docs/docWithSlug.md +0 -5
  96. package/src/__tests__/__fixtures__/empty-site/docusaurus.config.js +0 -16
  97. package/src/__tests__/__fixtures__/empty-site/sidebars.json +0 -1
  98. package/src/__tests__/__fixtures__/sidebars/sidebars-category-shorthand.js +0 -34
  99. package/src/__tests__/__fixtures__/sidebars/sidebars-category-wrong-items.json +0 -11
  100. package/src/__tests__/__fixtures__/sidebars/sidebars-category-wrong-label.json +0 -11
  101. package/src/__tests__/__fixtures__/sidebars/sidebars-category.js +0 -44
  102. package/src/__tests__/__fixtures__/sidebars/sidebars-collapsed-first-level.json +0 -20
  103. package/src/__tests__/__fixtures__/sidebars/sidebars-collapsed.json +0 -21
  104. package/src/__tests__/__fixtures__/sidebars/sidebars-doc-id-not-string.json +0 -10
  105. package/src/__tests__/__fixtures__/sidebars/sidebars-first-level-not-category.js +0 -20
  106. package/src/__tests__/__fixtures__/sidebars/sidebars-link-wrong-href.json +0 -11
  107. package/src/__tests__/__fixtures__/sidebars/sidebars-link-wrong-label.json +0 -11
  108. package/src/__tests__/__fixtures__/sidebars/sidebars-link.json +0 -11
  109. package/src/__tests__/__fixtures__/sidebars/sidebars-unknown-type.json +0 -14
  110. package/src/__tests__/__fixtures__/sidebars/sidebars-wrong-field.json +0 -20
  111. package/src/__tests__/__fixtures__/sidebars/sidebars.json +0 -20
  112. package/src/__tests__/__fixtures__/simple-site/docs/foo/bar.md +0 -69
  113. package/src/__tests__/__fixtures__/simple-site/docs/foo/baz.md +0 -70
  114. package/src/__tests__/__fixtures__/simple-site/docs/headingAsTitle.md +0 -1
  115. package/src/__tests__/__fixtures__/simple-site/docs/hello.md +0 -53
  116. package/src/__tests__/__fixtures__/simple-site/docs/ipsum.md +0 -5
  117. package/src/__tests__/__fixtures__/simple-site/docs/lorem.md +0 -6
  118. package/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md +0 -5
  119. package/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md +0 -5
  120. package/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md +0 -5
  121. package/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md +0 -5
  122. package/src/__tests__/__fixtures__/simple-site/docs/slugs/absoluteSlug.md +0 -5
  123. package/src/__tests__/__fixtures__/simple-site/docs/slugs/relativeSlug.md +0 -5
  124. package/src/__tests__/__fixtures__/simple-site/docs/slugs/resolvedSlug.md +0 -5
  125. package/src/__tests__/__fixtures__/simple-site/docs/slugs/tryToEscapeSlug.md +0 -5
  126. package/src/__tests__/__fixtures__/simple-site/docusaurus.config.js +0 -14
  127. package/src/__tests__/__fixtures__/simple-site/sidebars.json +0 -23
  128. package/src/__tests__/__fixtures__/simple-site/wrong-sidebars.json +0 -7
  129. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/0-getting-started.md +0 -3
  130. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/1-installation.md +0 -3
  131. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/00_api-overview.md +0 -3
  132. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/01_Core APIs/0 --- Client API.md +0 -1
  133. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/01_Core APIs/1 --- Server API.md +0 -1
  134. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/0. Plugin API.md +0 -1
  135. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/1. Theme API.md +0 -1
  136. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/_category_.yml +0 -1
  137. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/03_api-end.md +0 -3
  138. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/_category_.json +0 -3
  139. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/0-guide2.5.md +0 -8
  140. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/02-guide2.md +0 -7
  141. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/_category_.json +0 -3
  142. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/a-guide4.md +0 -7
  143. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/b-guide5.md +0 -7
  144. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/guide3.md +0 -8
  145. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/z-guide1.md +0 -8
  146. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docusaurus.config.js +0 -14
  147. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/partialAutogeneratedSidebars.js +0 -23
  148. package/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-1.md +0 -7
  149. package/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-2.md +0 -8
  150. package/src/__tests__/__fixtures__/site-with-doc-label/sidebars.json +0 -14
  151. package/src/__tests__/__fixtures__/versioned-site/community/team.md +0 -1
  152. package/src/__tests__/__fixtures__/versioned-site/community_sidebars.json +0 -3
  153. package/src/__tests__/__fixtures__/versioned-site/community_versioned_docs/version-1.0.0/team.md +0 -1
  154. package/src/__tests__/__fixtures__/versioned-site/community_versioned_sidebars/version-1.0.0-sidebars.json +0 -3
  155. package/src/__tests__/__fixtures__/versioned-site/community_versions.json +0 -1
  156. package/src/__tests__/__fixtures__/versioned-site/docs/foo/bar.md +0 -4
  157. package/src/__tests__/__fixtures__/versioned-site/docs/hello.md +0 -1
  158. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/absoluteSlug.md +0 -5
  159. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/relativeSlug.md +0 -5
  160. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/resolvedSlug.md +0 -5
  161. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/tryToEscapeSlug.md +0 -5
  162. package/src/__tests__/__fixtures__/versioned-site/docusaurus.config.js +0 -18
  163. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md +0 -1
  164. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs-community/current/team.md +0 -5
  165. package/src/__tests__/__fixtures__/versioned-site/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md +0 -1
  166. package/src/__tests__/__fixtures__/versioned-site/sidebars.json +0 -10
  167. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/foo/bar.md +0 -4
  168. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/foo/baz.md +0 -1
  169. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/hello.md +0 -1
  170. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/foo/bar.md +0 -1
  171. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/hello.md +0 -1
  172. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootAbsoluteSlug.md +0 -5
  173. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootRelativeSlug.md +0 -5
  174. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootResolvedSlug.md +0 -5
  175. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootTryToEscapeSlug.md +0 -5
  176. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/absoluteSlug.md +0 -5
  177. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/relativeSlug.md +0 -5
  178. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/resolvedSlug.md +0 -5
  179. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/tryToEscapeSlug.md +0 -5
  180. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.0-sidebars.json +0 -11
  181. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.1-sidebars.json +0 -10
  182. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-withSlugs-sidebars.json +0 -5
  183. package/src/__tests__/__fixtures__/versioned-site/versions.json +0 -5
  184. package/src/__tests__/__snapshots__/cli.test.ts.snap +0 -90
  185. package/src/__tests__/__snapshots__/index.test.ts.snap +0 -1916
  186. package/src/__tests__/__snapshots__/sidebars.test.ts.snap +0 -218
  187. package/src/__tests__/__snapshots__/translations.test.ts.snap +0 -487
  188. package/src/__tests__/cli.test.ts +0 -333
  189. package/src/__tests__/docFrontMatter.test.ts +0 -244
  190. package/src/__tests__/docs.test.ts +0 -878
  191. package/src/__tests__/index.test.ts +0 -1871
  192. package/src/__tests__/lastUpdate.test.ts +0 -69
  193. package/src/__tests__/numberPrefix.test.ts +0 -199
  194. package/src/__tests__/options.test.ts +0 -231
  195. package/src/__tests__/sidebarItemsGenerator.test.ts +0 -336
  196. package/src/__tests__/sidebars.test.ts +0 -639
  197. package/src/__tests__/slug.test.ts +0 -109
  198. package/src/__tests__/translations.test.ts +0 -159
  199. package/src/__tests__/versions.test.ts +0 -741
  200. package/src/client/__tests__/docsClientUtils.test.ts +0 -371
  201. package/src/markdown/__tests__/__fixtures__/docs/doc-localized.md +0 -1
  202. package/src/markdown/__tests__/__fixtures__/docs/doc1.md +0 -13
  203. package/src/markdown/__tests__/__fixtures__/docs/doc2.md +0 -12
  204. package/src/markdown/__tests__/__fixtures__/docs/doc4.md +0 -19
  205. package/src/markdown/__tests__/__fixtures__/docs/doc5.md +0 -6
  206. package/src/markdown/__tests__/__fixtures__/docs/subdir/doc3.md +0 -3
  207. package/src/markdown/__tests__/__fixtures__/versioned_docs/version-1.0.0/doc2.md +0 -7
  208. package/src/markdown/__tests__/__fixtures__/versioned_docs/version-1.0.0/subdir/doc1.md +0 -3
  209. package/src/markdown/__tests__/__snapshots__/linkify.test.ts.snap +0 -82
  210. package/src/markdown/__tests__/linkify.test.ts +0 -190
  211. package/src/sidebarItemsGenerator.ts +0 -307
  212. package/src/sidebars.ts +0 -522
  213. package/tsconfig.json +0 -9
@@ -7,49 +7,37 @@
7
7
 
8
8
  import {matchPath} from '@docusaurus/router';
9
9
 
10
- import {GlobalPluginData, GlobalVersion, GlobalDoc} from '../types';
10
+ import type {
11
+ GlobalPluginData,
12
+ GlobalVersion,
13
+ GlobalDoc,
14
+ GetActivePluginOptions,
15
+ ActivePlugin,
16
+ ActiveDocContext,
17
+ DocVersionSuggestions,
18
+ } from '@docusaurus/plugin-content-docs/client';
11
19
 
12
20
  // This code is not part of the api surface, not in ./theme on purpose
13
21
 
14
- // Short/convenient type aliases
15
- type Version = GlobalVersion;
16
- type Doc = GlobalDoc;
17
-
18
- export type ActivePlugin = {
19
- pluginId: string;
20
- pluginData: GlobalPluginData;
21
- };
22
-
23
- export type GetActivePluginOptions = {failfast?: boolean};
24
-
25
22
  // get the data of the plugin that is currently "active"
26
23
  // ie the docs of that plugin are currently browsed
27
24
  // it is useful to support multiple docs plugin instances
28
- export function getActivePlugin(
29
- allPluginDatas: Record<string, GlobalPluginData>,
30
- pathname: string,
31
- options: {failfast: true}, // use fail-fast option if you know for sure one plugin instance is active
32
- ): ActivePlugin;
33
- export function getActivePlugin(
34
- allPluginDatas: Record<string, GlobalPluginData>,
35
- pathname: string,
36
- options?: GetActivePluginOptions,
37
- ): ActivePlugin | undefined;
38
-
39
25
  export function getActivePlugin(
40
26
  allPluginDatas: Record<string, GlobalPluginData>,
41
27
  pathname: string,
42
28
  options: GetActivePluginOptions = {},
43
29
  ): ActivePlugin | undefined {
44
- const activeEntry = Object.entries(allPluginDatas).find(
45
- ([_id, pluginData]) => {
46
- return !!matchPath(pathname, {
47
- path: pluginData.path,
48
- exact: false,
49
- strict: false,
50
- });
51
- },
52
- );
30
+ const activeEntry = Object.entries(allPluginDatas)
31
+ // Route sorting: '/android/foo' should match '/android' instead of '/'
32
+ .sort((a, b) => b[1].path.localeCompare(a[1].path))
33
+ .find(
34
+ ([, pluginData]) =>
35
+ !!matchPath(pathname, {
36
+ path: pluginData.path,
37
+ exact: false,
38
+ strict: false,
39
+ }),
40
+ );
53
41
 
54
42
  const activePlugin: ActivePlugin | undefined = activeEntry
55
43
  ? {pluginId: activeEntry[0], pluginData: activeEntry[1]}
@@ -68,36 +56,30 @@ export function getActivePlugin(
68
56
  return activePlugin;
69
57
  }
70
58
 
71
- export type ActiveDocContext = {
72
- activeVersion?: Version;
73
- activeDoc?: Doc;
74
- alternateDocVersions: Record<string, Doc>;
75
- };
76
-
77
- export const getLatestVersion = (data: GlobalPluginData): Version => {
78
- return data.versions.find((version) => version.isLast)!;
79
- };
59
+ export const getLatestVersion = (data: GlobalPluginData): GlobalVersion =>
60
+ data.versions.find((version) => version.isLast)!;
80
61
 
81
62
  // Note: return undefined on doc-unrelated pages,
82
63
  // because there's no version currently considered as active
83
64
  export const getActiveVersion = (
84
65
  data: GlobalPluginData,
85
66
  pathname: string,
86
- ): Version | undefined => {
67
+ ): GlobalVersion | undefined => {
87
68
  const lastVersion = getLatestVersion(data);
88
69
  // Last version is a route like /docs/*,
89
- // 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
90
71
  const orderedVersionsMetadata = [
91
72
  ...data.versions.filter((version) => version !== lastVersion),
92
73
  lastVersion,
93
74
  ];
94
- return orderedVersionsMetadata.find((version) => {
95
- return !!matchPath(pathname, {
96
- path: version.path,
97
- exact: false,
98
- strict: false,
99
- });
100
- });
75
+ return orderedVersionsMetadata.find(
76
+ (version) =>
77
+ !!matchPath(pathname, {
78
+ path: version.path,
79
+ exact: false,
80
+ strict: false,
81
+ }),
82
+ );
101
83
  };
102
84
 
103
85
  export const getActiveDocContext = (
@@ -139,13 +121,6 @@ export const getActiveDocContext = (
139
121
  };
140
122
  };
141
123
 
142
- export type DocVersionSuggestions = {
143
- // suggest the latest version
144
- latestVersionSuggestion: GlobalVersion;
145
- // suggest the same doc, in latest version (if exist)
146
- latestDocSuggestion?: GlobalDoc;
147
- };
148
-
149
124
  export const getDocVersionSuggestions = (
150
125
  data: GlobalPluginData,
151
126
  pathname: string,
@@ -6,37 +6,38 @@
6
6
  */
7
7
 
8
8
  import {useLocation} from '@docusaurus/router';
9
- import useGlobalData, {
10
- // useAllPluginInstancesData,
11
- usePluginData,
12
- } from '@docusaurus/useGlobalData';
9
+ import useGlobalData, {usePluginData} from '@docusaurus/useGlobalData';
13
10
 
14
- import {GlobalPluginData, GlobalVersion} from '../../types';
15
11
  import {
16
12
  getActivePlugin,
17
13
  getLatestVersion,
18
14
  getActiveVersion,
19
15
  getActiveDocContext,
20
16
  getDocVersionSuggestions,
17
+ } from './docsClientUtils';
18
+ import type {
19
+ GlobalPluginData,
20
+ GlobalVersion,
21
21
  ActivePlugin,
22
22
  ActiveDocContext,
23
23
  DocVersionSuggestions,
24
24
  GetActivePluginOptions,
25
- } from '../../client/docsClientUtils';
25
+ } from '@docusaurus/plugin-content-docs/client';
26
26
 
27
- // Important to use a constant object to avoid React useEffect executions etc...,
27
+ // Important to use a constant object to avoid React useEffect executions etc.
28
28
  // see https://github.com/facebook/docusaurus/issues/5089
29
29
  const StableEmptyObject = {};
30
30
 
31
- // Not using useAllPluginInstancesData() because in blog-only mode, docs hooks are still used by the theme
32
- // We need a fail-safe fallback when the docs plugin is not in use
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
33
34
  export const useAllDocsData = (): Record<string, GlobalPluginData> =>
34
- // useAllPluginInstancesData('docusaurus-plugin-content-docs');
35
35
  useGlobalData()['docusaurus-plugin-content-docs'] ?? StableEmptyObject;
36
36
 
37
37
  export const useDocsData = (pluginId: string | undefined): GlobalPluginData =>
38
38
  usePluginData('docusaurus-plugin-content-docs', pluginId) as GlobalPluginData;
39
39
 
40
+ // TODO this feature should be provided by docusaurus core
40
41
  export const useActivePlugin = (
41
42
  options: GetActivePluginOptions = {},
42
43
  ): ActivePlugin | undefined => {
File without changes
@@ -5,17 +5,17 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- /* eslint-disable camelcase */
9
-
10
8
  import {
11
- JoiFrontMatter as Joi, // Custom instance for frontmatter
9
+ JoiFrontMatter as Joi, // Custom instance for front matter
12
10
  URISchema,
11
+ FrontMatterTagsSchema,
12
+ FrontMatterTOCHeadingLevels,
13
13
  validateFrontMatter,
14
14
  } from '@docusaurus/utils-validation';
15
- import {DocFrontMatter} from './types';
15
+ import type {DocFrontMatter} from './types';
16
16
 
17
17
  // NOTE: we don't add any default value on purpose here
18
- // We don't want default values to magically appear in doc metadatas and props
18
+ // We don't want default values to magically appear in doc metadata and props
19
19
  // While the user did not provide those values explicitly
20
20
  // We use default values in code instead
21
21
  const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
@@ -29,9 +29,16 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
29
29
  slug: Joi.string(),
30
30
  sidebar_label: Joi.string(),
31
31
  sidebar_position: Joi.number(),
32
+ sidebar_class_name: Joi.string(),
33
+ sidebar_custom_props: Joi.object().unknown(),
34
+ displayed_sidebar: Joi.string().allow(null),
35
+ tags: FrontMatterTagsSchema,
32
36
  pagination_label: Joi.string(),
33
37
  custom_edit_url: URISchema.allow('', null),
34
38
  parse_number_prefixes: Joi.boolean(),
39
+ pagination_next: Joi.string().allow(null),
40
+ pagination_prev: Joi.string().allow(null),
41
+ ...FrontMatterTOCHeadingLevels,
35
42
  }).unknown();
36
43
 
37
44
  export function validateDocFrontMatter(
package/src/docs.ts CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
  import path from 'path';
9
9
  import fs from 'fs-extra';
10
+ import logger from '@docusaurus/logger';
10
11
  import {
11
12
  aliasedSitePath,
12
13
  getEditUrl,
@@ -14,25 +15,34 @@ import {
14
15
  normalizeUrl,
15
16
  parseMarkdownString,
16
17
  posixPath,
18
+ Globby,
19
+ normalizeFrontMatterTags,
17
20
  } from '@docusaurus/utils';
18
- import {LoadContext} from '@docusaurus/types';
21
+ import type {LoadContext} from '@docusaurus/types';
19
22
 
20
23
  import {getFileLastUpdate} from './lastUpdate';
21
- import {
24
+ import type {
22
25
  DocFile,
23
26
  DocMetadataBase,
27
+ DocMetadata,
28
+ DocNavLink,
24
29
  LastUpdateData,
25
- MetadataOptions,
26
- PluginOptions,
27
30
  VersionMetadata,
31
+ LoadedVersion,
28
32
  } from './types';
29
33
  import getSlug from './slug';
30
34
  import {CURRENT_VERSION_NAME} from './constants';
31
- import globby from 'globby';
32
35
  import {getDocsDirPaths} from './versions';
33
36
  import {stripPathNumberPrefixes} from './numberPrefix';
34
37
  import {validateDocFrontMatter} from './docFrontMatter';
35
- import chalk from 'chalk';
38
+ import type {SidebarsUtils} from './sidebars/utils';
39
+ import {toDocNavigationLink, toNavigationLink} from './sidebars/utils';
40
+ import type {
41
+ MetadataOptions,
42
+ PluginOptions,
43
+ CategoryIndexMatcher,
44
+ CategoryIndexMatcherParam,
45
+ } from '@docusaurus/plugin-content-docs';
36
46
 
37
47
  type LastUpdateOptions = Pick<
38
48
  PluginOptions,
@@ -92,11 +102,12 @@ export async function readVersionDocs(
92
102
  versionMetadata: VersionMetadata,
93
103
  options: Pick<
94
104
  PluginOptions,
95
- 'include' | 'showLastUpdateAuthor' | 'showLastUpdateTime'
105
+ 'include' | 'exclude' | 'showLastUpdateAuthor' | 'showLastUpdateTime'
96
106
  >,
97
107
  ): Promise<DocFile[]> {
98
- const sources = await globby(options.include, {
108
+ const sources = await Globby(options.include, {
99
109
  cwd: versionMetadata.contentPath,
110
+ ignore: options.exclude,
100
111
  });
101
112
  return Promise.all(
102
113
  sources.map((source) => readDocFile(versionMetadata, source, options)),
@@ -115,7 +126,6 @@ function doProcessDocMetadata({
115
126
  options: MetadataOptions;
116
127
  }): DocMetadataBase {
117
128
  const {source, content, lastUpdate, contentPath, filePath} = docFile;
118
- const {homePageId} = options;
119
129
  const {siteDir, i18n} = context;
120
130
 
121
131
  const {
@@ -128,10 +138,10 @@ function doProcessDocMetadata({
128
138
  const {
129
139
  custom_edit_url: customEditURL,
130
140
 
131
- // Strip number prefixes by default (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc) by default,
132
- // but allow to disable this behavior with frontmatterr
133
- // eslint-disable-next-line camelcase
134
- parse_number_prefixes = true,
141
+ // Strip number prefixes by default
142
+ // (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
143
+ // but allow to disable this behavior with front matter
144
+ parse_number_prefixes: parseNumberPrefixes = true,
135
145
  } = frontMatter;
136
146
 
137
147
  // ex: api/plugins/myDoc -> myDoc
@@ -145,8 +155,7 @@ function doProcessDocMetadata({
145
155
  // ex: myDoc -> .
146
156
  const sourceDirName = path.dirname(source);
147
157
 
148
- // eslint-disable-next-line camelcase
149
- const {filename: unprefixedFileName, numberPrefix} = parse_number_prefixes
158
+ const {filename: unprefixedFileName, numberPrefix} = parseNumberPrefixes
150
159
  ? options.numberPrefixParser(sourceFileNameWithoutExtension)
151
160
  : {filename: sourceFileNameWithoutExtension, numberPrefix: undefined};
152
161
 
@@ -155,7 +164,8 @@ function doProcessDocMetadata({
155
164
  throw new Error(`Document id "${baseID}" cannot include slash.`);
156
165
  }
157
166
 
158
- // For autogenerated sidebars, sidebar position can come from filename number prefix or frontmatter
167
+ // For autogenerated sidebars, sidebar position can come from filename number
168
+ // prefix or front matter
159
169
  const sidebarPosition: number | undefined =
160
170
  frontMatter.sidebar_position ?? numberPrefix;
161
171
 
@@ -168,14 +178,13 @@ function doProcessDocMetadata({
168
178
  : `version-${versionMetadata.versionName}`;
169
179
 
170
180
  // TODO legacy retrocompatibility
171
- // I think it's bad to affect the frontmatter id with the dirname?
181
+ // I think it's bad to affect the front matter id with the dirname?
172
182
  function computeDirNameIdPrefix() {
173
183
  if (sourceDirName === '.') {
174
184
  return undefined;
175
185
  }
176
186
  // Eventually remove the number prefixes from intermediate directories
177
- // eslint-disable-next-line camelcase
178
- return parse_number_prefixes
187
+ return parseNumberPrefixes
179
188
  ? stripPathNumberPrefixes(sourceDirName, options.numberPrefixParser)
180
189
  : sourceDirName;
181
190
  }
@@ -188,26 +197,18 @@ function doProcessDocMetadata({
188
197
  // legacy versioned id, requires a breaking change to modify this
189
198
  const id = [versionIdPrefix, unversionedId].filter(Boolean).join('/');
190
199
 
191
- // TODO remove soon, deprecated homePageId
192
- const isDocsHomePage = unversionedId === (homePageId ?? '_index');
193
- if (frontMatter.slug && isDocsHomePage) {
194
- throw new Error(
195
- `The docs homepage (homePageId=${homePageId}) is not allowed to have a frontmatter slug=${frontMatter.slug} => you have to choose either homePageId or slug, not both`,
196
- );
197
- }
198
-
199
- const docSlug = isDocsHomePage
200
- ? '/'
201
- : getSlug({
202
- baseID,
203
- dirName: sourceDirName,
204
- frontmatterSlug: frontMatter.slug,
205
- stripDirNumberPrefixes: parse_number_prefixes,
206
- numberPrefixParser: options.numberPrefixParser,
207
- });
200
+ const docSlug = getSlug({
201
+ baseID,
202
+ source,
203
+ sourceDirName,
204
+ frontMatterSlug: frontMatter.slug,
205
+ stripDirNumberPrefixes: parseNumberPrefixes,
206
+ numberPrefixParser: options.numberPrefixParser,
207
+ });
208
208
 
209
- // Note: the title is used by default for page title, sidebar label, pagination buttons...
210
- // 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)
211
212
  const title: string = frontMatter.title ?? contentTitle ?? baseID;
212
213
 
213
214
  const description: string = frontMatter.description ?? excerpt ?? '';
@@ -234,9 +235,8 @@ function doProcessDocMetadata({
234
235
  ? versionMetadata.versionEditUrlLocalized
235
236
  : versionMetadata.versionEditUrl;
236
237
  return getEditUrl(relativeFilePath, baseVersionEditUrl);
237
- } else {
238
- return undefined;
239
238
  }
239
+ return undefined;
240
240
  }
241
241
 
242
242
  // Assign all of object properties during instantiation (if possible) for
@@ -246,7 +246,6 @@ function doProcessDocMetadata({
246
246
  return {
247
247
  unversionedId,
248
248
  id,
249
- isDocsHomePage,
250
249
  title,
251
250
  description,
252
251
  source: aliasedSitePath(filePath, siteDir),
@@ -254,6 +253,7 @@ function doProcessDocMetadata({
254
253
  slug: docSlug,
255
254
  permalink,
256
255
  editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(),
256
+ tags: normalizeFrontMatterTags(versionMetadata.tagsPath, frontMatter.tags),
257
257
  version: versionMetadata.versionName,
258
258
  lastUpdatedBy: lastUpdate.lastUpdatedBy,
259
259
  lastUpdatedAt: lastUpdate.lastUpdatedAt,
@@ -275,12 +275,178 @@ export function processDocMetadata(args: {
275
275
  }): DocMetadataBase {
276
276
  try {
277
277
  return doProcessDocMetadata(args);
278
- } catch (e) {
279
- console.error(
280
- chalk.red(
281
- `Can't process doc metadatas for doc at path "${args.docFile.filePath}" in version "${args.versionMetadata.versionName}"`,
282
- ),
278
+ } catch (err) {
279
+ logger.error`Can't process doc metadata for doc at path path=${args.docFile.filePath} in version name=${args.versionMetadata.versionName}`;
280
+ throw err;
281
+ }
282
+ }
283
+
284
+ export function addDocNavigation(
285
+ docsBase: DocMetadataBase[],
286
+ sidebarsUtils: SidebarsUtils,
287
+ sidebarFilePath: string,
288
+ ): LoadedVersion['docs'] {
289
+ const docsById = createDocsByIdIndex(docsBase);
290
+
291
+ sidebarsUtils.checkSidebarsDocIds(
292
+ docsBase.flatMap(getDocIds),
293
+ sidebarFilePath,
294
+ );
295
+
296
+ // Add sidebar/next/previous to the docs
297
+ function addNavData(doc: DocMetadataBase): DocMetadata {
298
+ const navigation = sidebarsUtils.getDocNavigation(
299
+ doc.unversionedId,
300
+ doc.id,
301
+ doc.frontMatter.displayed_sidebar,
283
302
  );
284
- throw e;
303
+
304
+ const toNavigationLinkByDocId = (
305
+ docId: string | null | undefined,
306
+ type: 'prev' | 'next',
307
+ ): DocNavLink | undefined => {
308
+ if (!docId) {
309
+ return undefined;
310
+ }
311
+ const navDoc = docsById[docId];
312
+ if (!navDoc) {
313
+ // This could only happen if user provided the ID through front matter
314
+ throw new Error(
315
+ `Error when loading ${doc.id} in ${doc.sourceDirName}: the pagination_${type} front matter points to a non-existent ID ${docId}.`,
316
+ );
317
+ }
318
+ return toDocNavigationLink(navDoc);
319
+ };
320
+
321
+ const previous =
322
+ doc.frontMatter.pagination_prev !== undefined
323
+ ? toNavigationLinkByDocId(doc.frontMatter.pagination_prev, 'prev')
324
+ : toNavigationLink(navigation.previous, docsById);
325
+ const next =
326
+ doc.frontMatter.pagination_next !== undefined
327
+ ? toNavigationLinkByDocId(doc.frontMatter.pagination_next, 'next')
328
+ : toNavigationLink(navigation.next, docsById);
329
+
330
+ return {...doc, sidebar: navigation.sidebarName, previous, next};
285
331
  }
332
+
333
+ const docsWithNavigation = docsBase.map(addNavData);
334
+ // sort to ensure consistent output for tests
335
+ docsWithNavigation.sort((a, b) => a.id.localeCompare(b.id));
336
+ return docsWithNavigation;
337
+ }
338
+
339
+ /**
340
+ * The "main doc" is the "version entry point"
341
+ * We browse this doc by clicking on a version:
342
+ * - the "home" doc (at '/docs/')
343
+ * - the first doc of the first sidebar
344
+ * - a random doc (if no docs are in any sidebar... edge case)
345
+ */
346
+ export function getMainDocId({
347
+ docs,
348
+ sidebarsUtils,
349
+ }: {
350
+ docs: DocMetadataBase[];
351
+ sidebarsUtils: SidebarsUtils;
352
+ }): string {
353
+ function getMainDoc(): DocMetadata {
354
+ const versionHomeDoc = docs.find((doc) => doc.slug === '/');
355
+ const firstDocIdOfFirstSidebar =
356
+ sidebarsUtils.getFirstDocIdOfFirstSidebar();
357
+ if (versionHomeDoc) {
358
+ return versionHomeDoc;
359
+ } else if (firstDocIdOfFirstSidebar) {
360
+ return docs.find(
361
+ (doc) =>
362
+ doc.id === firstDocIdOfFirstSidebar ||
363
+ doc.unversionedId === firstDocIdOfFirstSidebar,
364
+ )!;
365
+ }
366
+ return docs[0];
367
+ }
368
+
369
+ return getMainDoc().unversionedId;
370
+ }
371
+
372
+ // By convention, Docusaurus considers some docs are "indexes":
373
+ // - index.md
374
+ // - readme.md
375
+ // - <folder>/<folder>.md
376
+ //
377
+ // This function is the default implementation of this convention
378
+ //
379
+ // Those index docs produce a different behavior
380
+ // - Slugs do not end with a weird "/index" suffix
381
+ // - Auto-generated sidebar categories link to them as intro
382
+ export const isCategoryIndex: CategoryIndexMatcher = ({
383
+ fileName,
384
+ directories,
385
+ }): boolean => {
386
+ const eligibleDocIndexNames = [
387
+ 'index',
388
+ 'readme',
389
+ directories[0]?.toLowerCase(),
390
+ ];
391
+ return eligibleDocIndexNames.includes(fileName.toLowerCase());
392
+ };
393
+
394
+ export function toCategoryIndexMatcherParam({
395
+ source,
396
+ sourceDirName,
397
+ }: Pick<
398
+ DocMetadataBase,
399
+ 'source' | 'sourceDirName'
400
+ >): CategoryIndexMatcherParam {
401
+ // source + sourceDirName are always posix-style
402
+ return {
403
+ fileName: path.posix.parse(source).name,
404
+ extension: path.posix.parse(source).ext,
405
+ directories: sourceDirName.split(path.posix.sep).reverse(),
406
+ };
407
+ }
408
+
409
+ /**
410
+ * `guides/sidebar/autogenerated.md` ->
411
+ * `'autogenerated', '.md', ['sidebar', 'guides']`
412
+ */
413
+ export function splitPath(str: string): {
414
+ /**
415
+ * The list of directories, from lowest level to highest.
416
+ * If there's no dir name, directories is ['.']
417
+ */
418
+ directories: string[];
419
+ /** The file name, without extension */
420
+ fileName: string;
421
+ /** The extension, with a leading dot */
422
+ extension: string;
423
+ } {
424
+ return {
425
+ fileName: path.parse(str).name,
426
+ extension: path.parse(str).ext,
427
+ directories: path.dirname(str).split(path.sep).reverse(),
428
+ };
429
+ }
430
+
431
+ // Return both doc ids
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")
435
+ export function getDocIds(doc: DocMetadataBase): [string, string] {
436
+ return [doc.unversionedId, doc.id];
437
+ }
438
+
439
+ // docs are indexed by both versioned and unversioned ids at the same time
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")
443
+ export function createDocsByIdIndex<
444
+ Doc extends {id: string; unversionedId: string},
445
+ >(docs: Doc[]): Record<string, Doc> {
446
+ return Object.fromEntries(
447
+ docs.flatMap((doc) => [
448
+ [doc.unversionedId, doc],
449
+ [doc.id, doc],
450
+ ]),
451
+ );
286
452
  }
package/src/globalData.ts CHANGED
@@ -5,7 +5,20 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import {DocMetadata, GlobalDoc, LoadedVersion, GlobalVersion} from './types';
8
+ import _ from 'lodash';
9
+ import {normalizeUrl} from '@docusaurus/utils';
10
+ import type {Sidebars} from './sidebars/types';
11
+ import {createSidebarsUtils} from './sidebars/utils';
12
+ import type {
13
+ CategoryGeneratedIndexMetadata,
14
+ DocMetadata,
15
+ LoadedVersion,
16
+ } from './types';
17
+ import type {
18
+ GlobalVersion,
19
+ GlobalSidebar,
20
+ GlobalDoc,
21
+ } from '@docusaurus/plugin-content-docs/client';
9
22
 
10
23
  export function toGlobalDataDoc(doc: DocMetadata): GlobalDoc {
11
24
  return {
@@ -15,6 +28,41 @@ export function toGlobalDataDoc(doc: DocMetadata): GlobalDoc {
15
28
  };
16
29
  }
17
30
 
31
+ export function toGlobalDataGeneratedIndex(
32
+ doc: CategoryGeneratedIndexMetadata,
33
+ ): GlobalDoc {
34
+ return {
35
+ id: doc.slug,
36
+ path: doc.permalink,
37
+ sidebar: doc.sidebar,
38
+ };
39
+ }
40
+
41
+ export function toGlobalSidebars(
42
+ sidebars: Sidebars,
43
+ version: LoadedVersion,
44
+ ): Record<string, GlobalSidebar> {
45
+ const {getFirstLink} = createSidebarsUtils(sidebars);
46
+ return _.mapValues(sidebars, (sidebar, sidebarId) => {
47
+ const firstLink = getFirstLink(sidebarId);
48
+ if (!firstLink) {
49
+ return {};
50
+ }
51
+ return {
52
+ link: {
53
+ path:
54
+ firstLink.type === 'generated-index'
55
+ ? normalizeUrl([version.versionPath, firstLink.slug])
56
+ : version.docs.find(
57
+ (doc) =>
58
+ doc.id === firstLink.id || doc.unversionedId === firstLink.id,
59
+ )!.permalink,
60
+ label: firstLink.label,
61
+ },
62
+ };
63
+ });
64
+ }
65
+
18
66
  export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion {
19
67
  return {
20
68
  name: version.versionName,
@@ -22,6 +70,9 @@ export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion {
22
70
  isLast: version.isLast,
23
71
  path: version.versionPath,
24
72
  mainDocId: version.mainDocId,
25
- docs: version.docs.map(toGlobalDataDoc),
73
+ docs: version.docs
74
+ .map(toGlobalDataDoc)
75
+ .concat(version.categoryGeneratedIndices.map(toGlobalDataGeneratedIndex)),
76
+ sidebars: toGlobalSidebars(version.sidebars, version),
26
77
  };
27
78
  }