@docusaurus/plugin-content-docs 3.3.2 → 3.5.0

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 (90) hide show
  1. package/lib/categoryGeneratedIndex.d.ts +0 -1
  2. package/lib/categoryGeneratedIndex.js +1 -2
  3. package/lib/cli.d.ts +0 -1
  4. package/lib/cli.js +1 -2
  5. package/lib/client/doc.d.ts +29 -0
  6. package/lib/client/doc.js +47 -0
  7. package/lib/client/docSidebarItemsExpandedState.d.ts +30 -0
  8. package/lib/client/docSidebarItemsExpandedState.js +27 -0
  9. package/lib/client/docsClientUtils.js +16 -8
  10. package/lib/client/docsPreferredVersion.d.ts +29 -0
  11. package/lib/client/docsPreferredVersion.js +124 -0
  12. package/lib/client/docsSearch.d.ts +19 -0
  13. package/lib/client/docsSearch.js +39 -0
  14. package/lib/{markdown/linkify.d.ts → client/docsSearch.test.d.ts} +1 -2
  15. package/lib/client/docsSearch.test.js +12 -0
  16. package/lib/client/docsSidebar.d.ts +25 -0
  17. package/lib/client/docsSidebar.js +29 -0
  18. package/lib/client/docsUtils.d.ts +106 -0
  19. package/lib/client/docsUtils.js +273 -0
  20. package/lib/client/docsVersion.d.ts +19 -0
  21. package/lib/client/docsVersion.js +25 -0
  22. package/lib/client/index.d.ts +8 -0
  23. package/lib/client/index.js +8 -0
  24. package/lib/docs.d.ts +2 -1
  25. package/lib/docs.js +17 -10
  26. package/lib/frontMatter.d.ts +0 -1
  27. package/lib/frontMatter.js +2 -2
  28. package/lib/globalData.js +1 -2
  29. package/lib/index.d.ts +0 -1
  30. package/lib/index.js +85 -55
  31. package/lib/numberPrefix.d.ts +0 -1
  32. package/lib/numberPrefix.js +3 -3
  33. package/lib/options.d.ts +0 -1
  34. package/lib/options.js +13 -2
  35. package/lib/props.d.ts +0 -1
  36. package/lib/props.js +7 -6
  37. package/lib/routes.d.ts +0 -1
  38. package/lib/routes.js +23 -7
  39. package/lib/sidebars/generator.js +3 -0
  40. package/lib/sidebars/index.d.ts +0 -1
  41. package/lib/sidebars/index.js +4 -4
  42. package/lib/sidebars/normalization.js +2 -3
  43. package/lib/sidebars/postProcessor.js +1 -2
  44. package/lib/sidebars/processor.js +1 -2
  45. package/lib/sidebars/types.d.ts +1 -1
  46. package/lib/sidebars/utils.d.ts +0 -1
  47. package/lib/sidebars/utils.js +13 -14
  48. package/lib/sidebars/validation.js +3 -3
  49. package/lib/slug.d.ts +0 -1
  50. package/lib/slug.js +1 -1
  51. package/lib/translations.d.ts +0 -1
  52. package/lib/translations.js +2 -3
  53. package/lib/types.d.ts +3 -14
  54. package/lib/versions/files.d.ts +0 -1
  55. package/lib/versions/files.js +7 -8
  56. package/lib/versions/index.d.ts +1 -1
  57. package/lib/versions/index.js +15 -8
  58. package/lib/versions/validation.d.ts +0 -1
  59. package/lib/versions/validation.js +3 -4
  60. package/package.json +11 -10
  61. package/src/client/doc.tsx +71 -0
  62. package/src/client/docSidebarItemsExpandedState.tsx +55 -0
  63. package/src/client/docsClientUtils.ts +17 -8
  64. package/src/client/docsPreferredVersion.tsx +248 -0
  65. package/src/client/docsSearch.test.ts +14 -0
  66. package/src/client/docsSearch.ts +57 -0
  67. package/src/client/docsSidebar.tsx +50 -0
  68. package/src/client/docsUtils.tsx +415 -0
  69. package/src/client/docsVersion.tsx +36 -0
  70. package/src/client/index.ts +39 -0
  71. package/src/docs.ts +14 -2
  72. package/src/index.ts +116 -73
  73. package/src/options.ts +12 -0
  74. package/src/plugin-content-docs.d.ts +4 -3
  75. package/src/props.ts +2 -0
  76. package/src/routes.ts +23 -4
  77. package/src/sidebars/generator.ts +3 -0
  78. package/src/sidebars/postProcessor.ts +1 -0
  79. package/src/sidebars/types.ts +1 -0
  80. package/src/sidebars/validation.ts +1 -0
  81. package/src/types.ts +2 -16
  82. package/src/versions/index.ts +18 -1
  83. package/lib/markdown/index.d.ts +0 -9
  84. package/lib/markdown/index.js +0 -16
  85. package/lib/markdown/linkify.js +0 -34
  86. package/lib/tags.d.ts +0 -10
  87. package/lib/tags.js +0 -28
  88. package/src/markdown/index.ts +0 -20
  89. package/src/markdown/linkify.ts +0 -47
  90. package/src/tags.ts +0 -27
package/src/index.ts CHANGED
@@ -17,8 +17,15 @@ import {
17
17
  addTrailingPathSeparator,
18
18
  createAbsoluteFilePathMatcher,
19
19
  createSlugger,
20
+ resolveMarkdownLinkPathname,
20
21
  DEFAULT_PLUGIN_ID,
22
+ type SourceToPermalink,
23
+ type TagsFile,
21
24
  } from '@docusaurus/utils';
25
+ import {
26
+ getTagsFile,
27
+ getTagsFilePathsToWatch,
28
+ } from '@docusaurus/utils-validation';
22
29
  import {loadSidebars, resolveSidebarPathOption} from './sidebars';
23
30
  import {CategoryMetadataFilenamePattern} from './sidebars/generator';
24
31
  import {
@@ -28,7 +35,11 @@ import {
28
35
  type DocEnv,
29
36
  createDocsByIdIndex,
30
37
  } from './docs';
31
- import {readVersionsMetadata, toFullVersion} from './versions';
38
+ import {
39
+ getVersionFromSourceFilePath,
40
+ readVersionsMetadata,
41
+ toFullVersion,
42
+ } from './versions';
32
43
  import {cliDocsVersionCommand} from './cli';
33
44
  import {VERSIONS_JSON_FILE} from './constants';
34
45
  import {toGlobalDataVersion} from './globalData';
@@ -38,6 +49,7 @@ import {
38
49
  } from './translations';
39
50
  import {createAllRoutes} from './routes';
40
51
  import {createSidebarsUtils} from './sidebars/utils';
52
+ import type {Options as MDXLoaderOptions} from '@docusaurus/mdx-loader';
41
53
 
42
54
  import type {
43
55
  PluginOptions,
@@ -48,13 +60,31 @@ import type {
48
60
  LoadedVersion,
49
61
  } from '@docusaurus/plugin-content-docs';
50
62
  import type {LoadContext, Plugin} from '@docusaurus/types';
51
- import type {
52
- SourceToPermalink,
53
- DocFile,
54
- DocsMarkdownOption,
55
- FullVersion,
56
- } from './types';
57
- import type {RuleSetRule} from 'webpack';
63
+ import type {DocFile, FullVersion} from './types';
64
+ import type {RuleSetUseItem} from 'webpack';
65
+
66
+ // TODO this is bad, we should have a better way to do this (new lifecycle?)
67
+ // The source to permalink is currently a mutable map passed to the mdx loader
68
+ // for link resolution
69
+ // see https://github.com/facebook/docusaurus/pull/10185
70
+ function createSourceToPermalinkHelper() {
71
+ const sourceToPermalink: SourceToPermalink = new Map();
72
+
73
+ function computeSourceToPermalink(content: LoadedContent): SourceToPermalink {
74
+ const allDocs = content.loadedVersions.flatMap((v) => v.docs);
75
+ return new Map(allDocs.map(({source, permalink}) => [source, permalink]));
76
+ }
77
+
78
+ // Mutable map update :/
79
+ function update(content: LoadedContent): void {
80
+ sourceToPermalink.clear();
81
+ computeSourceToPermalink(content).forEach((value, key) => {
82
+ sourceToPermalink.set(key, value);
83
+ });
84
+ }
85
+
86
+ return {get: () => sourceToPermalink, update};
87
+ }
58
88
 
59
89
  export default async function pluginContentDocs(
60
90
  context: LoadContext,
@@ -82,6 +112,8 @@ export default async function pluginContentDocs(
82
112
  // TODO env should be injected into all plugins
83
113
  const env = process.env.NODE_ENV as DocEnv;
84
114
 
115
+ const sourceToPermalinkHelper = createSourceToPermalinkHelper();
116
+
85
117
  return {
86
118
  name: 'docusaurus-plugin-content-docs',
87
119
 
@@ -118,6 +150,10 @@ export default async function pluginContentDocs(
118
150
  (docsDirPath) => `${docsDirPath}/${pattern}`,
119
151
  ),
120
152
  ),
153
+ ...getTagsFilePathsToWatch({
154
+ contentPaths: version,
155
+ tags: options.tags,
156
+ }),
121
157
  `${version.contentPath}/**/${CategoryMetadataFilenamePattern}`,
122
158
  ];
123
159
  if (typeof version.sidebarFilePath === 'string') {
@@ -132,6 +168,7 @@ export default async function pluginContentDocs(
132
168
  async loadContent() {
133
169
  async function loadVersionDocsBase(
134
170
  versionMetadata: VersionMetadata,
171
+ tagsFile: TagsFile | null,
135
172
  ): Promise<DocMetadataBase[]> {
136
173
  const docFiles = await readVersionDocs(versionMetadata, options);
137
174
  if (docFiles.length === 0) {
@@ -151,6 +188,7 @@ export default async function pluginContentDocs(
151
188
  context,
152
189
  options,
153
190
  env,
191
+ tagsFile,
154
192
  });
155
193
  }
156
194
  return Promise.all(docFiles.map(processVersionDoc));
@@ -159,8 +197,14 @@ export default async function pluginContentDocs(
159
197
  async function doLoadVersion(
160
198
  versionMetadata: VersionMetadata,
161
199
  ): Promise<LoadedVersion> {
200
+ const tagsFile = await getTagsFile({
201
+ contentPaths: versionMetadata,
202
+ tags: options.tags,
203
+ });
204
+
162
205
  const docsBase: DocMetadataBase[] = await loadVersionDocsBase(
163
206
  versionMetadata,
207
+ tagsFile,
164
208
  );
165
209
 
166
210
  // TODO we only ever need draftIds in further code, not full draft items
@@ -226,6 +270,8 @@ export default async function pluginContentDocs(
226
270
  },
227
271
 
228
272
  async contentLoaded({content, actions}) {
273
+ sourceToPermalinkHelper.update(content);
274
+
229
275
  const versions: FullVersion[] = content.loadedVersions.map(toFullVersion);
230
276
 
231
277
  await createAllRoutes({
@@ -247,76 +293,67 @@ export default async function pluginContentDocs(
247
293
  const {
248
294
  rehypePlugins,
249
295
  remarkPlugins,
296
+ recmaPlugins,
250
297
  beforeDefaultRehypePlugins,
251
298
  beforeDefaultRemarkPlugins,
252
299
  } = options;
253
300
 
254
- function getSourceToPermalink(): SourceToPermalink {
255
- const allDocs = content.loadedVersions.flatMap((v) => v.docs);
256
- return Object.fromEntries(
257
- allDocs.map(({source, permalink}) => [source, permalink]),
258
- );
259
- }
260
-
261
- const docsMarkdownOptions: DocsMarkdownOption = {
262
- siteDir,
263
- sourceToPermalink: getSourceToPermalink(),
264
- versionsMetadata,
265
- onBrokenMarkdownLink: (brokenMarkdownLink) => {
266
- logger.report(
267
- siteConfig.onBrokenMarkdownLinks,
268
- )`Docs markdown link couldn't be resolved: (url=${brokenMarkdownLink.link}) in path=${brokenMarkdownLink.filePath} for version number=${brokenMarkdownLink.contentPaths.versionName}`;
269
- },
270
- };
301
+ const contentDirs = versionsMetadata
302
+ .flatMap(getContentPathList)
303
+ // Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
304
+ .map(addTrailingPathSeparator);
305
+
306
+ function createMDXLoader(): RuleSetUseItem {
307
+ const loaderOptions: MDXLoaderOptions = {
308
+ admonitions: options.admonitions,
309
+ remarkPlugins,
310
+ rehypePlugins,
311
+ recmaPlugins,
312
+ beforeDefaultRehypePlugins,
313
+ beforeDefaultRemarkPlugins,
314
+ staticDirs: siteConfig.staticDirectories.map((dir) =>
315
+ path.resolve(siteDir, dir),
316
+ ),
317
+ siteDir,
318
+ isMDXPartial: createAbsoluteFilePathMatcher(
319
+ options.exclude,
320
+ contentDirs,
321
+ ),
322
+ metadataPath: (mdxPath: string) => {
323
+ // Note that metadataPath must be the same/in-sync as
324
+ // the path from createData for each MDX.
325
+ const aliasedPath = aliasedSitePath(mdxPath, siteDir);
326
+ return path.join(dataDir, `${docuHash(aliasedPath)}.json`);
327
+ },
328
+ // Assets allow to convert some relative images paths to
329
+ // require(...) calls
330
+ createAssets: ({frontMatter}: {frontMatter: DocFrontMatter}) => ({
331
+ image: frontMatter.image,
332
+ }),
333
+ markdownConfig: siteConfig.markdown,
334
+ resolveMarkdownLink: ({linkPathname, sourceFilePath}) => {
335
+ const version = getVersionFromSourceFilePath(
336
+ sourceFilePath,
337
+ content.loadedVersions,
338
+ );
339
+ const permalink = resolveMarkdownLinkPathname(linkPathname, {
340
+ sourceFilePath,
341
+ sourceToPermalink: sourceToPermalinkHelper.get(),
342
+ siteDir,
343
+ contentPaths: version,
344
+ });
345
+ if (permalink === null) {
346
+ logger.report(
347
+ siteConfig.onBrokenMarkdownLinks,
348
+ )`Docs markdown link couldn't be resolved: (url=${linkPathname}) in source file path=${sourceFilePath} for version number=${version.versionName}`;
349
+ }
350
+ return permalink;
351
+ },
352
+ };
271
353
 
272
- function createMDXLoaderRule(): RuleSetRule {
273
- const contentDirs = versionsMetadata
274
- .flatMap(getContentPathList)
275
- // Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
276
- .map(addTrailingPathSeparator);
277
354
  return {
278
- test: /\.mdx?$/i,
279
- include: contentDirs,
280
- use: [
281
- {
282
- loader: require.resolve('@docusaurus/mdx-loader'),
283
- options: {
284
- admonitions: options.admonitions,
285
- remarkPlugins,
286
- rehypePlugins,
287
- beforeDefaultRehypePlugins,
288
- beforeDefaultRemarkPlugins,
289
- staticDirs: siteConfig.staticDirectories.map((dir) =>
290
- path.resolve(siteDir, dir),
291
- ),
292
- siteDir,
293
- isMDXPartial: createAbsoluteFilePathMatcher(
294
- options.exclude,
295
- contentDirs,
296
- ),
297
- metadataPath: (mdxPath: string) => {
298
- // Note that metadataPath must be the same/in-sync as
299
- // the path from createData for each MDX.
300
- const aliasedPath = aliasedSitePath(mdxPath, siteDir);
301
- return path.join(dataDir, `${docuHash(aliasedPath)}.json`);
302
- },
303
- // Assets allow to convert some relative images paths to
304
- // require(...) calls
305
- createAssets: ({
306
- frontMatter,
307
- }: {
308
- frontMatter: DocFrontMatter;
309
- }) => ({
310
- image: frontMatter.image,
311
- }),
312
- markdownConfig: siteConfig.markdown,
313
- },
314
- },
315
- {
316
- loader: path.resolve(__dirname, './markdown/index.js'),
317
- options: docsMarkdownOptions,
318
- },
319
- ].filter(Boolean),
355
+ loader: require.resolve('@docusaurus/mdx-loader'),
356
+ options: loaderOptions,
320
357
  };
321
358
  }
322
359
 
@@ -333,7 +370,13 @@ export default async function pluginContentDocs(
333
370
  },
334
371
  },
335
372
  module: {
336
- rules: [createMDXLoaderRule()],
373
+ rules: [
374
+ {
375
+ test: /\.mdx?$/i,
376
+ include: contentDirs,
377
+ use: [createMDXLoader()],
378
+ },
379
+ ],
337
380
  },
338
381
  };
339
382
  },
package/src/options.ts CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  Joi,
11
11
  RemarkPluginsSchema,
12
12
  RehypePluginsSchema,
13
+ RecmaPluginsSchema,
13
14
  AdmonitionsSchema,
14
15
  RouteBasePathSchema,
15
16
  URISchema,
@@ -40,6 +41,7 @@ export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'> = {
40
41
  docCategoryGeneratedIndexComponent: '@theme/DocCategoryGeneratedIndexPage',
41
42
  remarkPlugins: [],
42
43
  rehypePlugins: [],
44
+ recmaPlugins: [],
43
45
  beforeDefaultRemarkPlugins: [],
44
46
  beforeDefaultRehypePlugins: [],
45
47
  showLastUpdateTime: false,
@@ -54,6 +56,8 @@ export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'> = {
54
56
  sidebarCollapsible: true,
55
57
  sidebarCollapsed: true,
56
58
  breadcrumbs: true,
59
+ onInlineTags: 'warn',
60
+ tags: undefined,
57
61
  };
58
62
 
59
63
  const VersionOptionsSchema = Joi.object({
@@ -121,6 +125,7 @@ const OptionsSchema = Joi.object<PluginOptions>({
121
125
  ),
122
126
  remarkPlugins: RemarkPluginsSchema.default(DEFAULT_OPTIONS.remarkPlugins),
123
127
  rehypePlugins: RehypePluginsSchema.default(DEFAULT_OPTIONS.rehypePlugins),
128
+ recmaPlugins: RecmaPluginsSchema.default(DEFAULT_OPTIONS.recmaPlugins),
124
129
  beforeDefaultRemarkPlugins: RemarkPluginsSchema.default(
125
130
  DEFAULT_OPTIONS.beforeDefaultRemarkPlugins,
126
131
  ),
@@ -140,6 +145,13 @@ const OptionsSchema = Joi.object<PluginOptions>({
140
145
  lastVersion: Joi.string().optional(),
141
146
  versions: VersionsOptionsSchema,
142
147
  breadcrumbs: Joi.bool().default(DEFAULT_OPTIONS.breadcrumbs),
148
+ onInlineTags: Joi.string()
149
+ .equal('ignore', 'log', 'warn', 'throw')
150
+ .default(DEFAULT_OPTIONS.onInlineTags),
151
+ tags: Joi.string()
152
+ .disallow('')
153
+ .allow(null, false)
154
+ .default(() => DEFAULT_OPTIONS.tags),
143
155
  });
144
156
 
145
157
  export function validateOptions({
@@ -15,9 +15,10 @@ declare module '@docusaurus/plugin-content-docs' {
15
15
  FrontMatterTag,
16
16
  TagsListItem,
17
17
  TagModule,
18
- Tag,
19
18
  FrontMatterLastUpdate,
20
19
  LastUpdateData,
20
+ TagMetadata,
21
+ TagsPluginOptions,
21
22
  } from '@docusaurus/utils';
22
23
  import type {Plugin, LoadContext} from '@docusaurus/types';
23
24
  import type {Overwrite, Required} from 'utility-types';
@@ -64,7 +65,7 @@ declare module '@docusaurus/plugin-content-docs' {
64
65
  locale: string;
65
66
  }) => string | undefined;
66
67
 
67
- export type MetadataOptions = {
68
+ export type MetadataOptions = TagsPluginOptions & {
68
69
  /**
69
70
  * URL route for the docs section of your site. **DO NOT** include a
70
71
  * trailing slash. Use `/` for shipping docs without base path.
@@ -446,7 +447,7 @@ declare module '@docusaurus/plugin-content-docs' {
446
447
  */
447
448
  editUrl?: string | null;
448
449
  /** Tags, normalized. */
449
- tags: Tag[];
450
+ tags: TagMetadata[];
450
451
  /** Front matter, as-is. */
451
452
  frontMatter: DocFrontMatter & {[key: string]: unknown};
452
453
  };
package/src/props.ts CHANGED
@@ -206,6 +206,7 @@ export function toTagDocListProp({
206
206
  return {
207
207
  label: tag.label,
208
208
  permalink: tag.permalink,
209
+ description: tag.description,
209
210
  allTagsPath,
210
211
  count: tag.docIds.length,
211
212
  items: toDocListProp(),
@@ -221,6 +222,7 @@ export function toTagsListTagsProp(
221
222
  .map((tagValue) => ({
222
223
  label: tagValue.label,
223
224
  permalink: tagValue.permalink,
225
+ description: tagValue.description,
224
226
  count: tagValue.docIds.length,
225
227
  }));
226
228
  }
package/src/routes.ts CHANGED
@@ -11,19 +11,20 @@ import {
11
11
  docuHash,
12
12
  normalizeUrl,
13
13
  aliasedSitePathToRelativePath,
14
+ groupTaggedItems,
15
+ getTagVisibility,
14
16
  } from '@docusaurus/utils';
15
17
  import {
16
18
  toTagDocListProp,
17
19
  toTagsListTagsProp,
18
20
  toVersionMetadataProp,
19
21
  } from './props';
20
- import {getVersionTags} from './tags';
21
22
  import type {
22
23
  PluginContentLoadedActions,
23
24
  RouteConfig,
24
25
  RouteMetadata,
25
26
  } from '@docusaurus/types';
26
- import type {FullVersion, VersionTag} from './types';
27
+ import type {FullVersion, VersionTag, VersionTags} from './types';
27
28
  import type {
28
29
  CategoryGeneratedIndexMetadata,
29
30
  DocMetadata,
@@ -112,6 +113,23 @@ async function buildVersionSidebarRoute(param: BuildVersionRoutesParam) {
112
113
  routes: subRoutes,
113
114
  };
114
115
  }
116
+ function getVersionTags(docs: DocMetadata[]): VersionTags {
117
+ const groups = groupTaggedItems(docs, (doc) => doc.tags);
118
+ return _.mapValues(groups, ({tag, items: tagDocs}) => {
119
+ const tagVisibility = getTagVisibility({
120
+ items: tagDocs,
121
+ isUnlisted: (item) => item.unlisted,
122
+ });
123
+ return {
124
+ inline: tag.inline,
125
+ label: tag.label,
126
+ permalink: tag.permalink,
127
+ description: tag.description,
128
+ docIds: tagVisibility.listedItems.map((item) => item.id),
129
+ unlisted: tagVisibility.unlisted,
130
+ };
131
+ });
132
+ }
115
133
 
116
134
  async function buildVersionTagsRoutes(
117
135
  param: BuildVersionRoutesParam,
@@ -120,8 +138,9 @@ async function buildVersionTagsRoutes(
120
138
  const versionTags = getVersionTags(version.docs);
121
139
 
122
140
  async function buildTagsListRoute(): Promise<RouteConfig | null> {
141
+ const tags = toTagsListTagsProp(versionTags);
123
142
  // Don't create a tags list page if there's no tag
124
- if (Object.keys(versionTags).length === 0) {
143
+ if (tags.length === 0) {
125
144
  return null;
126
145
  }
127
146
  return {
@@ -129,7 +148,7 @@ async function buildVersionTagsRoutes(
129
148
  exact: true,
130
149
  component: options.docTagsListComponent,
131
150
  props: {
132
- tags: toTagsListTagsProp(versionTags),
151
+ tags,
133
152
  },
134
153
  };
135
154
  }
@@ -249,6 +249,9 @@ Available doc IDs:
249
249
  ...(customProps !== undefined && {customProps}),
250
250
  ...(className !== undefined && {className}),
251
251
  items,
252
+ ...(categoryMetadata?.description && {
253
+ description: categoryMetadata?.description,
254
+ }),
252
255
  ...(link && {link}),
253
256
  };
254
257
  }
@@ -64,6 +64,7 @@ function postProcessSidebarItem(
64
64
  .map((subItem) => postProcessSidebarItem(subItem, params))
65
65
  .filter((v): v is SidebarItem => Boolean(v)),
66
66
  };
67
+
67
68
  // If the current category doesn't have subitems, we render a normal link
68
69
  // instead.
69
70
  if (category.items.length === 0) {
@@ -217,6 +217,7 @@ export type PropSidebarBreadcrumbsItem =
217
217
  export type CategoryMetadataFile = {
218
218
  label?: string;
219
219
  position?: number;
220
+ description?: string;
220
221
  collapsed?: boolean;
221
222
  collapsible?: boolean;
222
223
  className?: string;
@@ -167,6 +167,7 @@ export function validateSidebars(sidebars: {
167
167
 
168
168
  const categoryMetadataFileSchema = Joi.object<CategoryMetadataFile>({
169
169
  label: Joi.string(),
170
+ description: Joi.string(),
170
171
  position: Joi.number(),
171
172
  collapsed: Joi.boolean(),
172
173
  collapsible: Joi.boolean(),
package/src/types.ts CHANGED
@@ -5,9 +5,8 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import type {BrokenMarkdownLink, Tag} from '@docusaurus/utils';
8
+ import type {TagMetadata} from '@docusaurus/utils';
9
9
  import type {
10
- VersionMetadata,
11
10
  LoadedVersion,
12
11
  CategoryGeneratedIndexMetadata,
13
12
  } from '@docusaurus/plugin-content-docs';
@@ -20,11 +19,7 @@ export type DocFile = {
20
19
  content: string;
21
20
  };
22
21
 
23
- export type SourceToPermalink = {
24
- [source: string]: string;
25
- };
26
-
27
- export type VersionTag = Tag & {
22
+ export type VersionTag = TagMetadata & {
28
23
  /** All doc ids having this tag. */
29
24
  docIds: string[];
30
25
  unlisted: boolean;
@@ -37,12 +32,3 @@ export type FullVersion = LoadedVersion & {
37
32
  sidebarsUtils: SidebarsUtils;
38
33
  categoryGeneratedIndices: CategoryGeneratedIndexMetadata[];
39
34
  };
40
-
41
- export type DocBrokenMarkdownLink = BrokenMarkdownLink<VersionMetadata>;
42
-
43
- export type DocsMarkdownOption = {
44
- versionsMetadata: VersionMetadata[];
45
- siteDir: string;
46
- sourceToPermalink: SourceToPermalink;
47
- onBrokenMarkdownLink: (brokenMarkdownLink: DocBrokenMarkdownLink) => void;
48
- };
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import path from 'path';
9
- import {normalizeUrl, posixPath} from '@docusaurus/utils';
9
+ import {getContentPathList, normalizeUrl, posixPath} from '@docusaurus/utils';
10
10
  import {CURRENT_VERSION_NAME} from '../constants';
11
11
  import {validateVersionsOptions} from './validation';
12
12
  import {
@@ -268,3 +268,20 @@ export function toFullVersion(version: LoadedVersion): FullVersion {
268
268
  }),
269
269
  };
270
270
  }
271
+
272
+ export function getVersionFromSourceFilePath(
273
+ filePath: string,
274
+ versionsMetadata: VersionMetadata[],
275
+ ): VersionMetadata {
276
+ const versionFound = versionsMetadata.find((version) =>
277
+ getContentPathList(version).some((docsDirPath) =>
278
+ filePath.startsWith(docsDirPath),
279
+ ),
280
+ );
281
+ if (!versionFound) {
282
+ throw new Error(
283
+ `Unexpected error: file at "${filePath}" does not belong to any docs version!`,
284
+ );
285
+ }
286
+ return versionFound;
287
+ }
@@ -1,9 +0,0 @@
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
- import type { DocsMarkdownOption } from '../types';
8
- import type { LoaderContext } from 'webpack';
9
- export default function markdownLoader(this: LoaderContext<DocsMarkdownOption>, source: string): void;
@@ -1,16 +0,0 @@
1
- "use strict";
2
- /**
3
- * Copyright (c) Facebook, Inc. and its affiliates.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- const linkify_1 = require("./linkify");
10
- function markdownLoader(source) {
11
- const fileString = source;
12
- const callback = this.async();
13
- const options = this.getOptions();
14
- return callback(null, (0, linkify_1.linkify)(fileString, this.resourcePath, options));
15
- }
16
- exports.default = markdownLoader;
@@ -1,34 +0,0 @@
1
- "use strict";
2
- /**
3
- * Copyright (c) Facebook, Inc. and its affiliates.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.linkify = void 0;
10
- const utils_1 = require("@docusaurus/utils");
11
- function getVersion(filePath, options) {
12
- const versionFound = options.versionsMetadata.find((version) => (0, utils_1.getContentPathList)(version).some((docsDirPath) => filePath.startsWith(docsDirPath)));
13
- // At this point, this should never happen, because the MDX loaders' paths are
14
- // literally using the version content paths; but if we allow sourcing content
15
- // from outside the docs directory (through the `include` option, for example;
16
- // is there a compelling use-case?), this would actually be testable
17
- if (!versionFound) {
18
- throw new Error(`Unexpected error: Markdown file at "${filePath}" does not belong to any docs version!`);
19
- }
20
- return versionFound;
21
- }
22
- function linkify(fileString, filePath, options) {
23
- const { siteDir, sourceToPermalink, onBrokenMarkdownLink } = options;
24
- const { newContent, brokenMarkdownLinks } = (0, utils_1.replaceMarkdownLinks)({
25
- siteDir,
26
- fileString,
27
- filePath,
28
- contentPaths: getVersion(filePath, options),
29
- sourceToPermalink,
30
- });
31
- brokenMarkdownLinks.forEach((l) => onBrokenMarkdownLink(l));
32
- return newContent;
33
- }
34
- exports.linkify = linkify;
package/lib/tags.d.ts DELETED
@@ -1,10 +0,0 @@
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
- /// <reference path="../src/plugin-content-docs.d.ts" />
8
- import type { VersionTags } from './types';
9
- import type { DocMetadata } from '@docusaurus/plugin-content-docs';
10
- export declare function getVersionTags(docs: DocMetadata[]): VersionTags;
package/lib/tags.js DELETED
@@ -1,28 +0,0 @@
1
- "use strict";
2
- /**
3
- * Copyright (c) Facebook, Inc. and its affiliates.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.getVersionTags = void 0;
10
- const tslib_1 = require("tslib");
11
- const lodash_1 = tslib_1.__importDefault(require("lodash"));
12
- const utils_1 = require("@docusaurus/utils");
13
- function getVersionTags(docs) {
14
- const groups = (0, utils_1.groupTaggedItems)(docs, (doc) => doc.tags);
15
- return lodash_1.default.mapValues(groups, ({ tag, items: tagDocs }) => {
16
- const tagVisibility = (0, utils_1.getTagVisibility)({
17
- items: tagDocs,
18
- isUnlisted: (item) => item.unlisted,
19
- });
20
- return {
21
- label: tag.label,
22
- docIds: tagVisibility.listedItems.map((item) => item.id),
23
- permalink: tag.permalink,
24
- unlisted: tagVisibility.unlisted,
25
- };
26
- });
27
- }
28
- exports.getVersionTags = getVersionTags;
@@ -1,20 +0,0 @@
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
-
8
- import {linkify} from './linkify';
9
- import type {DocsMarkdownOption} from '../types';
10
- import type {LoaderContext} from 'webpack';
11
-
12
- export default function markdownLoader(
13
- this: LoaderContext<DocsMarkdownOption>,
14
- source: string,
15
- ): void {
16
- const fileString = source;
17
- const callback = this.async();
18
- const options = this.getOptions();
19
- return callback(null, linkify(fileString, this.resourcePath, options));
20
- }