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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/lib/categoryGeneratedIndex.d.ts +1 -1
  2. package/lib/categoryGeneratedIndex.js +4 -2
  3. package/lib/cli.d.ts +3 -2
  4. package/lib/cli.js +45 -35
  5. package/lib/client/docsClientUtils.d.ts +6 -5
  6. package/lib/client/docsClientUtils.js +8 -10
  7. package/lib/client/index.d.ts +9 -8
  8. package/lib/client/index.js +30 -33
  9. package/lib/constants.d.ts +4 -0
  10. package/lib/constants.js +4 -1
  11. package/lib/docs.d.ts +5 -3
  12. package/lib/docs.js +18 -13
  13. package/lib/frontMatter.d.ts +1 -1
  14. package/lib/frontMatter.js +3 -0
  15. package/lib/globalData.d.ts +2 -2
  16. package/lib/globalData.js +6 -6
  17. package/lib/index.d.ts +1 -2
  18. package/lib/index.js +31 -23
  19. package/lib/markdown/linkify.js +1 -2
  20. package/lib/props.d.ts +3 -3
  21. package/lib/props.js +7 -6
  22. package/lib/routes.d.ts +5 -4
  23. package/lib/routes.js +9 -23
  24. package/lib/server-export.d.ts +2 -1
  25. package/lib/server-export.js +3 -4
  26. package/lib/sidebars/generator.js +3 -3
  27. package/lib/sidebars/index.js +0 -2
  28. package/lib/sidebars/normalization.js +1 -1
  29. package/lib/sidebars/postProcessor.js +2 -2
  30. package/lib/sidebars/processor.js +14 -3
  31. package/lib/sidebars/types.d.ts +18 -14
  32. package/lib/sidebars/utils.d.ts +3 -3
  33. package/lib/slug.d.ts +1 -2
  34. package/lib/tags.d.ts +2 -1
  35. package/lib/tags.js +1 -1
  36. package/lib/translations.d.ts +3 -3
  37. package/lib/translations.js +3 -53
  38. package/lib/types.d.ts +8 -96
  39. package/lib/versions/files.d.ts +44 -0
  40. package/lib/versions/files.js +142 -0
  41. package/lib/versions/index.d.ts +36 -0
  42. package/lib/versions/index.js +155 -0
  43. package/lib/versions/validation.d.ts +17 -0
  44. package/lib/versions/validation.js +71 -0
  45. package/package.json +14 -12
  46. package/src/categoryGeneratedIndex.ts +8 -3
  47. package/src/cli.ts +62 -65
  48. package/src/client/docsClientUtils.ts +11 -13
  49. package/src/client/index.ts +41 -42
  50. package/src/constants.ts +4 -2
  51. package/src/docs.ts +41 -26
  52. package/src/frontMatter.ts +6 -3
  53. package/src/globalData.ts +10 -10
  54. package/src/index.ts +44 -38
  55. package/src/markdown/linkify.ts +2 -3
  56. package/src/plugin-content-docs.d.ts +447 -113
  57. package/src/props.ts +12 -9
  58. package/src/routes.ts +13 -39
  59. package/src/server-export.ts +1 -3
  60. package/src/sidebars/generator.ts +4 -4
  61. package/src/sidebars/index.ts +0 -2
  62. package/src/sidebars/normalization.ts +1 -1
  63. package/src/sidebars/postProcessor.ts +2 -2
  64. package/src/sidebars/processor.ts +24 -5
  65. package/src/sidebars/types.ts +20 -19
  66. package/src/sidebars/utils.ts +6 -3
  67. package/src/slug.ts +4 -2
  68. package/src/tags.ts +3 -2
  69. package/src/translations.ts +10 -61
  70. package/src/types.ts +13 -106
  71. package/src/versions/files.ts +220 -0
  72. package/src/versions/index.ts +247 -0
  73. package/src/versions/validation.ts +113 -0
  74. package/lib/versions.d.ts +0 -41
  75. package/lib/versions.js +0 -324
  76. package/src/versions.ts +0 -606
package/src/cli.ts CHANGED
@@ -7,18 +7,19 @@
7
7
 
8
8
  import {
9
9
  getVersionsFilePath,
10
- getVersionedDocsDirPath,
11
- getVersionedSidebarsDirPath,
12
- } from './versions';
10
+ getVersionDocsDirPath,
11
+ getVersionSidebarsPath,
12
+ getDocsDirPathLocalized,
13
+ } from './versions/files';
14
+ import {validateVersionName} from './versions/validation';
13
15
  import fs from 'fs-extra';
14
16
  import path from 'path';
15
- import type {
16
- PathOptions,
17
- SidebarOptions,
18
- } from '@docusaurus/plugin-content-docs';
19
- import {loadSidebarsFileUnsafe, resolveSidebarPathOption} from './sidebars';
17
+ import type {PluginOptions} from '@docusaurus/plugin-content-docs';
18
+ import {loadSidebarsFileUnsafe} from './sidebars';
19
+ import {CURRENT_VERSION_NAME} from './constants';
20
20
  import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
21
21
  import logger from '@docusaurus/logger';
22
+ import type {LoadContext} from '@docusaurus/types';
22
23
 
23
24
  async function createVersionedSidebarFile({
24
25
  siteDir,
@@ -42,13 +43,8 @@ async function createVersionedSidebarFile({
42
43
  const shouldCreateVersionedSidebarFile = Object.keys(sidebars).length > 0;
43
44
 
44
45
  if (shouldCreateVersionedSidebarFile) {
45
- const versionedSidebarsDir = getVersionedSidebarsDirPath(siteDir, pluginId);
46
- const newSidebarFile = path.join(
47
- versionedSidebarsDir,
48
- `version-${version}-sidebars.json`,
49
- );
50
46
  await fs.outputFile(
51
- newSidebarFile,
47
+ getVersionSidebarsPath(siteDir, pluginId, version),
52
48
  `${JSON.stringify(sidebars, null, 2)}\n`,
53
49
  'utf8',
54
50
  );
@@ -57,54 +53,27 @@ async function createVersionedSidebarFile({
57
53
 
58
54
  // Tests depend on non-default export for mocking.
59
55
  export async function cliDocsVersionCommand(
60
- version: string | null | undefined,
61
- siteDir: string,
62
- pluginId: string,
63
- options: PathOptions & SidebarOptions,
56
+ version: string,
57
+ {id: pluginId, path: docsPath, sidebarPath}: PluginOptions,
58
+ {siteDir, i18n}: LoadContext,
64
59
  ): Promise<void> {
65
60
  // It wouldn't be very user-friendly to show a [default] log prefix,
66
61
  // so we use [docs] instead of [default]
67
62
  const pluginIdLogPrefix =
68
63
  pluginId === DEFAULT_PLUGIN_ID ? '[docs]' : `[${pluginId}]`;
69
64
 
70
- if (!version) {
71
- throw new Error(
72
- `${pluginIdLogPrefix}: no version tag specified! Pass the version you wish to create as an argument, for example: 1.0.0.`,
73
- );
74
- }
75
-
76
- if (version.includes('/') || version.includes('\\')) {
77
- throw new Error(
78
- `${pluginIdLogPrefix}: invalid version tag specified! Do not include slash (/) or backslash (\\). Try something like: 1.0.0.`,
79
- );
80
- }
81
-
82
- if (version.length > 32) {
83
- throw new Error(
84
- `${pluginIdLogPrefix}: invalid version tag specified! Length cannot exceed 32 characters. Try something like: 1.0.0.`,
85
- );
86
- }
87
-
88
- // Since we are going to create `version-${version}` folder, we need to make
89
- // sure it's a valid pathname.
90
- // eslint-disable-next-line no-control-regex
91
- if (/[<>:"|?*\x00-\x1F]/.test(version)) {
92
- throw new Error(
93
- `${pluginIdLogPrefix}: invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0.`,
94
- );
95
- }
96
-
97
- if (/^\.\.?$/.test(version)) {
98
- throw new Error(
99
- `${pluginIdLogPrefix}: invalid version tag specified! Do not name your version "." or "..". Try something like: 1.0.0.`,
100
- );
65
+ try {
66
+ validateVersionName(version);
67
+ } catch (e) {
68
+ logger.info`${pluginIdLogPrefix}: Invalid version name provided. Try something like: 1.0.0`;
69
+ throw e;
101
70
  }
102
71
 
103
72
  // Load existing versions.
104
73
  let versions = [];
105
74
  const versionsJSONFile = getVersionsFilePath(siteDir, pluginId);
106
75
  if (await fs.pathExists(versionsJSONFile)) {
107
- versions = JSON.parse(await fs.readFile(versionsJSONFile, 'utf8'));
76
+ versions = await fs.readJSON(versionsJSONFile);
108
77
  }
109
78
 
110
79
  // Check if version already exists.
@@ -114,27 +83,55 @@ export async function cliDocsVersionCommand(
114
83
  );
115
84
  }
116
85
 
117
- const {path: docsPath, sidebarPath} = options;
118
-
119
- // Copy docs files.
120
- const docsDir = path.join(siteDir, docsPath);
121
-
122
- if (
123
- (await fs.pathExists(docsDir)) &&
124
- (await fs.readdir(docsDir)).length > 0
125
- ) {
126
- const versionedDir = getVersionedDocsDirPath(siteDir, pluginId);
127
- const newVersionDir = path.join(versionedDir, `version-${version}`);
128
- await fs.copy(docsDir, newVersionDir);
129
- } else {
130
- throw new Error(`${pluginIdLogPrefix}: there is no docs to version!`);
86
+ if (i18n.locales.length > 1) {
87
+ logger.info`Versioned docs will be created for the following locales: name=${i18n.locales}`;
131
88
  }
132
89
 
90
+ await Promise.all(
91
+ i18n.locales.map(async (locale) => {
92
+ // Copy docs files.
93
+ const docsDir =
94
+ locale === i18n.defaultLocale
95
+ ? path.resolve(siteDir, docsPath)
96
+ : getDocsDirPathLocalized({
97
+ siteDir,
98
+ locale,
99
+ pluginId,
100
+ versionName: CURRENT_VERSION_NAME,
101
+ });
102
+
103
+ if (
104
+ !(await fs.pathExists(docsDir)) ||
105
+ (await fs.readdir(docsDir)).length === 0
106
+ ) {
107
+ if (locale === i18n.defaultLocale) {
108
+ throw new Error(
109
+ logger.interpolate`${pluginIdLogPrefix}: no docs found in path=${docsDir}.`,
110
+ );
111
+ } else {
112
+ logger.warn`${pluginIdLogPrefix}: no docs found in path=${docsDir}. Skipping.`;
113
+ return;
114
+ }
115
+ }
116
+
117
+ const newVersionDir =
118
+ locale === i18n.defaultLocale
119
+ ? getVersionDocsDirPath(siteDir, pluginId, version)
120
+ : getDocsDirPathLocalized({
121
+ siteDir,
122
+ locale,
123
+ pluginId,
124
+ versionName: version,
125
+ });
126
+ await fs.copy(docsDir, newVersionDir);
127
+ }),
128
+ );
129
+
133
130
  await createVersionedSidebarFile({
134
131
  siteDir,
135
132
  pluginId,
136
133
  version,
137
- sidebarPath: resolveSidebarPathOption(siteDir, sidebarPath),
134
+ sidebarPath,
138
135
  });
139
136
 
140
137
  // Update versions.json file.
@@ -11,11 +11,11 @@ import type {
11
11
  GlobalPluginData,
12
12
  GlobalVersion,
13
13
  GlobalDoc,
14
- GetActivePluginOptions,
15
14
  ActivePlugin,
16
15
  ActiveDocContext,
17
16
  DocVersionSuggestions,
18
17
  } from '@docusaurus/plugin-content-docs/client';
18
+ import type {UseDataOptions} from '@docusaurus/types';
19
19
 
20
20
  // This code is not part of the api surface, not in ./theme on purpose
21
21
 
@@ -25,7 +25,7 @@ import type {
25
25
  export function getActivePlugin(
26
26
  allPluginData: {[pluginId: string]: GlobalPluginData},
27
27
  pathname: string,
28
- options: GetActivePluginOptions = {},
28
+ options: UseDataOptions = {},
29
29
  ): ActivePlugin | undefined {
30
30
  const activeEntry = Object.entries(allPluginData)
31
31
  // Route sorting: '/android/foo' should match '/android' instead of '/'
@@ -59,12 +59,10 @@ export function getActivePlugin(
59
59
  export const getLatestVersion = (data: GlobalPluginData): GlobalVersion =>
60
60
  data.versions.find((version) => version.isLast)!;
61
61
 
62
- // Note: return undefined on doc-unrelated pages,
63
- // because there's no version currently considered as active
64
- export const getActiveVersion = (
62
+ export function getActiveVersion(
65
63
  data: GlobalPluginData,
66
64
  pathname: string,
67
- ): GlobalVersion | undefined => {
65
+ ): GlobalVersion | undefined {
68
66
  const lastVersion = getLatestVersion(data);
69
67
  // Last version is a route like /docs/*,
70
68
  // we need to match it last or it would match /docs/version-1.0/* as well
@@ -80,12 +78,12 @@ export const getActiveVersion = (
80
78
  strict: false,
81
79
  }),
82
80
  );
83
- };
81
+ }
84
82
 
85
- export const getActiveDocContext = (
83
+ export function getActiveDocContext(
86
84
  data: GlobalPluginData,
87
85
  pathname: string,
88
- ): ActiveDocContext => {
86
+ ): ActiveDocContext {
89
87
  const activeVersion = getActiveVersion(data, pathname);
90
88
  const activeDoc = activeVersion?.docs.find(
91
89
  (doc) =>
@@ -119,15 +117,15 @@ export const getActiveDocContext = (
119
117
  activeDoc,
120
118
  alternateDocVersions: alternateVersionDocs,
121
119
  };
122
- };
120
+ }
123
121
 
124
- export const getDocVersionSuggestions = (
122
+ export function getDocVersionSuggestions(
125
123
  data: GlobalPluginData,
126
124
  pathname: string,
127
- ): DocVersionSuggestions => {
125
+ ): DocVersionSuggestions {
128
126
  const latestVersion = getLatestVersion(data);
129
127
  const activeDocContext = getActiveDocContext(data, pathname);
130
128
  const latestDocSuggestion: GlobalDoc | undefined =
131
129
  activeDocContext?.alternateDocVersions[latestVersion.name];
132
130
  return {latestDocSuggestion, latestVersionSuggestion: latestVersion};
133
- };
131
+ }
@@ -6,7 +6,10 @@
6
6
  */
7
7
 
8
8
  import {useLocation} from '@docusaurus/router';
9
- import useGlobalData, {usePluginData} from '@docusaurus/useGlobalData';
9
+ import {
10
+ useAllPluginInstancesData,
11
+ usePluginData,
12
+ } from '@docusaurus/useGlobalData';
10
13
 
11
14
  import {
12
15
  getActivePlugin,
@@ -21,84 +24,80 @@ import type {
21
24
  ActivePlugin,
22
25
  ActiveDocContext,
23
26
  DocVersionSuggestions,
24
- GetActivePluginOptions,
25
27
  } from '@docusaurus/plugin-content-docs/client';
28
+ import type {UseDataOptions} from '@docusaurus/types';
26
29
 
27
30
  // Important to use a constant object to avoid React useEffect executions etc.
28
31
  // see https://github.com/facebook/docusaurus/issues/5089
29
32
  const StableEmptyObject = {};
30
33
 
31
- // Not using useAllPluginInstancesData() because in blog-only mode, docs hooks
32
- // are still used by the theme. We need a fail-safe fallback when the docs
33
- // plugin is not in use
34
+ // In blog-only mode, docs hooks are still used by the theme. We need a fail-
35
+ // safe fallback when the docs plugin is not in use
34
36
  export const useAllDocsData = (): {[pluginId: string]: GlobalPluginData} =>
35
- useGlobalData()['docusaurus-plugin-content-docs'] ?? StableEmptyObject;
37
+ useAllPluginInstancesData('docusaurus-plugin-content-docs') ??
38
+ StableEmptyObject;
36
39
 
37
40
  export const useDocsData = (pluginId: string | undefined): GlobalPluginData =>
38
- usePluginData('docusaurus-plugin-content-docs', pluginId) as GlobalPluginData;
41
+ usePluginData('docusaurus-plugin-content-docs', pluginId, {
42
+ failfast: true,
43
+ }) as GlobalPluginData;
39
44
 
40
45
  // TODO this feature should be provided by docusaurus core
41
- export const useActivePlugin = (
42
- options: GetActivePluginOptions = {},
43
- ): ActivePlugin | undefined => {
46
+ export function useActivePlugin(
47
+ options: UseDataOptions = {},
48
+ ): ActivePlugin | undefined {
44
49
  const data = useAllDocsData();
45
50
  const {pathname} = useLocation();
46
51
  return getActivePlugin(data, pathname, options);
47
- };
52
+ }
48
53
 
49
- export const useActivePluginAndVersion = (
50
- options: GetActivePluginOptions = {},
54
+ export function useActivePluginAndVersion(
55
+ options: UseDataOptions = {},
51
56
  ):
52
- | undefined
53
- | {activePlugin: ActivePlugin; activeVersion: GlobalVersion | undefined} => {
57
+ | {activePlugin: ActivePlugin; activeVersion: GlobalVersion | undefined}
58
+ | undefined {
54
59
  const activePlugin = useActivePlugin(options);
55
60
  const {pathname} = useLocation();
56
- if (activePlugin) {
57
- const activeVersion = getActiveVersion(activePlugin.pluginData, pathname);
58
- return {
59
- activePlugin,
60
- activeVersion,
61
- };
61
+ if (!activePlugin) {
62
+ return undefined;
62
63
  }
63
- return undefined;
64
- };
64
+ const activeVersion = getActiveVersion(activePlugin.pluginData, pathname);
65
+ return {
66
+ activePlugin,
67
+ activeVersion,
68
+ };
69
+ }
65
70
 
66
- // versions are returned ordered (most recent first)
67
- export const useVersions = (pluginId: string | undefined): GlobalVersion[] => {
71
+ export function useVersions(pluginId: string | undefined): GlobalVersion[] {
68
72
  const data = useDocsData(pluginId);
69
73
  return data.versions;
70
- };
74
+ }
71
75
 
72
- export const useLatestVersion = (
73
- pluginId: string | undefined,
74
- ): GlobalVersion => {
76
+ export function useLatestVersion(pluginId: string | undefined): GlobalVersion {
75
77
  const data = useDocsData(pluginId);
76
78
  return getLatestVersion(data);
77
- };
79
+ }
78
80
 
79
- // Note: return undefined on doc-unrelated pages,
80
- // because there's no version currently considered as active
81
- export const useActiveVersion = (
81
+ export function useActiveVersion(
82
82
  pluginId: string | undefined,
83
- ): GlobalVersion | undefined => {
83
+ ): GlobalVersion | undefined {
84
84
  const data = useDocsData(pluginId);
85
85
  const {pathname} = useLocation();
86
86
  return getActiveVersion(data, pathname);
87
- };
87
+ }
88
88
 
89
- export const useActiveDocContext = (
89
+ export function useActiveDocContext(
90
90
  pluginId: string | undefined,
91
- ): ActiveDocContext => {
91
+ ): ActiveDocContext {
92
92
  const data = useDocsData(pluginId);
93
93
  const {pathname} = useLocation();
94
94
  return getActiveDocContext(data, pathname);
95
- };
95
+ }
96
96
 
97
- // Useful to say "hey, you are not on the latest docs version, please switch"
98
- export const useDocVersionSuggestions = (
97
+ export function useDocVersionSuggestions(
99
98
  pluginId: string | undefined,
100
- ): DocVersionSuggestions => {
99
+ ): DocVersionSuggestions {
101
100
  const data = useDocsData(pluginId);
102
101
  const {pathname} = useLocation();
103
102
  return getDocVersionSuggestions(data, pathname);
104
- };
103
+ }
package/src/constants.ts CHANGED
@@ -5,9 +5,11 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- // The name of the version at the root of your site (website/docs)
8
+ /** The name of the version that's actively worked on (e.g. `website/docs`) */
9
9
  export const CURRENT_VERSION_NAME = 'current';
10
-
10
+ /** All doc versions are stored here by version names */
11
11
  export const VERSIONED_DOCS_DIR = 'versioned_docs';
12
+ /** All doc versioned sidebars are stored here by version names */
12
13
  export const VERSIONED_SIDEBARS_DIR = 'versioned_sidebars';
14
+ /** The version names. Should 1-1 map to the content of versioned docs dir. */
13
15
  export const VERSIONS_JSON_FILE = 'versions.json';
package/src/docs.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  aliasedSitePath,
13
13
  getEditUrl,
14
14
  getFolderContainingFile,
15
+ getContentPathList,
15
16
  normalizeUrl,
16
17
  parseMarkdownString,
17
18
  posixPath,
@@ -21,18 +22,9 @@ import {
21
22
  import type {LoadContext} from '@docusaurus/types';
22
23
 
23
24
  import {getFileLastUpdate} from './lastUpdate';
24
- import type {
25
- DocFile,
26
- DocMetadataBase,
27
- DocMetadata,
28
- DocNavLink,
29
- LastUpdateData,
30
- VersionMetadata,
31
- LoadedVersion,
32
- } from './types';
25
+ import type {DocFile} from './types';
33
26
  import getSlug from './slug';
34
27
  import {CURRENT_VERSION_NAME} from './constants';
35
- import {getDocsDirPaths} from './versions';
36
28
  import {stripPathNumberPrefixes} from './numberPrefix';
37
29
  import {validateDocFrontMatter} from './frontMatter';
38
30
  import type {SidebarsUtils} from './sidebars/utils';
@@ -41,7 +33,13 @@ import type {
41
33
  MetadataOptions,
42
34
  PluginOptions,
43
35
  CategoryIndexMatcher,
44
- CategoryIndexMatcherParam,
36
+ DocMetadataBase,
37
+ DocMetadata,
38
+ PropNavigationLink,
39
+ LastUpdateData,
40
+ VersionMetadata,
41
+ DocFrontMatter,
42
+ LoadedVersion,
45
43
  } from '@docusaurus/plugin-content-docs';
46
44
 
47
45
  type LastUpdateOptions = Pick<
@@ -85,7 +83,7 @@ export async function readDocFile(
85
83
  options: LastUpdateOptions,
86
84
  ): Promise<DocFile> {
87
85
  const contentPath = await getFolderContainingFile(
88
- getDocsDirPaths(versionMetadata),
86
+ getContentPathList(versionMetadata),
89
87
  source,
90
88
  );
91
89
 
@@ -114,16 +112,31 @@ export async function readVersionDocs(
114
112
  );
115
113
  }
116
114
 
115
+ export type DocEnv = 'production' | 'development';
116
+
117
+ /** Docs with draft front matter are only considered draft in production. */
118
+ function isDraftForEnvironment({
119
+ env,
120
+ frontMatter,
121
+ }: {
122
+ frontMatter: DocFrontMatter;
123
+ env: DocEnv;
124
+ }): boolean {
125
+ return (env === 'production' && frontMatter.draft) ?? false;
126
+ }
127
+
117
128
  function doProcessDocMetadata({
118
129
  docFile,
119
130
  versionMetadata,
120
131
  context,
121
132
  options,
133
+ env,
122
134
  }: {
123
135
  docFile: DocFile;
124
136
  versionMetadata: VersionMetadata;
125
137
  context: LoadContext;
126
138
  options: MetadataOptions;
139
+ env: DocEnv;
127
140
  }): DocMetadataBase {
128
141
  const {source, content, lastUpdate, contentPath, filePath} = docFile;
129
142
  const {siteDir, i18n} = context;
@@ -144,15 +157,13 @@ function doProcessDocMetadata({
144
157
  parse_number_prefixes: parseNumberPrefixes = true,
145
158
  } = frontMatter;
146
159
 
147
- // ex: api/plugins/myDoc -> myDoc
148
- // ex: myDoc -> myDoc
160
+ // E.g. api/plugins/myDoc -> myDoc; myDoc -> myDoc
149
161
  const sourceFileNameWithoutExtension = path.basename(
150
162
  source,
151
163
  path.extname(source),
152
164
  );
153
165
 
154
- // ex: api/plugins/myDoc -> api/plugins
155
- // ex: myDoc -> .
166
+ // E.g. api/plugins/myDoc -> api/plugins; myDoc -> .
156
167
  const sourceDirName = path.dirname(source);
157
168
 
158
169
  const {filename: unprefixedFileName, numberPrefix} = parseNumberPrefixes
@@ -213,7 +224,7 @@ function doProcessDocMetadata({
213
224
 
214
225
  const description: string = frontMatter.description ?? excerpt ?? '';
215
226
 
216
- const permalink = normalizeUrl([versionMetadata.versionPath, docSlug]);
227
+ const permalink = normalizeUrl([versionMetadata.path, docSlug]);
217
228
 
218
229
  function getDocEditUrl() {
219
230
  const relativeFilePath = path.relative(contentPath, filePath);
@@ -232,13 +243,15 @@ function doProcessDocMetadata({
232
243
  const isLocalized = contentPath === versionMetadata.contentPathLocalized;
233
244
  const baseVersionEditUrl =
234
245
  isLocalized && options.editLocalizedFiles
235
- ? versionMetadata.versionEditUrlLocalized
236
- : versionMetadata.versionEditUrl;
246
+ ? versionMetadata.editUrlLocalized
247
+ : versionMetadata.editUrl;
237
248
  return getEditUrl(relativeFilePath, baseVersionEditUrl);
238
249
  }
239
250
  return undefined;
240
251
  }
241
252
 
253
+ const draft = isDraftForEnvironment({env, frontMatter});
254
+
242
255
  // Assign all of object properties during instantiation (if possible) for
243
256
  // NodeJS optimization.
244
257
  // Adding properties to object after instantiation will cause hidden
@@ -252,15 +265,16 @@ function doProcessDocMetadata({
252
265
  sourceDirName,
253
266
  slug: docSlug,
254
267
  permalink,
268
+ draft,
255
269
  editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(),
256
270
  tags: normalizeFrontMatterTags(versionMetadata.tagsPath, frontMatter.tags),
257
271
  version: versionMetadata.versionName,
258
272
  lastUpdatedBy: lastUpdate.lastUpdatedBy,
259
273
  lastUpdatedAt: lastUpdate.lastUpdatedAt,
260
274
  formattedLastUpdatedAt: lastUpdate.lastUpdatedAt
261
- ? new Intl.DateTimeFormat(i18n.currentLocale).format(
262
- lastUpdate.lastUpdatedAt * 1000,
263
- )
275
+ ? new Intl.DateTimeFormat(i18n.currentLocale, {
276
+ calendar: i18n.localeConfigs[i18n.currentLocale]!.calendar,
277
+ }).format(lastUpdate.lastUpdatedAt * 1000)
264
278
  : undefined,
265
279
  sidebarPosition,
266
280
  frontMatter,
@@ -272,6 +286,7 @@ export function processDocMetadata(args: {
272
286
  versionMetadata: VersionMetadata;
273
287
  context: LoadContext;
274
288
  options: MetadataOptions;
289
+ env: DocEnv;
275
290
  }): DocMetadataBase {
276
291
  try {
277
292
  return doProcessDocMetadata(args);
@@ -304,7 +319,7 @@ export function addDocNavigation(
304
319
  const toNavigationLinkByDocId = (
305
320
  docId: string | null | undefined,
306
321
  type: 'prev' | 'next',
307
- ): DocNavLink | undefined => {
322
+ ): PropNavigationLink | undefined => {
308
323
  if (!docId) {
309
324
  return undefined;
310
325
  }
@@ -331,7 +346,7 @@ export function addDocNavigation(
331
346
  }
332
347
 
333
348
  const docsWithNavigation = docsBase.map(addNavData);
334
- // sort to ensure consistent output for tests
349
+ // Sort to ensure consistent output for tests
335
350
  docsWithNavigation.sort((a, b) => a.id.localeCompare(b.id));
336
351
  return docsWithNavigation;
337
352
  }
@@ -401,7 +416,7 @@ export function toCategoryIndexMatcherParam({
401
416
  }: Pick<
402
417
  DocMetadataBase,
403
418
  'source' | 'sourceDirName'
404
- >): CategoryIndexMatcherParam {
419
+ >): Parameters<CategoryIndexMatcher>[0] {
405
420
  // source + sourceDirName are always posix-style
406
421
  return {
407
422
  fileName: path.posix.parse(source).name,
@@ -418,7 +433,7 @@ export function getDocIds(doc: DocMetadataBase): [string, string] {
418
433
  return [doc.unversionedId, doc.id];
419
434
  }
420
435
 
421
- // docs are indexed by both versioned and unversioned ids at the same time
436
+ // Docs are indexed by both versioned and unversioned ids at the same time
422
437
  // TODO legacy retro-compatibility due to old versioned sidebars using
423
438
  // versioned doc ids ("id" should be removed & "versionedId" should be renamed
424
439
  // to "id")
@@ -12,7 +12,7 @@ import {
12
12
  FrontMatterTOCHeadingLevels,
13
13
  validateFrontMatter,
14
14
  } from '@docusaurus/utils-validation';
15
- import type {DocFrontMatter} from './types';
15
+ import type {DocFrontMatter} from '@docusaurus/plugin-content-docs';
16
16
 
17
17
  // NOTE: we don't add any default value on purpose here
18
18
  // We don't want default values to magically appear in doc metadata and props
@@ -20,12 +20,14 @@ import type {DocFrontMatter} from './types';
20
20
  // We use default values in code instead
21
21
  const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
22
22
  id: Joi.string(),
23
- title: Joi.string().allow(''), // see https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
23
+ // See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
24
+ title: Joi.string().allow(''),
24
25
  hide_title: Joi.boolean(),
25
26
  hide_table_of_contents: Joi.boolean(),
26
27
  keywords: Joi.array().items(Joi.string().required()),
27
28
  image: URISchema,
28
- description: Joi.string().allow(''), // see https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
29
+ // See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
30
+ description: Joi.string().allow(''),
29
31
  slug: Joi.string(),
30
32
  sidebar_label: Joi.string(),
31
33
  sidebar_position: Joi.number(),
@@ -38,6 +40,7 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
38
40
  parse_number_prefixes: Joi.boolean(),
39
41
  pagination_next: Joi.string().allow(null),
40
42
  pagination_prev: Joi.string().allow(null),
43
+ draft: Joi.boolean(),
41
44
  ...FrontMatterTOCHeadingLevels,
42
45
  }).unknown();
43
46
 
package/src/globalData.ts CHANGED
@@ -7,12 +7,12 @@
7
7
 
8
8
  import _ from 'lodash';
9
9
  import type {Sidebars} from './sidebars/types';
10
- import {createSidebarsUtils} from './sidebars/utils';
10
+ import {getMainDocId} from './docs';
11
+ import type {FullVersion} from './types';
11
12
  import type {
12
13
  CategoryGeneratedIndexMetadata,
13
14
  DocMetadata,
14
- LoadedVersion,
15
- } from './types';
15
+ } from '@docusaurus/plugin-content-docs';
16
16
  import type {
17
17
  GlobalVersion,
18
18
  GlobalSidebar,
@@ -39,11 +39,10 @@ function toGlobalDataGeneratedIndex(
39
39
 
40
40
  function toGlobalSidebars(
41
41
  sidebars: Sidebars,
42
- version: LoadedVersion,
42
+ version: FullVersion,
43
43
  ): {[sidebarId: string]: GlobalSidebar} {
44
- const {getFirstLink} = createSidebarsUtils(sidebars);
45
44
  return _.mapValues(sidebars, (sidebar, sidebarId) => {
46
- const firstLink = getFirstLink(sidebarId);
45
+ const firstLink = version.sidebarsUtils.getFirstLink(sidebarId);
47
46
  if (!firstLink) {
48
47
  return {};
49
48
  }
@@ -62,16 +61,17 @@ function toGlobalSidebars(
62
61
  });
63
62
  }
64
63
 
65
- export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion {
64
+ export function toGlobalDataVersion(version: FullVersion): GlobalVersion {
66
65
  return {
67
66
  name: version.versionName,
68
- label: version.versionLabel,
67
+ label: version.label,
69
68
  isLast: version.isLast,
70
- path: version.versionPath,
71
- mainDocId: version.mainDocId,
69
+ path: version.path,
70
+ mainDocId: getMainDocId(version),
72
71
  docs: version.docs
73
72
  .map(toGlobalDataDoc)
74
73
  .concat(version.categoryGeneratedIndices.map(toGlobalDataGeneratedIndex)),
74
+ draftIds: version.drafts.map((doc) => doc.unversionedId),
75
75
  sidebars: toGlobalSidebars(version.sidebars, version),
76
76
  };
77
77
  }