@docusaurus/plugin-content-docs 3.3.2 → 3.4.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.
- package/lib/docs.d.ts +2 -0
- package/lib/docs.js +9 -2
- package/lib/index.js +82 -53
- package/lib/options.js +9 -0
- package/lib/props.js +2 -0
- package/lib/routes.js +21 -4
- package/lib/types.d.ts +3 -13
- package/lib/versions/index.d.ts +1 -0
- package/lib/versions/index.js +9 -1
- package/package.json +10 -10
- package/src/docs.ts +14 -2
- package/src/index.ts +114 -73
- package/src/options.ts +9 -0
- package/src/plugin-content-docs.d.ts +4 -3
- package/src/props.ts +2 -0
- package/src/routes.ts +23 -4
- package/src/types.ts +2 -16
- package/src/versions/index.ts +18 -1
- package/lib/markdown/index.d.ts +0 -9
- package/lib/markdown/index.js +0 -16
- package/lib/markdown/linkify.d.ts +0 -8
- package/lib/markdown/linkify.js +0 -34
- package/lib/tags.d.ts +0 -10
- package/lib/tags.js +0 -28
- package/src/markdown/index.ts +0 -20
- package/src/markdown/linkify.ts +0 -47
- package/src/tags.ts +0 -27
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
|
|
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
|
|
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,
|
|
@@ -160,57 +191,49 @@ async function pluginContentDocs(context, options) {
|
|
|
160
191
|
},
|
|
161
192
|
configureWebpack(_config, isServer, utils, content) {
|
|
162
193
|
const { rehypePlugins, remarkPlugins, beforeDefaultRehypePlugins, beforeDefaultRemarkPlugins, } = options;
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
194
|
+
const contentDirs = versionsMetadata
|
|
195
|
+
.flatMap(utils_1.getContentPathList)
|
|
196
|
+
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
|
197
|
+
.map(utils_1.addTrailingPathSeparator);
|
|
198
|
+
function createMDXLoader() {
|
|
199
|
+
const loaderOptions = {
|
|
200
|
+
admonitions: options.admonitions,
|
|
201
|
+
remarkPlugins,
|
|
202
|
+
rehypePlugins,
|
|
203
|
+
beforeDefaultRehypePlugins,
|
|
204
|
+
beforeDefaultRemarkPlugins,
|
|
205
|
+
staticDirs: siteConfig.staticDirectories.map((dir) => path_1.default.resolve(siteDir, dir)),
|
|
206
|
+
siteDir,
|
|
207
|
+
isMDXPartial: (0, utils_1.createAbsoluteFilePathMatcher)(options.exclude, contentDirs),
|
|
208
|
+
metadataPath: (mdxPath) => {
|
|
209
|
+
// Note that metadataPath must be the same/in-sync as
|
|
210
|
+
// the path from createData for each MDX.
|
|
211
|
+
const aliasedPath = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
|
|
212
|
+
return path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedPath)}.json`);
|
|
213
|
+
},
|
|
214
|
+
// Assets allow to convert some relative images paths to
|
|
215
|
+
// require(...) calls
|
|
216
|
+
createAssets: ({ frontMatter }) => ({
|
|
217
|
+
image: frontMatter.image,
|
|
218
|
+
}),
|
|
219
|
+
markdownConfig: siteConfig.markdown,
|
|
220
|
+
resolveMarkdownLink: ({ linkPathname, sourceFilePath }) => {
|
|
221
|
+
const version = (0, versions_1.getVersionFromSourceFilePath)(sourceFilePath, content.loadedVersions);
|
|
222
|
+
const permalink = (0, utils_1.resolveMarkdownLinkPathname)(linkPathname, {
|
|
223
|
+
sourceFilePath,
|
|
224
|
+
sourceToPermalink: sourceToPermalinkHelper.get(),
|
|
225
|
+
siteDir,
|
|
226
|
+
contentPaths: version,
|
|
227
|
+
});
|
|
228
|
+
if (permalink === null) {
|
|
229
|
+
logger_1.default.report(siteConfig.onBrokenMarkdownLinks) `Docs markdown link couldn't be resolved: (url=${linkPathname}) in source file path=${sourceFilePath} for version number=${version.versionName}`;
|
|
230
|
+
}
|
|
231
|
+
return permalink;
|
|
232
|
+
},
|
|
233
|
+
};
|
|
180
234
|
return {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
use: [
|
|
184
|
-
{
|
|
185
|
-
loader: require.resolve('@docusaurus/mdx-loader'),
|
|
186
|
-
options: {
|
|
187
|
-
admonitions: options.admonitions,
|
|
188
|
-
remarkPlugins,
|
|
189
|
-
rehypePlugins,
|
|
190
|
-
beforeDefaultRehypePlugins,
|
|
191
|
-
beforeDefaultRemarkPlugins,
|
|
192
|
-
staticDirs: siteConfig.staticDirectories.map((dir) => path_1.default.resolve(siteDir, dir)),
|
|
193
|
-
siteDir,
|
|
194
|
-
isMDXPartial: (0, utils_1.createAbsoluteFilePathMatcher)(options.exclude, contentDirs),
|
|
195
|
-
metadataPath: (mdxPath) => {
|
|
196
|
-
// Note that metadataPath must be the same/in-sync as
|
|
197
|
-
// the path from createData for each MDX.
|
|
198
|
-
const aliasedPath = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
|
|
199
|
-
return path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedPath)}.json`);
|
|
200
|
-
},
|
|
201
|
-
// Assets allow to convert some relative images paths to
|
|
202
|
-
// require(...) calls
|
|
203
|
-
createAssets: ({ frontMatter, }) => ({
|
|
204
|
-
image: frontMatter.image,
|
|
205
|
-
}),
|
|
206
|
-
markdownConfig: siteConfig.markdown,
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
loader: path_1.default.resolve(__dirname, './markdown/index.js'),
|
|
211
|
-
options: docsMarkdownOptions,
|
|
212
|
-
},
|
|
213
|
-
].filter(Boolean),
|
|
235
|
+
loader: require.resolve('@docusaurus/mdx-loader'),
|
|
236
|
+
options: loaderOptions,
|
|
214
237
|
};
|
|
215
238
|
}
|
|
216
239
|
return {
|
|
@@ -225,7 +248,13 @@ async function pluginContentDocs(context, options) {
|
|
|
225
248
|
},
|
|
226
249
|
},
|
|
227
250
|
module: {
|
|
228
|
-
rules: [
|
|
251
|
+
rules: [
|
|
252
|
+
{
|
|
253
|
+
test: /\.mdx?$/i,
|
|
254
|
+
include: contentDirs,
|
|
255
|
+
use: [createMDXLoader()],
|
|
256
|
+
},
|
|
257
|
+
],
|
|
229
258
|
},
|
|
230
259
|
};
|
|
231
260
|
},
|
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 =
|
|
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 (
|
|
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
|
|
107
|
+
tags,
|
|
91
108
|
},
|
|
92
109
|
};
|
|
93
110
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
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 {
|
|
9
|
-
import type {
|
|
8
|
+
import type { TagMetadata } from '@docusaurus/utils';
|
|
9
|
+
import type { LoadedVersion, CategoryGeneratedIndexMetadata } from '@docusaurus/plugin-content-docs';
|
|
10
10
|
import type { SidebarsUtils } from './sidebars/utils';
|
|
11
11
|
export type DocFile = {
|
|
12
12
|
contentPath: string;
|
|
@@ -14,10 +14,7 @@ export type DocFile = {
|
|
|
14
14
|
source: string;
|
|
15
15
|
content: string;
|
|
16
16
|
};
|
|
17
|
-
export type
|
|
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;
|
|
@@ -29,10 +26,3 @@ export type FullVersion = LoadedVersion & {
|
|
|
29
26
|
sidebarsUtils: SidebarsUtils;
|
|
30
27
|
categoryGeneratedIndices: CategoryGeneratedIndexMetadata[];
|
|
31
28
|
};
|
|
32
|
-
export type DocBrokenMarkdownLink = BrokenMarkdownLink<VersionMetadata>;
|
|
33
|
-
export type DocsMarkdownOption = {
|
|
34
|
-
versionsMetadata: VersionMetadata[];
|
|
35
|
-
siteDir: string;
|
|
36
|
-
sourceToPermalink: SourceToPermalink;
|
|
37
|
-
onBrokenMarkdownLink: (brokenMarkdownLink: DocBrokenMarkdownLink) => void;
|
|
38
|
-
};
|
package/lib/versions/index.d.ts
CHANGED
|
@@ -38,3 +38,4 @@ export declare function readVersionsMetadata({ context, options, }: {
|
|
|
38
38
|
options: PluginOptions;
|
|
39
39
|
}): Promise<VersionMetadata[]>;
|
|
40
40
|
export declare function toFullVersion(version: LoadedVersion): FullVersion;
|
|
41
|
+
export declare function getVersionFromSourceFilePath(filePath: string, versionsMetadata: VersionMetadata[]): VersionMetadata;
|
package/lib/versions/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.toFullVersion = exports.readVersionsMetadata = exports.filterVersions = exports.getVersionNoIndex = exports.getVersionBadge = exports.getVersionBanner = exports.getDefaultVersionBanner = void 0;
|
|
9
|
+
exports.getVersionFromSourceFilePath = exports.toFullVersion = exports.readVersionsMetadata = exports.filterVersions = exports.getVersionNoIndex = exports.getVersionBadge = exports.getVersionBanner = exports.getDefaultVersionBanner = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
12
|
const utils_1 = require("@docusaurus/utils");
|
|
@@ -171,3 +171,11 @@ function toFullVersion(version) {
|
|
|
171
171
|
};
|
|
172
172
|
}
|
|
173
173
|
exports.toFullVersion = toFullVersion;
|
|
174
|
+
function getVersionFromSourceFilePath(filePath, versionsMetadata) {
|
|
175
|
+
const versionFound = versionsMetadata.find((version) => (0, utils_1.getContentPathList)(version).some((docsDirPath) => filePath.startsWith(docsDirPath)));
|
|
176
|
+
if (!versionFound) {
|
|
177
|
+
throw new Error(`Unexpected error: file at "${filePath}" does not belong to any docs version!`);
|
|
178
|
+
}
|
|
179
|
+
return versionFound;
|
|
180
|
+
}
|
|
181
|
+
exports.getVersionFromSourceFilePath = getVersionFromSourceFilePath;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/plugin-content-docs",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
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": "3.
|
|
39
|
-
"@docusaurus/logger": "3.
|
|
40
|
-
"@docusaurus/mdx-loader": "3.
|
|
41
|
-
"@docusaurus/module-type-aliases": "3.
|
|
42
|
-
"@docusaurus/types": "3.
|
|
43
|
-
"@docusaurus/utils": "3.
|
|
44
|
-
"@docusaurus/utils-common": "3.
|
|
45
|
-
"@docusaurus/utils-validation": "3.
|
|
38
|
+
"@docusaurus/core": "3.4.0",
|
|
39
|
+
"@docusaurus/logger": "3.4.0",
|
|
40
|
+
"@docusaurus/mdx-loader": "3.4.0",
|
|
41
|
+
"@docusaurus/module-type-aliases": "3.4.0",
|
|
42
|
+
"@docusaurus/types": "3.4.0",
|
|
43
|
+
"@docusaurus/utils": "3.4.0",
|
|
44
|
+
"@docusaurus/utils-common": "3.4.0",
|
|
45
|
+
"@docusaurus/utils-validation": "3.4.0",
|
|
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": "
|
|
69
|
+
"gitHead": "49e9a2143274a8dd795659b417b470bc42abbd6e"
|
|
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
|
|
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
|
@@ -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 {
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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({
|
|
@@ -251,72 +297,61 @@ export default async function pluginContentDocs(
|
|
|
251
297
|
beforeDefaultRemarkPlugins,
|
|
252
298
|
} = options;
|
|
253
299
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
)
|
|
269
|
-
|
|
270
|
-
|
|
300
|
+
const contentDirs = versionsMetadata
|
|
301
|
+
.flatMap(getContentPathList)
|
|
302
|
+
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
|
303
|
+
.map(addTrailingPathSeparator);
|
|
304
|
+
|
|
305
|
+
function createMDXLoader(): RuleSetUseItem {
|
|
306
|
+
const loaderOptions: MDXLoaderOptions = {
|
|
307
|
+
admonitions: options.admonitions,
|
|
308
|
+
remarkPlugins,
|
|
309
|
+
rehypePlugins,
|
|
310
|
+
beforeDefaultRehypePlugins,
|
|
311
|
+
beforeDefaultRemarkPlugins,
|
|
312
|
+
staticDirs: siteConfig.staticDirectories.map((dir) =>
|
|
313
|
+
path.resolve(siteDir, dir),
|
|
314
|
+
),
|
|
315
|
+
siteDir,
|
|
316
|
+
isMDXPartial: createAbsoluteFilePathMatcher(
|
|
317
|
+
options.exclude,
|
|
318
|
+
contentDirs,
|
|
319
|
+
),
|
|
320
|
+
metadataPath: (mdxPath: string) => {
|
|
321
|
+
// Note that metadataPath must be the same/in-sync as
|
|
322
|
+
// the path from createData for each MDX.
|
|
323
|
+
const aliasedPath = aliasedSitePath(mdxPath, siteDir);
|
|
324
|
+
return path.join(dataDir, `${docuHash(aliasedPath)}.json`);
|
|
325
|
+
},
|
|
326
|
+
// Assets allow to convert some relative images paths to
|
|
327
|
+
// require(...) calls
|
|
328
|
+
createAssets: ({frontMatter}: {frontMatter: DocFrontMatter}) => ({
|
|
329
|
+
image: frontMatter.image,
|
|
330
|
+
}),
|
|
331
|
+
markdownConfig: siteConfig.markdown,
|
|
332
|
+
resolveMarkdownLink: ({linkPathname, sourceFilePath}) => {
|
|
333
|
+
const version = getVersionFromSourceFilePath(
|
|
334
|
+
sourceFilePath,
|
|
335
|
+
content.loadedVersions,
|
|
336
|
+
);
|
|
337
|
+
const permalink = resolveMarkdownLinkPathname(linkPathname, {
|
|
338
|
+
sourceFilePath,
|
|
339
|
+
sourceToPermalink: sourceToPermalinkHelper.get(),
|
|
340
|
+
siteDir,
|
|
341
|
+
contentPaths: version,
|
|
342
|
+
});
|
|
343
|
+
if (permalink === null) {
|
|
344
|
+
logger.report(
|
|
345
|
+
siteConfig.onBrokenMarkdownLinks,
|
|
346
|
+
)`Docs markdown link couldn't be resolved: (url=${linkPathname}) in source file path=${sourceFilePath} for version number=${version.versionName}`;
|
|
347
|
+
}
|
|
348
|
+
return permalink;
|
|
349
|
+
},
|
|
350
|
+
};
|
|
271
351
|
|
|
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
352
|
return {
|
|
278
|
-
|
|
279
|
-
|
|
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),
|
|
353
|
+
loader: require.resolve('@docusaurus/mdx-loader'),
|
|
354
|
+
options: loaderOptions,
|
|
320
355
|
};
|
|
321
356
|
}
|
|
322
357
|
|
|
@@ -333,7 +368,13 @@ export default async function pluginContentDocs(
|
|
|
333
368
|
},
|
|
334
369
|
},
|
|
335
370
|
module: {
|
|
336
|
-
rules: [
|
|
371
|
+
rules: [
|
|
372
|
+
{
|
|
373
|
+
test: /\.mdx?$/i,
|
|
374
|
+
include: contentDirs,
|
|
375
|
+
use: [createMDXLoader()],
|
|
376
|
+
},
|
|
377
|
+
],
|
|
337
378
|
},
|
|
338
379
|
};
|
|
339
380
|
},
|
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:
|
|
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 (
|
|
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
|
|
151
|
+
tags,
|
|
133
152
|
},
|
|
134
153
|
};
|
|
135
154
|
}
|
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 {
|
|
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
|
|
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
|
-
};
|
package/src/versions/index.ts
CHANGED
|
@@ -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
|
+
}
|
package/lib/markdown/index.d.ts
DELETED
|
@@ -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;
|
package/lib/markdown/index.js
DELETED
|
@@ -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,8 +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
|
-
export declare function linkify(fileString: string, filePath: string, options: DocsMarkdownOption): string;
|
package/lib/markdown/linkify.js
DELETED
|
@@ -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;
|
package/src/markdown/index.ts
DELETED
|
@@ -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
|
-
}
|
package/src/markdown/linkify.ts
DELETED
|
@@ -1,47 +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 {replaceMarkdownLinks, getContentPathList} from '@docusaurus/utils';
|
|
9
|
-
import type {DocsMarkdownOption} from '../types';
|
|
10
|
-
|
|
11
|
-
function getVersion(filePath: string, options: DocsMarkdownOption) {
|
|
12
|
-
const versionFound = options.versionsMetadata.find((version) =>
|
|
13
|
-
getContentPathList(version).some((docsDirPath) =>
|
|
14
|
-
filePath.startsWith(docsDirPath),
|
|
15
|
-
),
|
|
16
|
-
);
|
|
17
|
-
// At this point, this should never happen, because the MDX loaders' paths are
|
|
18
|
-
// literally using the version content paths; but if we allow sourcing content
|
|
19
|
-
// from outside the docs directory (through the `include` option, for example;
|
|
20
|
-
// is there a compelling use-case?), this would actually be testable
|
|
21
|
-
if (!versionFound) {
|
|
22
|
-
throw new Error(
|
|
23
|
-
`Unexpected error: Markdown file at "${filePath}" does not belong to any docs version!`,
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
return versionFound;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function linkify(
|
|
30
|
-
fileString: string,
|
|
31
|
-
filePath: string,
|
|
32
|
-
options: DocsMarkdownOption,
|
|
33
|
-
): string {
|
|
34
|
-
const {siteDir, sourceToPermalink, onBrokenMarkdownLink} = options;
|
|
35
|
-
|
|
36
|
-
const {newContent, brokenMarkdownLinks} = replaceMarkdownLinks({
|
|
37
|
-
siteDir,
|
|
38
|
-
fileString,
|
|
39
|
-
filePath,
|
|
40
|
-
contentPaths: getVersion(filePath, options),
|
|
41
|
-
sourceToPermalink,
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
brokenMarkdownLinks.forEach((l) => onBrokenMarkdownLink(l));
|
|
45
|
-
|
|
46
|
-
return newContent;
|
|
47
|
-
}
|
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
|
-
}
|