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

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 (214) hide show
  1. package/lib/categoryGeneratedIndex.d.ts +12 -0
  2. package/lib/categoryGeneratedIndex.js +35 -0
  3. package/lib/cli.d.ts +2 -2
  4. package/lib/cli.js +37 -51
  5. package/lib/client/docsClientUtils.d.ts +6 -26
  6. package/lib/client/docsClientUtils.js +28 -34
  7. package/lib/{theme/hooks/useDocs.d.ts → client/index.d.ts} +4 -3
  8. package/lib/{theme/hooks/useDocs.js → client/index.js} +28 -25
  9. package/lib/docs.d.ts +31 -4
  10. package/lib/docs.js +160 -54
  11. package/{src/__tests__/__fixtures__/simple-site/docusaurus.config.js → lib/frontMatter.d.ts} +4 -8
  12. package/lib/{docFrontMatter.js → frontMatter.js} +13 -6
  13. package/lib/globalData.d.ts +2 -2
  14. package/lib/globalData.js +32 -3
  15. package/lib/index.d.ts +4 -3
  16. package/lib/index.js +123 -136
  17. package/lib/lastUpdate.d.ts +4 -6
  18. package/lib/lastUpdate.js +22 -26
  19. package/lib/markdown/index.d.ts +3 -6
  20. package/lib/markdown/index.js +3 -3
  21. package/lib/markdown/linkify.d.ts +1 -1
  22. package/lib/markdown/linkify.js +7 -3
  23. package/lib/numberPrefix.d.ts +1 -1
  24. package/lib/numberPrefix.js +16 -21
  25. package/lib/options.d.ts +3 -5
  26. package/lib/options.js +55 -19
  27. package/lib/props.d.ts +7 -2
  28. package/lib/props.js +70 -14
  29. package/lib/routes.d.ts +28 -0
  30. package/lib/routes.js +110 -0
  31. package/lib/server-export.d.ts +8 -0
  32. package/lib/server-export.js +23 -0
  33. package/lib/{sidebarItemsGenerator.d.ts → sidebars/generator.d.ts} +1 -6
  34. package/lib/sidebars/generator.js +209 -0
  35. package/lib/sidebars/index.d.ts +13 -0
  36. package/lib/sidebars/index.js +94 -0
  37. package/lib/sidebars/normalization.d.ts +13 -0
  38. package/lib/sidebars/normalization.js +55 -0
  39. package/lib/sidebars/postProcessor.d.ts +8 -0
  40. package/lib/sidebars/postProcessor.js +65 -0
  41. package/lib/sidebars/processor.d.ts +10 -0
  42. package/lib/sidebars/processor.js +79 -0
  43. package/lib/sidebars/types.d.ts +174 -0
  44. package/{src/__tests__/__fixtures__/site-with-autogenerated-sidebar/partialAutogeneratedSidebars2.js → lib/sidebars/types.js} +2 -10
  45. package/lib/sidebars/utils.d.ts +54 -0
  46. package/lib/sidebars/utils.js +255 -0
  47. package/lib/sidebars/validation.d.ts +11 -0
  48. package/lib/sidebars/validation.js +138 -0
  49. package/lib/slug.d.ts +6 -4
  50. package/lib/slug.js +29 -19
  51. package/{src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docusaurus.config.js → lib/tags.d.ts} +2 -8
  52. package/lib/tags.js +21 -0
  53. package/lib/translations.d.ts +2 -2
  54. package/lib/translations.js +89 -49
  55. package/lib/types.d.ts +60 -130
  56. package/lib/versions.d.ts +29 -4
  57. package/lib/versions.js +134 -97
  58. package/package.json +30 -26
  59. package/src/categoryGeneratedIndex.ts +55 -0
  60. package/src/cli.ts +47 -63
  61. package/src/client/docsClientUtils.ts +38 -73
  62. package/src/{theme/hooks/useDocs.ts → client/index.ts} +16 -11
  63. package/{types.d.ts → src/deps.d.ts} +1 -1
  64. package/src/docs.ts +212 -46
  65. package/src/{docFrontMatter.ts → frontMatter.ts} +21 -26
  66. package/src/globalData.ts +53 -3
  67. package/src/index.ts +168 -178
  68. package/src/lastUpdate.ts +26 -33
  69. package/src/markdown/index.ts +10 -16
  70. package/src/markdown/linkify.ts +6 -2
  71. package/src/numberPrefix.ts +19 -26
  72. package/src/options.ts +60 -32
  73. package/src/plugin-content-docs.d.ts +263 -40
  74. package/src/props.ts +105 -21
  75. package/src/routes.ts +185 -0
  76. package/src/server-export.ts +24 -0
  77. package/src/sidebars/README.md +9 -0
  78. package/src/sidebars/generator.ts +292 -0
  79. package/src/sidebars/index.ts +120 -0
  80. package/src/sidebars/normalization.ts +85 -0
  81. package/src/sidebars/postProcessor.ts +89 -0
  82. package/src/sidebars/processor.ts +120 -0
  83. package/src/sidebars/types.ts +274 -0
  84. package/src/sidebars/utils.ts +388 -0
  85. package/src/sidebars/validation.ts +174 -0
  86. package/src/slug.ts +40 -23
  87. package/src/tags.ts +19 -0
  88. package/src/translations.ts +124 -66
  89. package/src/types.ts +67 -187
  90. package/src/versions.ts +205 -110
  91. package/lib/.tsbuildinfo +0 -4717
  92. package/lib/docFrontMatter.d.ts +0 -21
  93. package/lib/sidebarItemsGenerator.js +0 -211
  94. package/lib/sidebars.d.ts +0 -42
  95. package/lib/sidebars.js +0 -309
  96. package/src/__tests__/__fixtures__/bad-id-site/docs/invalid-id.md +0 -5
  97. package/src/__tests__/__fixtures__/bad-slug-on-doc-home-site/docs/docWithSlug.md +0 -5
  98. package/src/__tests__/__fixtures__/empty-site/docusaurus.config.js +0 -16
  99. package/src/__tests__/__fixtures__/empty-site/sidebars.json +0 -1
  100. package/src/__tests__/__fixtures__/sidebars/sidebars-category-shorthand.js +0 -34
  101. package/src/__tests__/__fixtures__/sidebars/sidebars-category-wrong-items.json +0 -11
  102. package/src/__tests__/__fixtures__/sidebars/sidebars-category-wrong-label.json +0 -11
  103. package/src/__tests__/__fixtures__/sidebars/sidebars-category.js +0 -44
  104. package/src/__tests__/__fixtures__/sidebars/sidebars-collapsed-first-level.json +0 -20
  105. package/src/__tests__/__fixtures__/sidebars/sidebars-collapsed.json +0 -21
  106. package/src/__tests__/__fixtures__/sidebars/sidebars-doc-id-not-string.json +0 -10
  107. package/src/__tests__/__fixtures__/sidebars/sidebars-first-level-not-category.js +0 -20
  108. package/src/__tests__/__fixtures__/sidebars/sidebars-link-wrong-href.json +0 -11
  109. package/src/__tests__/__fixtures__/sidebars/sidebars-link-wrong-label.json +0 -11
  110. package/src/__tests__/__fixtures__/sidebars/sidebars-link.json +0 -11
  111. package/src/__tests__/__fixtures__/sidebars/sidebars-unknown-type.json +0 -14
  112. package/src/__tests__/__fixtures__/sidebars/sidebars-wrong-field.json +0 -20
  113. package/src/__tests__/__fixtures__/sidebars/sidebars.json +0 -20
  114. package/src/__tests__/__fixtures__/simple-site/docs/foo/bar.md +0 -69
  115. package/src/__tests__/__fixtures__/simple-site/docs/foo/baz.md +0 -67
  116. package/src/__tests__/__fixtures__/simple-site/docs/headingAsTitle.md +0 -1
  117. package/src/__tests__/__fixtures__/simple-site/docs/hello.md +0 -52
  118. package/src/__tests__/__fixtures__/simple-site/docs/ipsum.md +0 -5
  119. package/src/__tests__/__fixtures__/simple-site/docs/lorem.md +0 -6
  120. package/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md +0 -5
  121. package/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md +0 -5
  122. package/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md +0 -5
  123. package/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md +0 -5
  124. package/src/__tests__/__fixtures__/simple-site/docs/slugs/absoluteSlug.md +0 -5
  125. package/src/__tests__/__fixtures__/simple-site/docs/slugs/relativeSlug.md +0 -5
  126. package/src/__tests__/__fixtures__/simple-site/docs/slugs/resolvedSlug.md +0 -5
  127. package/src/__tests__/__fixtures__/simple-site/docs/slugs/tryToEscapeSlug.md +0 -5
  128. package/src/__tests__/__fixtures__/simple-site/sidebars.json +0 -23
  129. package/src/__tests__/__fixtures__/simple-site/wrong-sidebars.json +0 -7
  130. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/0-getting-started.md +0 -3
  131. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/1-installation.md +0 -3
  132. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/00_api-overview.md +0 -3
  133. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/01_Core APIs/0 --- Client API.md +0 -1
  134. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/01_Core APIs/1 --- Server API.md +0 -1
  135. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/0. Plugin API.md +0 -1
  136. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/1. Theme API.md +0 -1
  137. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/_category_.yml +0 -1
  138. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/03_api-end.md +0 -3
  139. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/_category_.json +0 -3
  140. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/0-guide2.5.md +0 -8
  141. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/02-guide2.md +0 -7
  142. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/_category_.json +0 -3
  143. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/a-guide4.md +0 -7
  144. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/b-guide5.md +0 -7
  145. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/guide3.md +0 -8
  146. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/z-guide1.md +0 -8
  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/docusaurus.config.js +0 -14
  151. package/src/__tests__/__fixtures__/site-with-doc-label/sidebars.json +0 -14
  152. package/src/__tests__/__fixtures__/versioned-site/community/team.md +0 -1
  153. package/src/__tests__/__fixtures__/versioned-site/community_sidebars.json +0 -3
  154. package/src/__tests__/__fixtures__/versioned-site/community_versioned_docs/version-1.0.0/team.md +0 -1
  155. package/src/__tests__/__fixtures__/versioned-site/community_versioned_sidebars/version-1.0.0-sidebars.json +0 -3
  156. package/src/__tests__/__fixtures__/versioned-site/community_versions.json +0 -1
  157. package/src/__tests__/__fixtures__/versioned-site/docs/foo/bar.md +0 -4
  158. package/src/__tests__/__fixtures__/versioned-site/docs/hello.md +0 -1
  159. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/absoluteSlug.md +0 -5
  160. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/relativeSlug.md +0 -5
  161. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/resolvedSlug.md +0 -5
  162. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/tryToEscapeSlug.md +0 -5
  163. package/src/__tests__/__fixtures__/versioned-site/docusaurus.config.js +0 -18
  164. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md +0 -1
  165. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs-community/current/team.md +0 -5
  166. package/src/__tests__/__fixtures__/versioned-site/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md +0 -1
  167. package/src/__tests__/__fixtures__/versioned-site/sidebars.json +0 -10
  168. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/foo/bar.md +0 -4
  169. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/foo/baz.md +0 -1
  170. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/hello.md +0 -1
  171. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/foo/bar.md +0 -1
  172. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/hello.md +0 -1
  173. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootAbsoluteSlug.md +0 -5
  174. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootRelativeSlug.md +0 -5
  175. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootResolvedSlug.md +0 -5
  176. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootTryToEscapeSlug.md +0 -5
  177. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/absoluteSlug.md +0 -5
  178. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/relativeSlug.md +0 -5
  179. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/resolvedSlug.md +0 -5
  180. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/tryToEscapeSlug.md +0 -5
  181. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.0-sidebars.json +0 -11
  182. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.1-sidebars.json +0 -10
  183. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-withSlugs-sidebars.json +0 -5
  184. package/src/__tests__/__fixtures__/versioned-site/versions.json +0 -5
  185. package/src/__tests__/__snapshots__/cli.test.ts.snap +0 -90
  186. package/src/__tests__/__snapshots__/index.test.ts.snap +0 -1907
  187. package/src/__tests__/__snapshots__/sidebars.test.ts.snap +0 -218
  188. package/src/__tests__/__snapshots__/translations.test.ts.snap +0 -487
  189. package/src/__tests__/cli.test.ts +0 -333
  190. package/src/__tests__/docFrontMatter.test.ts +0 -204
  191. package/src/__tests__/docs.test.ts +0 -875
  192. package/src/__tests__/index.test.ts +0 -1831
  193. package/src/__tests__/lastUpdate.test.ts +0 -68
  194. package/src/__tests__/numberPrefix.test.ts +0 -199
  195. package/src/__tests__/options.test.ts +0 -232
  196. package/src/__tests__/sidebarItemsGenerator.test.ts +0 -336
  197. package/src/__tests__/sidebars.test.ts +0 -638
  198. package/src/__tests__/slug.test.ts +0 -109
  199. package/src/__tests__/translations.test.ts +0 -159
  200. package/src/__tests__/versions.test.ts +0 -718
  201. package/src/client/__tests__/docsClientUtils.test.ts +0 -372
  202. package/src/markdown/__tests__/__fixtures__/docs/doc-localized.md +0 -1
  203. package/src/markdown/__tests__/__fixtures__/docs/doc1.md +0 -13
  204. package/src/markdown/__tests__/__fixtures__/docs/doc2.md +0 -12
  205. package/src/markdown/__tests__/__fixtures__/docs/doc4.md +0 -19
  206. package/src/markdown/__tests__/__fixtures__/docs/doc5.md +0 -6
  207. package/src/markdown/__tests__/__fixtures__/docs/subdir/doc3.md +0 -3
  208. package/src/markdown/__tests__/__fixtures__/versioned_docs/version-1.0.0/doc2.md +0 -7
  209. package/src/markdown/__tests__/__fixtures__/versioned_docs/version-1.0.0/subdir/doc1.md +0 -3
  210. package/src/markdown/__tests__/__snapshots__/linkify.test.ts.snap +0 -82
  211. package/src/markdown/__tests__/linkify.test.ts +0 -190
  212. package/src/sidebarItemsGenerator.ts +0 -307
  213. package/src/sidebars.ts +0 -489
  214. package/tsconfig.json +0 -9
package/src/index.ts CHANGED
@@ -7,10 +7,6 @@
7
7
 
8
8
  import path from 'path';
9
9
 
10
- import {
11
- STATIC_DIR_NAME,
12
- DEFAULT_PLUGIN_ID,
13
- } from '@docusaurus/core/lib/constants';
14
10
  import {
15
11
  normalizeUrl,
16
12
  docuHash,
@@ -18,47 +14,59 @@ import {
18
14
  reportMessage,
19
15
  posixPath,
20
16
  addTrailingPathSeparator,
17
+ createAbsoluteFilePathMatcher,
18
+ createSlugger,
19
+ DEFAULT_PLUGIN_ID,
21
20
  } from '@docusaurus/utils';
22
- import {LoadContext, Plugin, RouteConfig} from '@docusaurus/types';
23
- import {loadSidebars, createSidebarsUtils, processSidebars} from './sidebars';
24
- import {readVersionDocs, processDocMetadata} from './docs';
21
+ import type {LoadContext, Plugin} from '@docusaurus/types';
22
+ import {loadSidebars} from './sidebars';
23
+ import {CategoryMetadataFilenamePattern} from './sidebars/generator';
24
+ import {
25
+ readVersionDocs,
26
+ processDocMetadata,
27
+ addDocNavigation,
28
+ getMainDocId,
29
+ } from './docs';
25
30
  import {getDocsDirPaths, readVersionsMetadata} from './versions';
26
31
 
27
- import {
28
- PluginOptions,
32
+ import type {
29
33
  LoadedContent,
30
34
  SourceToPermalink,
31
35
  DocMetadataBase,
32
- DocMetadata,
33
- GlobalPluginData,
34
36
  VersionMetadata,
35
- DocNavLink,
36
37
  LoadedVersion,
37
38
  DocFile,
38
39
  DocsMarkdownOption,
40
+ VersionTag,
41
+ DocFrontMatter,
39
42
  } from './types';
40
- import {PermalinkToSidebar} from '@docusaurus/plugin-content-docs-types';
41
- import {RuleSetRule} from 'webpack';
43
+ import type {RuleSetRule} from 'webpack';
42
44
  import {cliDocsVersionCommand} from './cli';
43
45
  import {VERSIONS_JSON_FILE} from './constants';
44
- import {flatten, keyBy, compact} from 'lodash';
45
46
  import {toGlobalDataVersion} from './globalData';
46
- import {toVersionMetadataProp} from './props';
47
+ import {toTagDocListProp} from './props';
47
48
  import {
48
49
  translateLoadedContent,
49
50
  getLoadedContentTranslationFiles,
50
51
  } from './translations';
51
- import {CategoryMetadataFilenamePattern} from './sidebarItemsGenerator';
52
+ import logger from '@docusaurus/logger';
53
+ import {getVersionTags} from './tags';
54
+ import {createVersionRoutes} from './routes';
55
+ import type {
56
+ PropTagsListPage,
57
+ PluginOptions,
58
+ } from '@docusaurus/plugin-content-docs';
59
+ import {createSidebarsUtils} from './sidebars/utils';
60
+ import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex';
52
61
 
53
- export default function pluginContentDocs(
62
+ export default async function pluginContentDocs(
54
63
  context: LoadContext,
55
64
  options: PluginOptions,
56
- ): Plugin<LoadedContent> {
65
+ ): Promise<Plugin<LoadedContent>> {
57
66
  const {siteDir, generatedFilesDir, baseUrl, siteConfig} = context;
58
67
 
59
- const versionsMetadata = readVersionsMetadata({context, options});
68
+ const versionsMetadata = await readVersionsMetadata({context, options});
60
69
 
61
- const sourceToPermalink: SourceToPermalink = {};
62
70
  const pluginId = options.id ?? DEFAULT_PLUGIN_ID;
63
71
 
64
72
  const pluginDataDirRoot = path.join(
@@ -72,14 +80,6 @@ export default function pluginContentDocs(
72
80
  return {
73
81
  name: 'docusaurus-plugin-content-docs',
74
82
 
75
- getThemePath() {
76
- return path.resolve(__dirname, './theme');
77
- },
78
-
79
- getTypeScriptThemePath() {
80
- return path.resolve(__dirname, '..', 'src', 'theme');
81
- },
82
-
83
83
  extendCli(cli) {
84
84
  const isDefaultPluginId = pluginId === DEFAULT_PLUGIN_ID;
85
85
 
@@ -100,6 +100,8 @@ export default function pluginContentDocs(
100
100
  cliDocsVersionCommand(version, siteDir, pluginId, {
101
101
  path: options.path,
102
102
  sidebarPath: options.sidebarPath,
103
+ sidebarCollapsed: options.sidebarCollapsed,
104
+ sidebarCollapsible: options.sidebarCollapsible,
103
105
  });
104
106
  });
105
107
  },
@@ -108,22 +110,12 @@ export default function pluginContentDocs(
108
110
  return getLoadedContentTranslationFiles(content);
109
111
  },
110
112
 
111
- getClientModules() {
112
- const modules = [];
113
- if (options.admonitions) {
114
- modules.push(require.resolve('remark-admonitions/styles/infima.css'));
115
- }
116
- return modules;
117
- },
118
-
119
113
  getPathsToWatch() {
120
114
  function getVersionPathsToWatch(version: VersionMetadata): string[] {
121
115
  const result = [
122
- ...flatten(
123
- options.include.map((pattern) =>
124
- getDocsDirPaths(version).map(
125
- (docsDirPath) => `${docsDirPath}/${pattern}`,
126
- ),
116
+ ...options.include.flatMap((pattern) =>
117
+ getDocsDirPaths(version).map(
118
+ (docsDirPath) => `${docsDirPath}/${pattern}`,
127
119
  ),
128
120
  ),
129
121
  `${version.contentPath}/**/${CategoryMetadataFilenamePattern}`,
@@ -134,7 +126,7 @@ export default function pluginContentDocs(
134
126
  return result;
135
127
  }
136
128
 
137
- return flatten(versionsMetadata.map(getVersionPathsToWatch));
129
+ return versionsMetadata.flatMap(getVersionPathsToWatch);
138
130
  },
139
131
 
140
132
  async loadContent() {
@@ -144,12 +136,12 @@ export default function pluginContentDocs(
144
136
  const docFiles = await readVersionDocs(versionMetadata, options);
145
137
  if (docFiles.length === 0) {
146
138
  throw new Error(
147
- `Docs version ${
139
+ `Docs version "${
148
140
  versionMetadata.versionName
149
- } has no docs! At least one doc should exist at path=[${path.relative(
141
+ }" has no docs! At least one doc should exist at "${path.relative(
150
142
  siteDir,
151
143
  versionMetadata.contentPath,
152
- )}]`,
144
+ )}".`,
153
145
  );
154
146
  }
155
147
  async function processVersionDoc(docFile: DocFile) {
@@ -163,101 +155,52 @@ export default function pluginContentDocs(
163
155
  return Promise.all(docFiles.map(processVersionDoc));
164
156
  }
165
157
 
166
- async function loadVersion(
158
+ async function doLoadVersion(
167
159
  versionMetadata: VersionMetadata,
168
160
  ): Promise<LoadedVersion> {
169
- const unprocessedSidebars = loadSidebars(
170
- versionMetadata.sidebarFilePath,
171
- );
172
-
173
- const docsBase: DocMetadataBase[] = await loadVersionDocsBase(
161
+ const docs: DocMetadataBase[] = await loadVersionDocsBase(
174
162
  versionMetadata,
175
163
  );
176
- const docsBaseById: Record<string, DocMetadataBase> = keyBy(
177
- docsBase,
178
- (doc) => doc.id,
179
- );
180
164
 
181
- const sidebars = await processSidebars({
165
+ const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, {
182
166
  sidebarItemsGenerator: options.sidebarItemsGenerator,
183
167
  numberPrefixParser: options.numberPrefixParser,
184
- unprocessedSidebars,
185
- docs: docsBase,
168
+ docs,
186
169
  version: versionMetadata,
170
+ sidebarOptions: {
171
+ sidebarCollapsed: options.sidebarCollapsed,
172
+ sidebarCollapsible: options.sidebarCollapsible,
173
+ },
174
+ categoryLabelSlugger: createSlugger(),
187
175
  });
188
176
 
189
177
  const sidebarsUtils = createSidebarsUtils(sidebars);
190
178
 
191
- const validDocIds = Object.keys(docsBaseById);
192
- sidebarsUtils.checkSidebarsDocIds(validDocIds);
193
-
194
- // Add sidebar/next/previous to the docs
195
- function addNavData(doc: DocMetadataBase): DocMetadata {
196
- const {
197
- sidebarName,
198
- previousId,
199
- nextId,
200
- } = sidebarsUtils.getDocNavigation(doc.id);
201
- const toDocNavLink = (navDocId: string): DocNavLink => ({
202
- title: docsBaseById[navDocId].title,
203
- permalink: docsBaseById[navDocId].permalink,
204
- });
205
- return {
206
- ...doc,
207
- sidebar: sidebarName,
208
- previous: previousId ? toDocNavLink(previousId) : undefined,
209
- next: nextId ? toDocNavLink(nextId) : undefined,
210
- };
211
- }
212
-
213
- const docs = docsBase.map(addNavData);
214
-
215
- // sort to ensure consistent output for tests
216
- docs.sort((a, b) => a.id.localeCompare(b.id));
217
-
218
- // TODO annoying side effect!
219
- Object.values(docs).forEach((loadedDoc) => {
220
- const {source, permalink} = loadedDoc;
221
- sourceToPermalink[source] = permalink;
222
- });
223
-
224
- // TODO really useful? replace with global state logic?
225
- const permalinkToSidebar: PermalinkToSidebar = {};
226
- Object.values(docs).forEach((doc) => {
227
- if (doc.sidebar) {
228
- permalinkToSidebar[doc.permalink] = doc.sidebar;
229
- }
230
- });
231
-
232
- // The "main doc" is the "version entry point"
233
- // We browse this doc by clicking on a version:
234
- // - the "home" doc (at '/docs/')
235
- // - the first doc of the first sidebar
236
- // - a random doc (if no docs are in any sidebar... edge case)
237
- function getMainDoc(): DocMetadata {
238
- const versionHomeDoc = docs.find(
239
- (doc) =>
240
- doc.unversionedId === options.homePageId || doc.slug === '/',
241
- );
242
- const firstDocIdOfFirstSidebar = sidebarsUtils.getFirstDocIdOfFirstSidebar();
243
- if (versionHomeDoc) {
244
- return versionHomeDoc;
245
- } else if (firstDocIdOfFirstSidebar) {
246
- return docs.find((doc) => doc.id === firstDocIdOfFirstSidebar)!;
247
- } else {
248
- return docs[0];
249
- }
250
- }
251
-
252
179
  return {
253
180
  ...versionMetadata,
254
- mainDocId: getMainDoc().unversionedId,
181
+ docs: addDocNavigation(
182
+ docs,
183
+ sidebarsUtils,
184
+ versionMetadata.sidebarFilePath as string,
185
+ ),
255
186
  sidebars,
256
- permalinkToSidebar,
257
- docs: docs.map(addNavData),
187
+ mainDocId: getMainDocId({docs, sidebarsUtils}),
188
+ categoryGeneratedIndices: getCategoryGeneratedIndexMetadataList({
189
+ docs,
190
+ sidebarsUtils,
191
+ }),
258
192
  };
259
193
  }
260
194
 
195
+ async function loadVersion(versionMetadata: VersionMetadata) {
196
+ try {
197
+ return await doLoadVersion(versionMetadata);
198
+ } catch (err) {
199
+ logger.error`Loading of version failed for version name=${versionMetadata.versionName}`;
200
+ throw err;
201
+ }
202
+ }
203
+
261
204
  return {
262
205
  loadedVersions: await Promise.all(versionsMetadata.map(loadVersion)),
263
206
  };
@@ -269,71 +212,94 @@ export default function pluginContentDocs(
269
212
 
270
213
  async contentLoaded({content, actions}) {
271
214
  const {loadedVersions} = content;
272
- const {docLayoutComponent, docItemComponent} = options;
215
+ const {
216
+ docLayoutComponent,
217
+ docItemComponent,
218
+ docCategoryGeneratedIndexComponent,
219
+ breadcrumbs,
220
+ } = options;
273
221
  const {addRoute, createData, setGlobalData} = actions;
274
222
 
275
- const createDocRoutes = async (
276
- docs: DocMetadata[],
277
- ): Promise<RouteConfig[]> => {
278
- const routes = await Promise.all(
279
- docs.map(async (metadataItem) => {
280
- await createData(
281
- // Note that this created data path must be in sync with
282
- // metadataPath provided to mdx-loader.
283
- `${docuHash(metadataItem.source)}.json`,
284
- JSON.stringify(metadataItem, null, 2),
223
+ async function createVersionTagsRoutes(version: LoadedVersion) {
224
+ const versionTags = getVersionTags(version.docs);
225
+
226
+ // TODO tags should be a sub route of the version route
227
+ async function createTagsListPage() {
228
+ const tagsProp: PropTagsListPage['tags'] = Object.values(
229
+ versionTags,
230
+ ).map((tagValue) => ({
231
+ name: tagValue.name,
232
+ permalink: tagValue.permalink,
233
+ count: tagValue.docIds.length,
234
+ }));
235
+
236
+ // Only create /tags page if there are tags.
237
+ if (Object.keys(tagsProp).length > 0) {
238
+ const tagsPropPath = await createData(
239
+ `${docuHash(`tags-list-${version.versionName}-prop`)}.json`,
240
+ JSON.stringify(tagsProp, null, 2),
285
241
  );
286
-
287
- return {
288
- path: metadataItem.permalink,
289
- component: docItemComponent,
242
+ addRoute({
243
+ path: version.tagsPath,
290
244
  exact: true,
245
+ component: options.docTagsListComponent,
291
246
  modules: {
292
- content: metadataItem.source,
247
+ tags: aliasedSource(tagsPropPath),
293
248
  },
294
- };
295
- }),
296
- );
297
-
298
- return routes.sort((a, b) => a.path.localeCompare(b.path));
299
- };
249
+ });
250
+ }
251
+ }
300
252
 
301
- async function handleVersion(loadedVersion: LoadedVersion) {
302
- const versionMetadataPropPath = await createData(
303
- `${docuHash(
304
- `version-${loadedVersion.versionName}-metadata-prop`,
305
- )}.json`,
306
- JSON.stringify(
307
- toVersionMetadataProp(pluginId, loadedVersion),
308
- null,
309
- 2,
310
- ),
311
- );
253
+ // TODO tags should be a sub route of the version route
254
+ async function createTagDocListPage(tag: VersionTag) {
255
+ const tagProps = toTagDocListProp({
256
+ allTagsPath: version.tagsPath,
257
+ tag,
258
+ docs: version.docs,
259
+ });
260
+ const tagPropPath = await createData(
261
+ `${docuHash(`tag-${tag.permalink}`)}.json`,
262
+ JSON.stringify(tagProps, null, 2),
263
+ );
264
+ addRoute({
265
+ path: tag.permalink,
266
+ component: options.docTagDocListComponent,
267
+ exact: true,
268
+ modules: {
269
+ tag: aliasedSource(tagPropPath),
270
+ },
271
+ });
272
+ }
312
273
 
313
- addRoute({
314
- path: loadedVersion.versionPath,
315
- // allow matching /docs/* as well
316
- exact: false,
317
- // main docs component (DocPage)
318
- component: docLayoutComponent,
319
- // sub-routes for each doc
320
- routes: await createDocRoutes(loadedVersion.docs),
321
- modules: {
322
- versionMetadata: aliasedSource(versionMetadataPropPath),
323
- },
324
- priority: loadedVersion.routePriority,
325
- });
274
+ await createTagsListPage();
275
+ await Promise.all(Object.values(versionTags).map(createTagDocListPage));
326
276
  }
327
277
 
328
- await Promise.all(loadedVersions.map(handleVersion));
278
+ await Promise.all(
279
+ loadedVersions.map((loadedVersion) =>
280
+ createVersionRoutes({
281
+ loadedVersion,
282
+ docItemComponent,
283
+ docLayoutComponent,
284
+ docCategoryGeneratedIndexComponent,
285
+ pluginId,
286
+ aliasedSource,
287
+ actions,
288
+ }),
289
+ ),
290
+ );
291
+
292
+ // TODO tags should be a sub route of the version route
293
+ await Promise.all(loadedVersions.map(createVersionTagsRoutes));
329
294
 
330
- setGlobalData<GlobalPluginData>({
295
+ setGlobalData({
331
296
  path: normalizeUrl([baseUrl, options.routeBasePath]),
332
297
  versions: loadedVersions.map(toGlobalDataVersion),
298
+ breadcrumbs,
333
299
  });
334
300
  },
335
301
 
336
- configureWebpack(_config, isServer, utils) {
302
+ configureWebpack(_config, isServer, utils, content) {
337
303
  const {getJSLoader} = utils;
338
304
  const {
339
305
  rehypePlugins,
@@ -342,9 +308,16 @@ export default function pluginContentDocs(
342
308
  beforeDefaultRemarkPlugins,
343
309
  } = options;
344
310
 
311
+ function getSourceToPermalink(): SourceToPermalink {
312
+ const allDocs = content.loadedVersions.flatMap((v) => v.docs);
313
+ return Object.fromEntries(
314
+ allDocs.map(({source, permalink}) => [source, permalink]),
315
+ );
316
+ }
317
+
345
318
  const docsMarkdownOptions: DocsMarkdownOption = {
346
319
  siteDir,
347
- sourceToPermalink,
320
+ sourceToPermalink: getSourceToPermalink(),
348
321
  versionsMetadata,
349
322
  onBrokenMarkdownLink: (brokenMarkdownLink) => {
350
323
  if (siteConfig.onBrokenMarkdownLinks === 'ignore') {
@@ -358,12 +331,13 @@ export default function pluginContentDocs(
358
331
  };
359
332
 
360
333
  function createMDXLoaderRule(): RuleSetRule {
334
+ const contentDirs = versionsMetadata.flatMap(getDocsDirPaths);
361
335
  return {
362
- test: /(\.mdx?)$/,
363
- include: flatten(versionsMetadata.map(getDocsDirPaths))
336
+ test: /\.mdx?$/i,
337
+ include: contentDirs
364
338
  // Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
365
339
  .map(addTrailingPathSeparator),
366
- use: compact([
340
+ use: [
367
341
  getJSLoader({isServer}),
368
342
  {
369
343
  loader: require.resolve('@docusaurus/mdx-loader'),
@@ -372,20 +346,36 @@ export default function pluginContentDocs(
372
346
  rehypePlugins,
373
347
  beforeDefaultRehypePlugins,
374
348
  beforeDefaultRemarkPlugins,
375
- staticDir: path.join(siteDir, STATIC_DIR_NAME),
349
+ staticDirs: siteConfig.staticDirectories.map((dir) =>
350
+ path.resolve(siteDir, dir),
351
+ ),
352
+ siteDir,
353
+ isMDXPartial: createAbsoluteFilePathMatcher(
354
+ options.exclude,
355
+ contentDirs,
356
+ ),
376
357
  metadataPath: (mdxPath: string) => {
377
358
  // Note that metadataPath must be the same/in-sync as
378
359
  // the path from createData for each MDX.
379
360
  const aliasedPath = aliasedSitePath(mdxPath, siteDir);
380
361
  return path.join(dataDir, `${docuHash(aliasedPath)}.json`);
381
362
  },
363
+ // Assets allow to convert some relative images paths to
364
+ // require(...) calls
365
+ createAssets: ({
366
+ frontMatter,
367
+ }: {
368
+ frontMatter: DocFrontMatter;
369
+ }) => ({
370
+ image: frontMatter.image,
371
+ }),
382
372
  },
383
373
  },
384
374
  {
385
375
  loader: path.resolve(__dirname, './markdown/index.js'),
386
376
  options: docsMarkdownOptions,
387
377
  },
388
- ]),
378
+ ].filter(Boolean),
389
379
  };
390
380
  }
391
381
 
package/src/lastUpdate.ts CHANGED
@@ -5,54 +5,47 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import shell from 'shelljs';
9
- import execa from 'execa';
10
-
11
- type FileLastUpdateData = {timestamp?: number; author?: string};
12
-
13
- const GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX = /^(\d+), (.+)$/;
8
+ import logger from '@docusaurus/logger';
9
+ import {
10
+ getFileCommitDate,
11
+ FileNotTrackedError,
12
+ GitNotFoundError,
13
+ } from '@docusaurus/utils';
14
14
 
15
15
  let showedGitRequirementError = false;
16
+ let showedFileNotTrackedError = false;
16
17
 
17
18
  export async function getFileLastUpdate(
18
19
  filePath?: string,
19
- ): Promise<FileLastUpdateData | null> {
20
+ ): Promise<{timestamp: number; author: string} | null> {
20
21
  if (!filePath) {
21
22
  return null;
22
23
  }
23
- function getTimestampAndAuthor(str: string): FileLastUpdateData | null {
24
- if (!str) {
25
- return null;
26
- }
27
-
28
- const temp = str.match(GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX);
29
- return !temp || temp.length < 3
30
- ? null
31
- : {timestamp: +temp[1], author: temp[2]};
32
- }
33
24
 
34
25
  // Wrap in try/catch in case the shell commands fail
35
26
  // (e.g. project doesn't use Git, etc).
36
27
  try {
37
- if (!shell.which('git')) {
28
+ const result = getFileCommitDate(filePath, {
29
+ age: 'newest',
30
+ includeAuthor: true,
31
+ });
32
+ return {timestamp: result.timestamp, author: result.author};
33
+ } catch (err) {
34
+ if (err instanceof GitNotFoundError) {
38
35
  if (!showedGitRequirementError) {
36
+ logger.warn('Sorry, the docs plugin last update options require Git.');
39
37
  showedGitRequirementError = true;
40
- console.warn('Sorry, the docs plugin last update options require Git.');
41
38
  }
42
-
43
- return null;
39
+ } else if (err instanceof FileNotTrackedError) {
40
+ if (!showedFileNotTrackedError) {
41
+ logger.warn(
42
+ 'Cannot infer the update date for some files, as they are not tracked by git.',
43
+ );
44
+ showedFileNotTrackedError = true;
45
+ }
46
+ } else {
47
+ logger.warn(err);
44
48
  }
45
-
46
- const {stdout} = await execa('git', [
47
- 'log',
48
- '-1',
49
- '--format=%ct, %an',
50
- filePath,
51
- ]);
52
- return getTimestampAndAuthor(stdout);
53
- } catch (error) {
54
- console.error(error);
49
+ return null;
55
50
  }
56
-
57
- return null;
58
51
  }
@@ -6,21 +6,15 @@
6
6
  */
7
7
 
8
8
  import {linkify} from './linkify';
9
- import {DocsMarkdownOption} from '../types';
9
+ import type {DocsMarkdownOption} from '../types';
10
+ import type {LoaderContext} from 'webpack';
10
11
 
11
- // TODO temporary until Webpack5 export this type
12
- // see https://github.com/webpack/webpack/issues/11630
13
- interface Loader extends Function {
14
- (this: any, source: string): string | Buffer | void | undefined;
15
- }
16
-
17
- const markdownLoader: Loader = function (source) {
18
- const fileString = source as string;
12
+ export default function markdownLoader(
13
+ this: LoaderContext<DocsMarkdownOption>,
14
+ source: string,
15
+ ): void {
16
+ const fileString = source;
19
17
  const callback = this.async();
20
- const options = this.getOptions() as DocsMarkdownOption;
21
- return (
22
- callback && callback(null, linkify(fileString, this.resourcePath, options))
23
- );
24
- };
25
-
26
- export default markdownLoader;
18
+ const options = this.getOptions();
19
+ return callback?.(null, linkify(fileString, this.resourcePath, options));
20
+ }
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import {DocsMarkdownOption} from '../types';
8
+ import type {DocsMarkdownOption} from '../types';
9
9
  import {getDocsDirPaths} from '../versions';
10
10
  import {replaceMarkdownLinks} from '@docusaurus/utils';
11
11
 
@@ -15,9 +15,13 @@ function getVersion(filePath: string, options: DocsMarkdownOption) {
15
15
  filePath.startsWith(docsDirPath),
16
16
  ),
17
17
  );
18
+ // At this point, this should never happen, because the MDX loaders' paths are
19
+ // literally using the version content paths; but if we allow sourcing content
20
+ // from outside the docs directory (through the `include` option, for example;
21
+ // is there a compelling use-case?), this would actually be testable
18
22
  if (!versionFound) {
19
23
  throw new Error(
20
- `Unexpected, markdown file does not belong to any docs version! file=${filePath}`,
24
+ `Unexpected error: Markdown file at "${filePath}" does not belong to any docs version!`,
21
25
  );
22
26
  }
23
27
  return versionFound;