@docusaurus/plugin-content-docs 0.0.0-5961 → 0.0.0-5963

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.
package/lib/docs.d.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  /// <reference path="../src/plugin-content-docs.d.ts" />
8
+ import type { TagsFile } from '@docusaurus/utils';
8
9
  import type { MetadataOptions, PluginOptions, CategoryIndexMatcher, DocMetadataBase, VersionMetadata, LoadedVersion } from '@docusaurus/plugin-content-docs';
9
10
  import type { LoadContext } from '@docusaurus/types';
10
11
  import type { SidebarsUtils } from './sidebars/utils';
@@ -18,6 +19,7 @@ export declare function processDocMetadata(args: {
18
19
  context: LoadContext;
19
20
  options: MetadataOptions;
20
21
  env: DocEnv;
22
+ tagsFile: TagsFile | null;
21
23
  }): Promise<DocMetadataBase>;
22
24
  export declare function addDocNavigation({ docs, sidebarsUtils, }: {
23
25
  docs: DocMetadataBase[];
package/lib/docs.js CHANGED
@@ -31,7 +31,7 @@ async function readVersionDocs(versionMetadata, options) {
31
31
  return Promise.all(sources.map((source) => readDocFile(versionMetadata, source)));
32
32
  }
33
33
  exports.readVersionDocs = readVersionDocs;
34
- async function doProcessDocMetadata({ docFile, versionMetadata, context, options, env, }) {
34
+ async function doProcessDocMetadata({ docFile, versionMetadata, context, options, env, tagsFile, }) {
35
35
  const { source, content, contentPath, filePath } = docFile;
36
36
  const { siteDir, siteConfig: { markdown: { parseFrontMatter }, }, } = context;
37
37
  const { frontMatter: unsafeFrontMatter, contentTitle, excerpt, } = await (0, utils_1.parseMarkdownFile)({
@@ -108,6 +108,13 @@ async function doProcessDocMetadata({ docFile, versionMetadata, context, options
108
108
  }
109
109
  const draft = (0, utils_1.isDraft)({ env, frontMatter });
110
110
  const unlisted = (0, utils_1.isUnlisted)({ env, frontMatter });
111
+ const tags = (0, utils_1.normalizeTags)({
112
+ options,
113
+ source,
114
+ frontMatterTags: frontMatter.tags,
115
+ tagsBaseRoutePath: versionMetadata.tagsPath,
116
+ tagsFile,
117
+ });
111
118
  // Assign all of object properties during instantiation (if possible) for
112
119
  // NodeJS optimization.
113
120
  // Adding properties to object after instantiation will cause hidden
@@ -123,7 +130,7 @@ async function doProcessDocMetadata({ docFile, versionMetadata, context, options
123
130
  draft,
124
131
  unlisted,
125
132
  editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(),
126
- tags: (0, utils_1.normalizeFrontMatterTags)(versionMetadata.tagsPath, frontMatter.tags),
133
+ tags,
127
134
  version: versionMetadata.versionName,
128
135
  lastUpdatedBy: lastUpdate.lastUpdatedBy,
129
136
  lastUpdatedAt: lastUpdate.lastUpdatedAt,
package/lib/index.js CHANGED
@@ -12,6 +12,7 @@ const path_1 = tslib_1.__importDefault(require("path"));
12
12
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
13
13
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
14
14
  const utils_1 = require("@docusaurus/utils");
15
+ const utils_validation_1 = require("@docusaurus/utils-validation");
15
16
  const sidebars_1 = require("./sidebars");
16
17
  const generator_1 = require("./sidebars/generator");
17
18
  const docs_1 = require("./docs");
@@ -22,6 +23,25 @@ const globalData_1 = require("./globalData");
22
23
  const translations_1 = require("./translations");
23
24
  const routes_1 = require("./routes");
24
25
  const utils_2 = require("./sidebars/utils");
26
+ // TODO this is bad, we should have a better way to do this (new lifecycle?)
27
+ // The source to permalink is currently a mutable map passed to the mdx loader
28
+ // for link resolution
29
+ // see https://github.com/facebook/docusaurus/pull/10185
30
+ function createSourceToPermalinkHelper() {
31
+ const sourceToPermalink = new Map();
32
+ function computeSourceToPermalink(content) {
33
+ const allDocs = content.loadedVersions.flatMap((v) => v.docs);
34
+ return new Map(allDocs.map(({ source, permalink }) => [source, permalink]));
35
+ }
36
+ // Mutable map update :/
37
+ function update(content) {
38
+ sourceToPermalink.clear();
39
+ computeSourceToPermalink(content).forEach((value, key) => {
40
+ sourceToPermalink.set(key, value);
41
+ });
42
+ }
43
+ return { get: () => sourceToPermalink, update };
44
+ }
25
45
  async function pluginContentDocs(context, options) {
26
46
  const { siteDir, generatedFilesDir, baseUrl, siteConfig } = context;
27
47
  // Mutate options to resolve sidebar path according to siteDir
@@ -36,6 +56,7 @@ async function pluginContentDocs(context, options) {
36
56
  const aliasedSource = (source) => `~docs/${(0, utils_1.posixPath)(path_1.default.relative(pluginDataDirRoot, source))}`;
37
57
  // TODO env should be injected into all plugins
38
58
  const env = process.env.NODE_ENV;
59
+ const sourceToPermalinkHelper = createSourceToPermalinkHelper();
39
60
  return {
40
61
  name: 'docusaurus-plugin-content-docs',
41
62
  extendCli(cli) {
@@ -61,6 +82,10 @@ async function pluginContentDocs(context, options) {
61
82
  function getVersionPathsToWatch(version) {
62
83
  const result = [
63
84
  ...options.include.flatMap((pattern) => (0, utils_1.getContentPathList)(version).map((docsDirPath) => `${docsDirPath}/${pattern}`)),
85
+ ...(0, utils_validation_1.getTagsFilePathsToWatch)({
86
+ contentPaths: version,
87
+ tags: options.tags,
88
+ }),
64
89
  `${version.contentPath}/**/${generator_1.CategoryMetadataFilenamePattern}`,
65
90
  ];
66
91
  if (typeof version.sidebarFilePath === 'string') {
@@ -71,7 +96,7 @@ async function pluginContentDocs(context, options) {
71
96
  return versionsMetadata.flatMap(getVersionPathsToWatch);
72
97
  },
73
98
  async loadContent() {
74
- async function loadVersionDocsBase(versionMetadata) {
99
+ async function loadVersionDocsBase(versionMetadata, tagsFile) {
75
100
  const docFiles = await (0, docs_1.readVersionDocs)(versionMetadata, options);
76
101
  if (docFiles.length === 0) {
77
102
  throw new Error(`Docs version "${versionMetadata.versionName}" has no docs! At least one doc should exist at "${path_1.default.relative(siteDir, versionMetadata.contentPath)}".`);
@@ -83,12 +108,17 @@ async function pluginContentDocs(context, options) {
83
108
  context,
84
109
  options,
85
110
  env,
111
+ tagsFile,
86
112
  });
87
113
  }
88
114
  return Promise.all(docFiles.map(processVersionDoc));
89
115
  }
90
116
  async function doLoadVersion(versionMetadata) {
91
- const docsBase = await loadVersionDocsBase(versionMetadata);
117
+ const tagsFile = await (0, utils_validation_1.getTagsFile)({
118
+ contentPaths: versionMetadata,
119
+ tags: options.tags,
120
+ });
121
+ const docsBase = await loadVersionDocsBase(versionMetadata, tagsFile);
92
122
  // TODO we only ever need draftIds in further code, not full draft items
93
123
  // To simplify and prevent mistakes, avoid exposing draft
94
124
  // replace draft=>draftIds in content loaded
@@ -144,6 +174,7 @@ async function pluginContentDocs(context, options) {
144
174
  return (0, translations_1.translateLoadedContent)(content, translationFiles);
145
175
  },
146
176
  async contentLoaded({ content, actions }) {
177
+ sourceToPermalinkHelper.update(content);
147
178
  const versions = content.loadedVersions.map(versions_1.toFullVersion);
148
179
  await (0, routes_1.createAllRoutes)({
149
180
  baseUrl,
@@ -164,13 +195,6 @@ async function pluginContentDocs(context, options) {
164
195
  .flatMap(utils_1.getContentPathList)
165
196
  // Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
166
197
  .map(utils_1.addTrailingPathSeparator);
167
- // TODO this does not re-run when content gets updated in dev!
168
- // it's probably better to restore a mutable cache in the plugin
169
- function getSourceToPermalink() {
170
- const allDocs = content.loadedVersions.flatMap((v) => v.docs);
171
- return Object.fromEntries(allDocs.map(({ source, permalink }) => [source, permalink]));
172
- }
173
- const sourceToPermalink = getSourceToPermalink();
174
198
  function createMDXLoader() {
175
199
  const loaderOptions = {
176
200
  admonitions: options.admonitions,
@@ -197,7 +221,7 @@ async function pluginContentDocs(context, options) {
197
221
  const version = (0, versions_1.getVersionFromSourceFilePath)(sourceFilePath, content.loadedVersions);
198
222
  const permalink = (0, utils_1.resolveMarkdownLinkPathname)(linkPathname, {
199
223
  sourceFilePath,
200
- sourceToPermalink,
224
+ sourceToPermalink: sourceToPermalinkHelper.get(),
201
225
  siteDir,
202
226
  contentPaths: version,
203
227
  });
package/lib/options.js CHANGED
@@ -44,6 +44,8 @@ exports.DEFAULT_OPTIONS = {
44
44
  sidebarCollapsible: true,
45
45
  sidebarCollapsed: true,
46
46
  breadcrumbs: true,
47
+ onInlineTags: 'warn',
48
+ tags: undefined,
47
49
  };
48
50
  const VersionOptionsSchema = utils_validation_1.Joi.object({
49
51
  path: utils_validation_1.Joi.string().allow('').optional(),
@@ -100,6 +102,13 @@ const OptionsSchema = utils_validation_1.Joi.object({
100
102
  lastVersion: utils_validation_1.Joi.string().optional(),
101
103
  versions: VersionsOptionsSchema,
102
104
  breadcrumbs: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.breadcrumbs),
105
+ onInlineTags: utils_validation_1.Joi.string()
106
+ .equal('ignore', 'log', 'warn', 'throw')
107
+ .default(exports.DEFAULT_OPTIONS.onInlineTags),
108
+ tags: utils_validation_1.Joi.string()
109
+ .disallow('')
110
+ .allow(null, false)
111
+ .default(() => exports.DEFAULT_OPTIONS.tags),
103
112
  });
104
113
  function validateOptions({ validate, options: userOptions, }) {
105
114
  let options = userOptions;
package/lib/props.js CHANGED
@@ -134,6 +134,7 @@ function toTagDocListProp({ allTagsPath, tag, docs, }) {
134
134
  return {
135
135
  label: tag.label,
136
136
  permalink: tag.permalink,
137
+ description: tag.description,
137
138
  allTagsPath,
138
139
  count: tag.docIds.length,
139
140
  items: toDocListProp(),
@@ -147,6 +148,7 @@ function toTagsListTagsProp(versionTags) {
147
148
  .map((tagValue) => ({
148
149
  label: tagValue.label,
149
150
  permalink: tagValue.permalink,
151
+ description: tagValue.description,
150
152
  count: tagValue.docIds.length,
151
153
  }));
152
154
  }
package/lib/routes.js CHANGED
@@ -12,7 +12,6 @@ const lodash_1 = tslib_1.__importDefault(require("lodash"));
12
12
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
13
13
  const utils_1 = require("@docusaurus/utils");
14
14
  const props_1 = require("./props");
15
- const tags_1 = require("./tags");
16
15
  function createDocRouteMetadata(docMeta) {
17
16
  return {
18
17
  sourceFilePath: (0, utils_1.aliasedSitePathToRelativePath)(docMeta.source),
@@ -74,12 +73,30 @@ async function buildVersionSidebarRoute(param) {
74
73
  routes: subRoutes,
75
74
  };
76
75
  }
76
+ function getVersionTags(docs) {
77
+ const groups = (0, utils_1.groupTaggedItems)(docs, (doc) => doc.tags);
78
+ return lodash_1.default.mapValues(groups, ({ tag, items: tagDocs }) => {
79
+ const tagVisibility = (0, utils_1.getTagVisibility)({
80
+ items: tagDocs,
81
+ isUnlisted: (item) => item.unlisted,
82
+ });
83
+ return {
84
+ inline: tag.inline,
85
+ label: tag.label,
86
+ permalink: tag.permalink,
87
+ description: tag.description,
88
+ docIds: tagVisibility.listedItems.map((item) => item.id),
89
+ unlisted: tagVisibility.unlisted,
90
+ };
91
+ });
92
+ }
77
93
  async function buildVersionTagsRoutes(param) {
78
94
  const { version, options } = param;
79
- const versionTags = (0, tags_1.getVersionTags)(version.docs);
95
+ const versionTags = getVersionTags(version.docs);
80
96
  async function buildTagsListRoute() {
97
+ const tags = (0, props_1.toTagsListTagsProp)(versionTags);
81
98
  // Don't create a tags list page if there's no tag
82
- if (Object.keys(versionTags).length === 0) {
99
+ if (tags.length === 0) {
83
100
  return null;
84
101
  }
85
102
  return {
@@ -87,7 +104,7 @@ async function buildVersionTagsRoutes(param) {
87
104
  exact: true,
88
105
  component: options.docTagsListComponent,
89
106
  props: {
90
- tags: (0, props_1.toTagsListTagsProp)(versionTags),
107
+ tags,
91
108
  },
92
109
  };
93
110
  }
package/lib/types.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  /// <reference path="../src/plugin-content-docs.d.ts" />
8
- import type { Tag } from '@docusaurus/utils';
8
+ import type { TagMetadata } from '@docusaurus/utils';
9
9
  import type { LoadedVersion, CategoryGeneratedIndexMetadata } from '@docusaurus/plugin-content-docs';
10
10
  import type { SidebarsUtils } from './sidebars/utils';
11
11
  export type DocFile = {
@@ -14,10 +14,7 @@ export type DocFile = {
14
14
  source: string;
15
15
  content: string;
16
16
  };
17
- export type SourceToPermalink = {
18
- [source: string]: string;
19
- };
20
- export type VersionTag = Tag & {
17
+ export type VersionTag = TagMetadata & {
21
18
  /** All doc ids having this tag. */
22
19
  docIds: string[];
23
20
  unlisted: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docusaurus/plugin-content-docs",
3
- "version": "0.0.0-5961",
3
+ "version": "0.0.0-5963",
4
4
  "description": "Docs plugin for Docusaurus.",
5
5
  "main": "lib/index.js",
6
6
  "sideEffects": false,
@@ -35,14 +35,14 @@
35
35
  },
36
36
  "license": "MIT",
37
37
  "dependencies": {
38
- "@docusaurus/core": "0.0.0-5961",
39
- "@docusaurus/logger": "0.0.0-5961",
40
- "@docusaurus/mdx-loader": "0.0.0-5961",
41
- "@docusaurus/module-type-aliases": "0.0.0-5961",
42
- "@docusaurus/types": "0.0.0-5961",
43
- "@docusaurus/utils": "0.0.0-5961",
44
- "@docusaurus/utils-common": "0.0.0-5961",
45
- "@docusaurus/utils-validation": "0.0.0-5961",
38
+ "@docusaurus/core": "0.0.0-5963",
39
+ "@docusaurus/logger": "0.0.0-5963",
40
+ "@docusaurus/mdx-loader": "0.0.0-5963",
41
+ "@docusaurus/module-type-aliases": "0.0.0-5963",
42
+ "@docusaurus/types": "0.0.0-5963",
43
+ "@docusaurus/utils": "0.0.0-5963",
44
+ "@docusaurus/utils-common": "0.0.0-5963",
45
+ "@docusaurus/utils-validation": "0.0.0-5963",
46
46
  "@types/react-router-config": "^5.0.7",
47
47
  "combine-promises": "^1.1.0",
48
48
  "fs-extra": "^11.1.1",
@@ -66,5 +66,5 @@
66
66
  "engines": {
67
67
  "node": ">=18.0"
68
68
  },
69
- "gitHead": "ae17c4245467ae9c0c218dc375d4d059410f8622"
69
+ "gitHead": "e9090dc8a38a21043b0849887aa7d54d04c4af9f"
70
70
  }
package/src/docs.ts CHANGED
@@ -17,15 +17,16 @@ import {
17
17
  parseMarkdownFile,
18
18
  posixPath,
19
19
  Globby,
20
- normalizeFrontMatterTags,
21
20
  isUnlisted,
22
21
  isDraft,
23
22
  readLastUpdateData,
23
+ normalizeTags,
24
24
  } from '@docusaurus/utils';
25
25
  import {validateDocFrontMatter} from './frontMatter';
26
26
  import getSlug from './slug';
27
27
  import {stripPathNumberPrefixes} from './numberPrefix';
28
28
  import {toDocNavigationLink, toNavigationLink} from './sidebars/utils';
29
+ import type {TagsFile} from '@docusaurus/utils';
29
30
  import type {
30
31
  MetadataOptions,
31
32
  PluginOptions,
@@ -82,12 +83,14 @@ async function doProcessDocMetadata({
82
83
  context,
83
84
  options,
84
85
  env,
86
+ tagsFile,
85
87
  }: {
86
88
  docFile: DocFile;
87
89
  versionMetadata: VersionMetadata;
88
90
  context: LoadContext;
89
91
  options: MetadataOptions;
90
92
  env: DocEnv;
93
+ tagsFile: TagsFile | null;
91
94
  }): Promise<DocMetadataBase> {
92
95
  const {source, content, contentPath, filePath} = docFile;
93
96
  const {
@@ -206,6 +209,14 @@ async function doProcessDocMetadata({
206
209
  const draft = isDraft({env, frontMatter});
207
210
  const unlisted = isUnlisted({env, frontMatter});
208
211
 
212
+ const tags = normalizeTags({
213
+ options,
214
+ source,
215
+ frontMatterTags: frontMatter.tags,
216
+ tagsBaseRoutePath: versionMetadata.tagsPath,
217
+ tagsFile,
218
+ });
219
+
209
220
  // Assign all of object properties during instantiation (if possible) for
210
221
  // NodeJS optimization.
211
222
  // Adding properties to object after instantiation will cause hidden
@@ -221,7 +232,7 @@ async function doProcessDocMetadata({
221
232
  draft,
222
233
  unlisted,
223
234
  editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(),
224
- tags: normalizeFrontMatterTags(versionMetadata.tagsPath, frontMatter.tags),
235
+ tags,
225
236
  version: versionMetadata.versionName,
226
237
  lastUpdatedBy: lastUpdate.lastUpdatedBy,
227
238
  lastUpdatedAt: lastUpdate.lastUpdatedAt,
@@ -236,6 +247,7 @@ export async function processDocMetadata(args: {
236
247
  context: LoadContext;
237
248
  options: MetadataOptions;
238
249
  env: DocEnv;
250
+ tagsFile: TagsFile | null;
239
251
  }): Promise<DocMetadataBase> {
240
252
  try {
241
253
  return await doProcessDocMetadata(args);
package/src/index.ts CHANGED
@@ -19,7 +19,13 @@ import {
19
19
  createSlugger,
20
20
  resolveMarkdownLinkPathname,
21
21
  DEFAULT_PLUGIN_ID,
22
+ type SourceToPermalink,
23
+ type TagsFile,
22
24
  } from '@docusaurus/utils';
25
+ import {
26
+ getTagsFile,
27
+ getTagsFilePathsToWatch,
28
+ } from '@docusaurus/utils-validation';
23
29
  import {loadSidebars, resolveSidebarPathOption} from './sidebars';
24
30
  import {CategoryMetadataFilenamePattern} from './sidebars/generator';
25
31
  import {
@@ -54,9 +60,32 @@ import type {
54
60
  LoadedVersion,
55
61
  } from '@docusaurus/plugin-content-docs';
56
62
  import type {LoadContext, Plugin} from '@docusaurus/types';
57
- import type {SourceToPermalink, DocFile, FullVersion} from './types';
63
+ import type {DocFile, FullVersion} from './types';
58
64
  import type {RuleSetUseItem} from 'webpack';
59
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
+ }
88
+
60
89
  export default async function pluginContentDocs(
61
90
  context: LoadContext,
62
91
  options: PluginOptions,
@@ -83,6 +112,8 @@ export default async function pluginContentDocs(
83
112
  // TODO env should be injected into all plugins
84
113
  const env = process.env.NODE_ENV as DocEnv;
85
114
 
115
+ const sourceToPermalinkHelper = createSourceToPermalinkHelper();
116
+
86
117
  return {
87
118
  name: 'docusaurus-plugin-content-docs',
88
119
 
@@ -119,6 +150,10 @@ export default async function pluginContentDocs(
119
150
  (docsDirPath) => `${docsDirPath}/${pattern}`,
120
151
  ),
121
152
  ),
153
+ ...getTagsFilePathsToWatch({
154
+ contentPaths: version,
155
+ tags: options.tags,
156
+ }),
122
157
  `${version.contentPath}/**/${CategoryMetadataFilenamePattern}`,
123
158
  ];
124
159
  if (typeof version.sidebarFilePath === 'string') {
@@ -133,6 +168,7 @@ export default async function pluginContentDocs(
133
168
  async loadContent() {
134
169
  async function loadVersionDocsBase(
135
170
  versionMetadata: VersionMetadata,
171
+ tagsFile: TagsFile | null,
136
172
  ): Promise<DocMetadataBase[]> {
137
173
  const docFiles = await readVersionDocs(versionMetadata, options);
138
174
  if (docFiles.length === 0) {
@@ -152,6 +188,7 @@ export default async function pluginContentDocs(
152
188
  context,
153
189
  options,
154
190
  env,
191
+ tagsFile,
155
192
  });
156
193
  }
157
194
  return Promise.all(docFiles.map(processVersionDoc));
@@ -160,8 +197,14 @@ export default async function pluginContentDocs(
160
197
  async function doLoadVersion(
161
198
  versionMetadata: VersionMetadata,
162
199
  ): Promise<LoadedVersion> {
200
+ const tagsFile = await getTagsFile({
201
+ contentPaths: versionMetadata,
202
+ tags: options.tags,
203
+ });
204
+
163
205
  const docsBase: DocMetadataBase[] = await loadVersionDocsBase(
164
206
  versionMetadata,
207
+ tagsFile,
165
208
  );
166
209
 
167
210
  // TODO we only ever need draftIds in further code, not full draft items
@@ -227,6 +270,8 @@ export default async function pluginContentDocs(
227
270
  },
228
271
 
229
272
  async contentLoaded({content, actions}) {
273
+ sourceToPermalinkHelper.update(content);
274
+
230
275
  const versions: FullVersion[] = content.loadedVersions.map(toFullVersion);
231
276
 
232
277
  await createAllRoutes({
@@ -257,16 +302,6 @@ export default async function pluginContentDocs(
257
302
  // Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
258
303
  .map(addTrailingPathSeparator);
259
304
 
260
- // TODO this does not re-run when content gets updated in dev!
261
- // it's probably better to restore a mutable cache in the plugin
262
- function getSourceToPermalink(): SourceToPermalink {
263
- const allDocs = content.loadedVersions.flatMap((v) => v.docs);
264
- return Object.fromEntries(
265
- allDocs.map(({source, permalink}) => [source, permalink]),
266
- );
267
- }
268
- const sourceToPermalink = getSourceToPermalink();
269
-
270
305
  function createMDXLoader(): RuleSetUseItem {
271
306
  const loaderOptions: MDXLoaderOptions = {
272
307
  admonitions: options.admonitions,
@@ -301,7 +336,7 @@ export default async function pluginContentDocs(
301
336
  );
302
337
  const permalink = resolveMarkdownLinkPathname(linkPathname, {
303
338
  sourceFilePath,
304
- sourceToPermalink,
339
+ sourceToPermalink: sourceToPermalinkHelper.get(),
305
340
  siteDir,
306
341
  contentPaths: version,
307
342
  });
package/src/options.ts CHANGED
@@ -54,6 +54,8 @@ export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'> = {
54
54
  sidebarCollapsible: true,
55
55
  sidebarCollapsed: true,
56
56
  breadcrumbs: true,
57
+ onInlineTags: 'warn',
58
+ tags: undefined,
57
59
  };
58
60
 
59
61
  const VersionOptionsSchema = Joi.object({
@@ -140,6 +142,13 @@ const OptionsSchema = Joi.object<PluginOptions>({
140
142
  lastVersion: Joi.string().optional(),
141
143
  versions: VersionsOptionsSchema,
142
144
  breadcrumbs: Joi.bool().default(DEFAULT_OPTIONS.breadcrumbs),
145
+ onInlineTags: Joi.string()
146
+ .equal('ignore', 'log', 'warn', 'throw')
147
+ .default(DEFAULT_OPTIONS.onInlineTags),
148
+ tags: Joi.string()
149
+ .disallow('')
150
+ .allow(null, false)
151
+ .default(() => DEFAULT_OPTIONS.tags),
143
152
  });
144
153
 
145
154
  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
  }
package/src/types.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import type {Tag} from '@docusaurus/utils';
8
+ import type {TagMetadata} from '@docusaurus/utils';
9
9
  import type {
10
10
  LoadedVersion,
11
11
  CategoryGeneratedIndexMetadata,
@@ -19,11 +19,7 @@ export type DocFile = {
19
19
  content: string;
20
20
  };
21
21
 
22
- export type SourceToPermalink = {
23
- [source: string]: string;
24
- };
25
-
26
- export type VersionTag = Tag & {
22
+ export type VersionTag = TagMetadata & {
27
23
  /** All doc ids having this tag. */
28
24
  docIds: string[];
29
25
  unlisted: boolean;
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;
package/src/tags.ts DELETED
@@ -1,27 +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 _ from 'lodash';
9
- import {getTagVisibility, groupTaggedItems} from '@docusaurus/utils';
10
- import type {VersionTags} from './types';
11
- import type {DocMetadata} from '@docusaurus/plugin-content-docs';
12
-
13
- export function getVersionTags(docs: DocMetadata[]): VersionTags {
14
- const groups = groupTaggedItems(docs, (doc) => doc.tags);
15
- return _.mapValues(groups, ({tag, items: tagDocs}) => {
16
- const tagVisibility = 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
- }