@docusaurus/plugin-content-docs 0.0.0-4848 → 0.0.0-4851

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.
@@ -0,0 +1,113 @@
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 type {VersionsOptions} from '@docusaurus/plugin-content-docs';
10
+
11
+ export function validateVersionName(name: unknown): asserts name is string {
12
+ if (typeof name !== 'string') {
13
+ throw new Error(
14
+ `Versions should be strings. Found type "${typeof name}" for version "${name}".`,
15
+ );
16
+ }
17
+ if (!name.trim()) {
18
+ throw new Error(
19
+ `Invalid version name "${name}": version name must contain at least one non-whitespace character.`,
20
+ );
21
+ }
22
+ const errors: [RegExp, string][] = [
23
+ [/[/\\]/, 'should not include slash (/) or backslash (\\)'],
24
+ [/.{33,}/, 'cannot be longer than 32 characters'],
25
+ // eslint-disable-next-line no-control-regex
26
+ [/[<>:"|?*\x00-\x1F]/, 'should be a valid file path'],
27
+ [/^\.\.?$/, 'should not be "." or ".."'],
28
+ ];
29
+
30
+ errors.forEach(([pattern, message]) => {
31
+ if (pattern.test(name)) {
32
+ throw new Error(
33
+ `Invalid version name "${name}": version name ${message}.`,
34
+ );
35
+ }
36
+ });
37
+ }
38
+
39
+ export function validateVersionNames(
40
+ names: unknown,
41
+ ): asserts names is string[] {
42
+ if (!Array.isArray(names)) {
43
+ throw new Error(
44
+ `The versions file should contain an array of version names! Found content: ${JSON.stringify(
45
+ names,
46
+ )}`,
47
+ );
48
+ }
49
+
50
+ names.forEach(validateVersionName);
51
+ }
52
+
53
+ /**
54
+ * @throws Throws for one of the following invalid options:
55
+ * - `lastVersion` is non-existent
56
+ * - `versions` includes unknown keys
57
+ * - `onlyIncludeVersions` is empty, contains unknown names, or doesn't include
58
+ * `latestVersion` (if provided)
59
+ */
60
+ export function validateVersionsOptions(
61
+ availableVersionNames: string[],
62
+ options: VersionsOptions,
63
+ ): void {
64
+ const availableVersionNamesMsg = `Available version names are: ${availableVersionNames.join(
65
+ ', ',
66
+ )}`;
67
+ if (
68
+ options.lastVersion &&
69
+ !availableVersionNames.includes(options.lastVersion)
70
+ ) {
71
+ throw new Error(
72
+ `Docs option lastVersion: ${options.lastVersion} is invalid. ${availableVersionNamesMsg}`,
73
+ );
74
+ }
75
+ const unknownVersionConfigNames = _.difference(
76
+ Object.keys(options.versions),
77
+ availableVersionNames,
78
+ );
79
+ if (unknownVersionConfigNames.length > 0) {
80
+ throw new Error(
81
+ `Invalid docs option "versions": unknown versions (${unknownVersionConfigNames.join(
82
+ ',',
83
+ )}) found. ${availableVersionNamesMsg}`,
84
+ );
85
+ }
86
+
87
+ if (options.onlyIncludeVersions) {
88
+ if (options.onlyIncludeVersions.length === 0) {
89
+ throw new Error(
90
+ `Invalid docs option "onlyIncludeVersions": an empty array is not allowed, at least one version is needed.`,
91
+ );
92
+ }
93
+ const unknownOnlyIncludeVersionNames = _.difference(
94
+ options.onlyIncludeVersions,
95
+ availableVersionNames,
96
+ );
97
+ if (unknownOnlyIncludeVersionNames.length > 0) {
98
+ throw new Error(
99
+ `Invalid docs option "onlyIncludeVersions": unknown versions (${unknownOnlyIncludeVersionNames.join(
100
+ ',',
101
+ )}) found. ${availableVersionNamesMsg}`,
102
+ );
103
+ }
104
+ if (
105
+ options.lastVersion &&
106
+ !options.onlyIncludeVersions.includes(options.lastVersion)
107
+ ) {
108
+ throw new Error(
109
+ `Invalid docs option "lastVersion": if you use both the "onlyIncludeVersions" and "lastVersion" options, then "lastVersion" must be present in the provided "onlyIncludeVersions" array.`,
110
+ );
111
+ }
112
+ }
113
+ }
package/lib/versions.d.ts DELETED
@@ -1,45 +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 { PluginOptions, VersionBanner, VersionMetadata } from '@docusaurus/plugin-content-docs';
8
- import type { LoadContext } from '@docusaurus/types';
9
- export declare function getVersionedDocsDirPath(siteDir: string, pluginId: string): string;
10
- export declare function getVersionedSidebarsDirPath(siteDir: string, pluginId: string): string;
11
- export declare function getVersionsFilePath(siteDir: string, pluginId: string): string;
12
- export declare function readVersionsFile(siteDir: string, pluginId: string): Promise<string[] | null>;
13
- export declare function readVersionNames(siteDir: string, options: Pick<PluginOptions, 'id' | 'disableVersioning' | 'includeCurrentVersion'>): Promise<string[]>;
14
- export declare function getDocsDirPathLocalized({ siteDir, locale, pluginId, versionName, }: {
15
- siteDir: string;
16
- locale: string;
17
- pluginId: string;
18
- versionName: string;
19
- }): string;
20
- export declare function getDefaultVersionBanner({ versionName, versionNames, lastVersionName, }: {
21
- versionName: string;
22
- versionNames: string[];
23
- lastVersionName: string;
24
- }): VersionBanner | null;
25
- export declare function getVersionBanner({ versionName, versionNames, lastVersionName, options, }: {
26
- versionName: string;
27
- versionNames: string[];
28
- lastVersionName: string;
29
- options: Pick<PluginOptions, 'versions'>;
30
- }): VersionBanner | null;
31
- export declare function getVersionBadge({ versionName, versionNames, options, }: {
32
- versionName: string;
33
- versionNames: string[];
34
- options: Pick<PluginOptions, 'versions'>;
35
- }): boolean;
36
- /**
37
- * Filter versions according to provided options.
38
- * Note: we preserve the order in which versions are provided;
39
- * the order of the onlyIncludeVersions array does not matter
40
- */
41
- export declare function filterVersions(versionNamesUnfiltered: string[], options: Pick<PluginOptions, 'onlyIncludeVersions'>): string[];
42
- export declare function readVersionsMetadata({ context, options, }: {
43
- context: Pick<LoadContext, 'siteDir' | 'baseUrl' | 'i18n'>;
44
- options: Pick<PluginOptions, 'id' | 'path' | 'sidebarPath' | 'routeBasePath' | 'tagsBasePath' | 'includeCurrentVersion' | 'disableVersioning' | 'lastVersion' | 'versions' | 'onlyIncludeVersions' | 'editUrl' | 'editCurrentVersion'>;
45
- }): Promise<VersionMetadata[]>;
package/lib/versions.js DELETED
@@ -1,314 +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.readVersionsMetadata = exports.filterVersions = exports.getVersionBadge = exports.getVersionBanner = exports.getDefaultVersionBanner = exports.getDocsDirPathLocalized = exports.readVersionNames = exports.readVersionsFile = exports.getVersionsFilePath = exports.getVersionedSidebarsDirPath = exports.getVersionedDocsDirPath = void 0;
10
- const tslib_1 = require("tslib");
11
- const path_1 = tslib_1.__importDefault(require("path"));
12
- const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
13
- const constants_1 = require("./constants");
14
- const utils_1 = require("@docusaurus/utils");
15
- const lodash_1 = tslib_1.__importDefault(require("lodash"));
16
- const sidebars_1 = require("./sidebars");
17
- // retro-compatibility: no prefix for the default plugin id
18
- function addPluginIdPrefix(fileOrDir, pluginId) {
19
- return pluginId === utils_1.DEFAULT_PLUGIN_ID
20
- ? fileOrDir
21
- : `${pluginId}_${fileOrDir}`;
22
- }
23
- function getVersionedDocsDirPath(siteDir, pluginId) {
24
- return path_1.default.join(siteDir, addPluginIdPrefix(constants_1.VERSIONED_DOCS_DIR, pluginId));
25
- }
26
- exports.getVersionedDocsDirPath = getVersionedDocsDirPath;
27
- function getVersionedSidebarsDirPath(siteDir, pluginId) {
28
- return path_1.default.join(siteDir, addPluginIdPrefix(constants_1.VERSIONED_SIDEBARS_DIR, pluginId));
29
- }
30
- exports.getVersionedSidebarsDirPath = getVersionedSidebarsDirPath;
31
- function getVersionsFilePath(siteDir, pluginId) {
32
- return path_1.default.join(siteDir, addPluginIdPrefix(constants_1.VERSIONS_JSON_FILE, pluginId));
33
- }
34
- exports.getVersionsFilePath = getVersionsFilePath;
35
- function ensureValidVersionString(version) {
36
- if (typeof version !== 'string') {
37
- throw new Error(`Versions should be strings. Found type "${typeof version}" for version "${version}".`);
38
- }
39
- // Should we forbid versions with special chars like / ?
40
- if (version.trim().length === 0) {
41
- throw new Error(`Invalid version "${version}".`);
42
- }
43
- }
44
- function ensureValidVersionArray(versionArray) {
45
- if (!Array.isArray(versionArray)) {
46
- throw new Error(`The versions file should contain an array of version names! Found content: ${JSON.stringify(versionArray)}`);
47
- }
48
- versionArray.forEach(ensureValidVersionString);
49
- }
50
- async function readVersionsFile(siteDir, pluginId) {
51
- const versionsFilePath = getVersionsFilePath(siteDir, pluginId);
52
- if (await fs_extra_1.default.pathExists(versionsFilePath)) {
53
- const content = JSON.parse(await fs_extra_1.default.readFile(versionsFilePath, 'utf8'));
54
- ensureValidVersionArray(content);
55
- return content;
56
- }
57
- return null;
58
- }
59
- exports.readVersionsFile = readVersionsFile;
60
- async function readVersionNames(siteDir, options) {
61
- const versionFileContent = await readVersionsFile(siteDir, options.id);
62
- if (!versionFileContent && options.disableVersioning) {
63
- throw new Error(`Docs: using "disableVersioning: ${options.disableVersioning}" option on a non-versioned site does not make sense.`);
64
- }
65
- const versions = options.disableVersioning ? [] : versionFileContent ?? [];
66
- // We add the current version at the beginning, unless:
67
- // - user don't want to; or
68
- // - it's already been explicitly added to versions.json
69
- if (options.includeCurrentVersion &&
70
- !versions.includes(constants_1.CURRENT_VERSION_NAME)) {
71
- versions.unshift(constants_1.CURRENT_VERSION_NAME);
72
- }
73
- if (versions.length === 0) {
74
- throw new Error(`It is not possible to use docs without any version. Please check the configuration of these options: "includeCurrentVersion: ${options.includeCurrentVersion}", "disableVersioning: ${options.disableVersioning}".`);
75
- }
76
- return versions;
77
- }
78
- exports.readVersionNames = readVersionNames;
79
- function getDocsDirPathLocalized({ siteDir, locale, pluginId, versionName, }) {
80
- return (0, utils_1.getPluginI18nPath)({
81
- siteDir,
82
- locale,
83
- pluginName: 'docusaurus-plugin-content-docs',
84
- pluginId,
85
- subPaths: [
86
- versionName === constants_1.CURRENT_VERSION_NAME
87
- ? constants_1.CURRENT_VERSION_NAME
88
- : `version-${versionName}`,
89
- ],
90
- });
91
- }
92
- exports.getDocsDirPathLocalized = getDocsDirPathLocalized;
93
- function getVersionMetadataPaths({ versionName, context, options, }) {
94
- const isCurrentVersion = versionName === constants_1.CURRENT_VERSION_NAME;
95
- const contentPathLocalized = getDocsDirPathLocalized({
96
- siteDir: context.siteDir,
97
- locale: context.i18n.currentLocale,
98
- pluginId: options.id,
99
- versionName,
100
- });
101
- if (isCurrentVersion) {
102
- return {
103
- contentPath: path_1.default.resolve(context.siteDir, options.path),
104
- contentPathLocalized,
105
- sidebarFilePath: (0, sidebars_1.resolveSidebarPathOption)(context.siteDir, options.sidebarPath),
106
- };
107
- }
108
- return {
109
- contentPath: path_1.default.join(getVersionedDocsDirPath(context.siteDir, options.id), `version-${versionName}`),
110
- contentPathLocalized,
111
- sidebarFilePath: path_1.default.join(getVersionedSidebarsDirPath(context.siteDir, options.id), `version-${versionName}-sidebars.json`),
112
- };
113
- }
114
- function getVersionEditUrls({ contentPath, contentPathLocalized, context: { siteDir, i18n }, options: { id, path: currentVersionPath, editUrl: editUrlOption, editCurrentVersion, }, }) {
115
- // If the user is using the functional form of editUrl,
116
- // she has total freedom and we can't compute a "version edit url"
117
- if (!editUrlOption || typeof editUrlOption === 'function') {
118
- return { editUrl: undefined, editUrlLocalized: undefined };
119
- }
120
- const editDirPath = editCurrentVersion ? currentVersionPath : contentPath;
121
- const editDirPathLocalized = editCurrentVersion
122
- ? getDocsDirPathLocalized({
123
- siteDir,
124
- locale: i18n.currentLocale,
125
- versionName: constants_1.CURRENT_VERSION_NAME,
126
- pluginId: id,
127
- })
128
- : contentPathLocalized;
129
- const versionPathSegment = (0, utils_1.posixPath)(path_1.default.relative(siteDir, path_1.default.resolve(siteDir, editDirPath)));
130
- const versionPathSegmentLocalized = (0, utils_1.posixPath)(path_1.default.relative(siteDir, path_1.default.resolve(siteDir, editDirPathLocalized)));
131
- const editUrl = (0, utils_1.normalizeUrl)([editUrlOption, versionPathSegment]);
132
- const editUrlLocalized = (0, utils_1.normalizeUrl)([
133
- editUrlOption,
134
- versionPathSegmentLocalized,
135
- ]);
136
- return {
137
- editUrl,
138
- editUrlLocalized,
139
- };
140
- }
141
- function getDefaultVersionBanner({ versionName, versionNames, lastVersionName, }) {
142
- // Current version: good, no banner
143
- if (versionName === lastVersionName) {
144
- return null;
145
- }
146
- // Upcoming versions: unreleased banner
147
- if (versionNames.indexOf(versionName) < versionNames.indexOf(lastVersionName)) {
148
- return 'unreleased';
149
- }
150
- // Older versions: display unmaintained banner
151
- return 'unmaintained';
152
- }
153
- exports.getDefaultVersionBanner = getDefaultVersionBanner;
154
- function getVersionBanner({ versionName, versionNames, lastVersionName, options, }) {
155
- const versionBannerOption = options.versions[versionName]?.banner;
156
- if (versionBannerOption) {
157
- return versionBannerOption === 'none' ? null : versionBannerOption;
158
- }
159
- return getDefaultVersionBanner({
160
- versionName,
161
- versionNames,
162
- lastVersionName,
163
- });
164
- }
165
- exports.getVersionBanner = getVersionBanner;
166
- function getVersionBadge({ versionName, versionNames, options, }) {
167
- const versionBadgeOption = options.versions[versionName]?.badge;
168
- // If site is not versioned or only one version is included
169
- // we don't show the version badge by default
170
- // See https://github.com/facebook/docusaurus/issues/3362
171
- const versionBadgeDefault = versionNames.length !== 1;
172
- return versionBadgeOption ?? versionBadgeDefault;
173
- }
174
- exports.getVersionBadge = getVersionBadge;
175
- function getVersionClassName({ versionName, options, }) {
176
- const versionClassNameOption = options.versions[versionName]?.className;
177
- const versionClassNameDefault = `docs-version-${versionName}`;
178
- return versionClassNameOption ?? versionClassNameDefault;
179
- }
180
- function createVersionMetadata({ versionName, versionNames, lastVersionName, context, options, }) {
181
- const { sidebarFilePath, contentPath, contentPathLocalized } = getVersionMetadataPaths({ versionName, context, options });
182
- const isLast = versionName === lastVersionName;
183
- // retro-compatible values
184
- const defaultVersionLabel = versionName === constants_1.CURRENT_VERSION_NAME ? 'Next' : versionName;
185
- function getDefaultVersionPathPart() {
186
- if (isLast) {
187
- return '';
188
- }
189
- return versionName === constants_1.CURRENT_VERSION_NAME ? 'next' : versionName;
190
- }
191
- const defaultVersionPathPart = getDefaultVersionPathPart();
192
- const versionOptions = options.versions[versionName] ?? {};
193
- const label = versionOptions.label ?? defaultVersionLabel;
194
- const versionPathPart = versionOptions.path ?? defaultVersionPathPart;
195
- const routePath = (0, utils_1.normalizeUrl)([
196
- context.baseUrl,
197
- options.routeBasePath,
198
- versionPathPart,
199
- ]);
200
- const versionEditUrls = getVersionEditUrls({
201
- contentPath,
202
- contentPathLocalized,
203
- context,
204
- options,
205
- });
206
- const routePriority = versionPathPart === '' ? -1 : undefined;
207
- // the path that will be used to refer the docs tags
208
- // example below will be using /docs/tags
209
- const tagsPath = (0, utils_1.normalizeUrl)([routePath, options.tagsBasePath]);
210
- return {
211
- versionName,
212
- label,
213
- path: routePath,
214
- tagsPath,
215
- editUrl: versionEditUrls.editUrl,
216
- editUrlLocalized: versionEditUrls.editUrlLocalized,
217
- banner: getVersionBanner({
218
- versionName,
219
- versionNames,
220
- lastVersionName,
221
- options,
222
- }),
223
- badge: getVersionBadge({ versionName, versionNames, options }),
224
- className: getVersionClassName({ versionName, options }),
225
- isLast,
226
- routePriority,
227
- sidebarFilePath,
228
- contentPath,
229
- contentPathLocalized,
230
- };
231
- }
232
- async function checkVersionMetadataPaths({ versionMetadata, context, }) {
233
- const { versionName, contentPath, sidebarFilePath } = versionMetadata;
234
- const { siteDir } = context;
235
- const isCurrentVersion = versionName === constants_1.CURRENT_VERSION_NAME;
236
- if (!(await fs_extra_1.default.pathExists(contentPath))) {
237
- throw new Error(`The docs folder does not exist for version "${versionName}". A docs folder is expected to be found at ${path_1.default.relative(siteDir, contentPath)}.`);
238
- }
239
- // If the current version defines a path to a sidebar file that does not
240
- // exist, we throw! Note: for versioned sidebars, the file may not exist (as
241
- // we prefer to not create it rather than to create an empty file)
242
- // See https://github.com/facebook/docusaurus/issues/3366
243
- // See https://github.com/facebook/docusaurus/pull/4775
244
- if (isCurrentVersion &&
245
- typeof sidebarFilePath === 'string' &&
246
- !(await fs_extra_1.default.pathExists(sidebarFilePath))) {
247
- throw new Error(`The path to the sidebar file does not exist at "${path_1.default.relative(siteDir, sidebarFilePath)}".
248
- Please set the docs "sidebarPath" field in your config file to:
249
- - a sidebars path that exists
250
- - false: to disable the sidebar
251
- - undefined: for Docusaurus to generate it automatically`);
252
- }
253
- }
254
- // TODO for retrocompatibility with existing behavior
255
- // We should make this configurable
256
- // "last version" is not a very good concept nor api surface
257
- function getDefaultLastVersionName(versionNames) {
258
- if (versionNames.length === 1) {
259
- return versionNames[0];
260
- }
261
- return versionNames.filter((versionName) => versionName !== constants_1.CURRENT_VERSION_NAME)[0];
262
- }
263
- function checkVersionsOptions(availableVersionNames, options) {
264
- const availableVersionNamesMsg = `Available version names are: ${availableVersionNames.join(', ')}`;
265
- if (options.lastVersion &&
266
- !availableVersionNames.includes(options.lastVersion)) {
267
- throw new Error(`Docs option lastVersion: ${options.lastVersion} is invalid. ${availableVersionNamesMsg}`);
268
- }
269
- const unknownVersionConfigNames = lodash_1.default.difference(Object.keys(options.versions), availableVersionNames);
270
- if (unknownVersionConfigNames.length > 0) {
271
- throw new Error(`Invalid docs option "versions": unknown versions (${unknownVersionConfigNames.join(',')}) found. ${availableVersionNamesMsg}`);
272
- }
273
- if (options.onlyIncludeVersions) {
274
- if (options.onlyIncludeVersions.length === 0) {
275
- throw new Error(`Invalid docs option "onlyIncludeVersions": an empty array is not allowed, at least one version is needed.`);
276
- }
277
- const unknownOnlyIncludeVersionNames = lodash_1.default.difference(options.onlyIncludeVersions, availableVersionNames);
278
- if (unknownOnlyIncludeVersionNames.length > 0) {
279
- throw new Error(`Invalid docs option "onlyIncludeVersions": unknown versions (${unknownOnlyIncludeVersionNames.join(',')}) found. ${availableVersionNamesMsg}`);
280
- }
281
- if (options.lastVersion &&
282
- !options.onlyIncludeVersions.includes(options.lastVersion)) {
283
- throw new Error(`Invalid docs option "lastVersion": if you use both the "onlyIncludeVersions" and "lastVersion" options, then "lastVersion" must be present in the provided "onlyIncludeVersions" array.`);
284
- }
285
- }
286
- }
287
- /**
288
- * Filter versions according to provided options.
289
- * Note: we preserve the order in which versions are provided;
290
- * the order of the onlyIncludeVersions array does not matter
291
- */
292
- function filterVersions(versionNamesUnfiltered, options) {
293
- if (options.onlyIncludeVersions) {
294
- return versionNamesUnfiltered.filter((name) => options.onlyIncludeVersions.includes(name));
295
- }
296
- return versionNamesUnfiltered;
297
- }
298
- exports.filterVersions = filterVersions;
299
- async function readVersionsMetadata({ context, options, }) {
300
- const versionNamesUnfiltered = await readVersionNames(context.siteDir, options);
301
- checkVersionsOptions(versionNamesUnfiltered, options);
302
- const versionNames = filterVersions(versionNamesUnfiltered, options);
303
- const lastVersionName = options.lastVersion ?? getDefaultLastVersionName(versionNames);
304
- const versionsMetadata = versionNames.map((versionName) => createVersionMetadata({
305
- versionName,
306
- versionNames,
307
- lastVersionName,
308
- context,
309
- options,
310
- }));
311
- await Promise.all(versionsMetadata.map((versionMetadata) => checkVersionMetadataPaths({ versionMetadata, context })));
312
- return versionsMetadata;
313
- }
314
- exports.readVersionsMetadata = readVersionsMetadata;