@azerion/bunosaurus-plugin-content-docs 0.0.0-stage → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +6 -2
  2. package/lib/categoryGeneratedIndex.d.ts +12 -0
  3. package/lib/categoryGeneratedIndex.js +36 -0
  4. package/lib/cli.d.ts +13 -0
  5. package/lib/cli.js +124 -0
  6. package/lib/client/doc.d.ts +29 -0
  7. package/lib/client/doc.js +47 -0
  8. package/lib/client/docSidebarItemsExpandedState.d.ts +30 -0
  9. package/lib/client/docSidebarItemsExpandedState.js +27 -0
  10. package/lib/client/docsClientUtils.d.ts +15 -0
  11. package/lib/client/docsClientUtils.js +86 -0
  12. package/lib/client/docsPreferredVersion.d.ts +29 -0
  13. package/lib/client/docsPreferredVersion.js +124 -0
  14. package/lib/client/docsSearch.d.ts +19 -0
  15. package/lib/client/docsSearch.js +39 -0
  16. package/lib/client/docsSidebar.d.ts +25 -0
  17. package/lib/client/docsSidebar.js +29 -0
  18. package/lib/client/docsUtils.d.ts +112 -0
  19. package/lib/client/docsUtils.js +299 -0
  20. package/lib/client/docsVersion.d.ts +19 -0
  21. package/lib/client/docsVersion.js +25 -0
  22. package/lib/client/index.d.ts +91 -0
  23. package/lib/client/index.js +83 -0
  24. package/lib/client/structuredDataUtils.d.ts +11 -0
  25. package/lib/client/structuredDataUtils.js +35 -0
  26. package/lib/constants.d.ts +14 -0
  27. package/lib/constants.js +17 -0
  28. package/lib/contentHelpers.d.ts +12 -0
  29. package/lib/contentHelpers.js +31 -0
  30. package/lib/docs.d.ts +48 -0
  31. package/lib/docs.js +252 -0
  32. package/lib/frontMatter.d.ts +10 -0
  33. package/lib/frontMatter.js +46 -0
  34. package/lib/globalData.d.ts +9 -0
  35. package/lib/globalData.js +59 -0
  36. package/lib/index.d.ts +10 -0
  37. package/lib/index.js +198 -0
  38. package/lib/numberPrefix.d.ts +11 -0
  39. package/lib/numberPrefix.js +50 -0
  40. package/lib/options.d.ts +10 -0
  41. package/lib/options.js +138 -0
  42. package/lib/props.d.ts +21 -0
  43. package/lib/props.js +156 -0
  44. package/lib/routes.d.ts +22 -0
  45. package/lib/routes.js +184 -0
  46. package/lib/server-export.d.ts +9 -0
  47. package/lib/server-export.js +25 -0
  48. package/lib/sidebars/generator.d.ts +10 -0
  49. package/lib/sidebars/generator.js +217 -0
  50. package/lib/sidebars/index.d.ts +13 -0
  51. package/lib/sidebars/index.js +99 -0
  52. package/lib/sidebars/normalization.d.ts +13 -0
  53. package/lib/sidebars/normalization.js +58 -0
  54. package/lib/sidebars/postProcessor.d.ts +11 -0
  55. package/lib/sidebars/postProcessor.js +82 -0
  56. package/lib/sidebars/processor.d.ts +10 -0
  57. package/lib/sidebars/processor.js +77 -0
  58. package/lib/sidebars/types.d.ts +192 -0
  59. package/lib/sidebars/types.js +8 -0
  60. package/lib/sidebars/utils.d.ts +69 -0
  61. package/lib/sidebars/utils.js +327 -0
  62. package/lib/sidebars/validation.d.ts +11 -0
  63. package/lib/sidebars/validation.js +152 -0
  64. package/lib/slug.d.ts +15 -0
  65. package/lib/slug.js +51 -0
  66. package/lib/translations.d.ts +10 -0
  67. package/lib/translations.js +243 -0
  68. package/lib/types.d.ts +27 -0
  69. package/lib/types.js +8 -0
  70. package/lib/versions/files.d.ts +54 -0
  71. package/lib/versions/files.js +152 -0
  72. package/lib/versions/loadVersion.d.ts +17 -0
  73. package/lib/versions/loadVersion.js +126 -0
  74. package/lib/versions/validation.d.ts +17 -0
  75. package/lib/versions/validation.js +70 -0
  76. package/lib/versions/version.d.ts +40 -0
  77. package/lib/versions/version.js +189 -0
  78. package/package.json +70 -4
  79. package/src/categoryGeneratedIndex.ts +60 -0
  80. package/src/cli.ts +180 -0
  81. package/src/client/doc.tsx +71 -0
  82. package/src/client/docSidebarItemsExpandedState.tsx +55 -0
  83. package/src/client/docsClientUtils.ts +140 -0
  84. package/src/client/docsPreferredVersion.tsx +245 -0
  85. package/src/client/docsSearch.test.ts +15 -0
  86. package/src/client/docsSearch.ts +57 -0
  87. package/src/client/docsSidebar.tsx +50 -0
  88. package/src/client/docsUtils.tsx +442 -0
  89. package/src/client/docsVersion.tsx +36 -0
  90. package/src/client/index.ts +211 -0
  91. package/src/client/structuredDataUtils.ts +54 -0
  92. package/src/constants.ts +15 -0
  93. package/src/contentHelpers.ts +34 -0
  94. package/src/docs.ts +402 -0
  95. package/src/frontMatter.ts +57 -0
  96. package/src/globalData.ts +79 -0
  97. package/src/index.ts +289 -0
  98. package/src/numberPrefix.ts +62 -0
  99. package/src/options.ts +185 -0
  100. package/src/plugin-content-docs.d.ts +667 -0
  101. package/src/props.ts +223 -0
  102. package/src/routes.ts +263 -0
  103. package/src/server-export.ts +26 -0
  104. package/src/sidebars/README.md +10 -0
  105. package/src/sidebars/generator.ts +307 -0
  106. package/src/sidebars/index.ts +130 -0
  107. package/src/sidebars/normalization.ts +91 -0
  108. package/src/sidebars/postProcessor.ts +115 -0
  109. package/src/sidebars/processor.ts +122 -0
  110. package/src/sidebars/types.ts +293 -0
  111. package/src/sidebars/utils.ts +529 -0
  112. package/src/sidebars/validation.ts +189 -0
  113. package/src/slug.ts +79 -0
  114. package/src/translations.ts +365 -0
  115. package/src/types.ts +34 -0
  116. package/src/versions/files.ts +240 -0
  117. package/src/versions/loadVersion.ts +185 -0
  118. package/src/versions/validation.ts +115 -0
  119. package/src/versions/version.ts +300 -0
@@ -0,0 +1,55 @@
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 React, {type ReactNode, useMemo, useState, useContext} from 'react';
9
+ import {ReactContextError} from '@docusaurus/theme-common';
10
+
11
+ type ContextValue = {
12
+ /**
13
+ * The item that the user last opened, `null` when there's none open. On
14
+ * initial render, it will always be `null`, which doesn't necessarily mean
15
+ * there's no category open (can have 0, 1, or many being initially open).
16
+ */
17
+ expandedItem: number | null;
18
+ /**
19
+ * Set the currently expanded item, when the user opens one. Set the value to
20
+ * `null` when the user closes an open category.
21
+ */
22
+ setExpandedItem: (a: number | null) => void;
23
+ };
24
+
25
+ const EmptyContext: unique symbol = Symbol('EmptyContext');
26
+ const Context = React.createContext<ContextValue | typeof EmptyContext>(
27
+ EmptyContext,
28
+ );
29
+
30
+ /**
31
+ * Should be used to wrap one sidebar category level. This provider syncs the
32
+ * expanded states of all sibling categories, and categories can choose to
33
+ * collapse itself if another one is expanded.
34
+ */
35
+ export function DocSidebarItemsExpandedStateProvider({
36
+ children,
37
+ }: {
38
+ children: ReactNode;
39
+ }): ReactNode {
40
+ const [expandedItem, setExpandedItem] = useState<number | null>(null);
41
+ const contextValue = useMemo(
42
+ () => ({expandedItem, setExpandedItem}),
43
+ [expandedItem],
44
+ );
45
+
46
+ return <Context value={contextValue}>{children}</Context>;
47
+ }
48
+
49
+ export function useDocSidebarItemsExpandedState(): ContextValue {
50
+ const value = useContext(Context);
51
+ if (value === EmptyContext) {
52
+ throw new ReactContextError('DocSidebarItemsExpandedStateProvider');
53
+ }
54
+ return value;
55
+ }
@@ -0,0 +1,140 @@
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 {matchPath} from '@docusaurus/router';
9
+
10
+ import type {
11
+ GlobalPluginData,
12
+ GlobalVersion,
13
+ GlobalDoc,
14
+ ActivePlugin,
15
+ ActiveDocContext,
16
+ DocVersionSuggestions,
17
+ } from '@docusaurus/plugin-content-docs/client';
18
+ import type {UseDataOptions} from '@docusaurus/types';
19
+
20
+ // This code is not part of the api surface, not in ./theme on purpose
21
+
22
+ // get the data of the plugin that is currently "active"
23
+ // ie the docs of that plugin are currently browsed
24
+ // it is useful to support multiple docs plugin instances
25
+ export function getActivePlugin(
26
+ allPluginData: {[pluginId: string]: GlobalPluginData},
27
+ pathname: string,
28
+ options: UseDataOptions = {},
29
+ ): ActivePlugin | undefined {
30
+ const activeEntry = Object.entries(allPluginData)
31
+ // Route sorting: '/android/foo' should match '/android' instead of '/'
32
+ .sort((a, b) => b[1].path.localeCompare(a[1].path))
33
+ .find(
34
+ ([, pluginData]) =>
35
+ !!matchPath(pathname, {
36
+ path: pluginData.path,
37
+ exact: false,
38
+ strict: false,
39
+ }),
40
+ );
41
+
42
+ const activePlugin: ActivePlugin | undefined = activeEntry
43
+ ? {pluginId: activeEntry[0], pluginData: activeEntry[1]}
44
+ : undefined;
45
+
46
+ if (!activePlugin && options.failfast) {
47
+ throw new Error(
48
+ `Can't find active docs plugin for "${pathname}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(
49
+ allPluginData,
50
+ )
51
+ .map((plugin) => plugin.path)
52
+ .join(', ')}`,
53
+ );
54
+ }
55
+
56
+ return activePlugin;
57
+ }
58
+
59
+ export const getLatestVersion = (data: GlobalPluginData): GlobalVersion =>
60
+ data.versions.find((version) => version.isLast)!;
61
+
62
+ export function getActiveVersion(
63
+ data: GlobalPluginData,
64
+ pathname: string,
65
+ ): GlobalVersion | undefined {
66
+ // Sort paths so that a match-all version like /docs/* is matched last
67
+ // Otherwise /docs/* would match /docs/1.0.0/* routes
68
+ // This is simplified but similar to the core sortRoutes() logic
69
+ const sortedVersions = [...data.versions].sort((a, b) => {
70
+ if (a.path === b.path) {
71
+ return 0;
72
+ }
73
+ if (a.path.includes(b.path)) {
74
+ return -1;
75
+ }
76
+ if (b.path.includes(a.path)) {
77
+ return 1;
78
+ }
79
+ return 0;
80
+ });
81
+
82
+ return sortedVersions.find(
83
+ (version) =>
84
+ !!matchPath(pathname, {
85
+ path: version.path,
86
+ exact: false,
87
+ strict: false,
88
+ }),
89
+ );
90
+ }
91
+
92
+ export function getActiveDocContext(
93
+ data: GlobalPluginData,
94
+ pathname: string,
95
+ ): ActiveDocContext {
96
+ const activeVersion = getActiveVersion(data, pathname);
97
+ const activeDoc = activeVersion?.docs.find(
98
+ (doc) =>
99
+ !!matchPath(pathname, {
100
+ path: doc.path,
101
+ exact: true,
102
+ strict: false,
103
+ }),
104
+ );
105
+
106
+ function getAlternateVersionDocs(
107
+ docId: string,
108
+ ): ActiveDocContext['alternateDocVersions'] {
109
+ const result: ActiveDocContext['alternateDocVersions'] = {};
110
+ data.versions.forEach((version) => {
111
+ version.docs.forEach((doc) => {
112
+ if (doc.id === docId) {
113
+ result[version.name] = doc;
114
+ }
115
+ });
116
+ });
117
+ return result;
118
+ }
119
+
120
+ const alternateVersionDocs = activeDoc
121
+ ? getAlternateVersionDocs(activeDoc.id)
122
+ : {};
123
+
124
+ return {
125
+ activeVersion,
126
+ activeDoc,
127
+ alternateDocVersions: alternateVersionDocs,
128
+ };
129
+ }
130
+
131
+ export function getDocVersionSuggestions(
132
+ data: GlobalPluginData,
133
+ pathname: string,
134
+ ): DocVersionSuggestions {
135
+ const latestVersion = getLatestVersion(data);
136
+ const activeDocContext = getActiveDocContext(data, pathname);
137
+ const latestDocSuggestion: GlobalDoc | undefined =
138
+ activeDocContext.alternateDocVersions[latestVersion.name];
139
+ return {latestDocSuggestion, latestVersionSuggestion: latestVersion};
140
+ }
@@ -0,0 +1,245 @@
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 React, {
9
+ useContext,
10
+ useEffect,
11
+ useMemo,
12
+ useState,
13
+ useCallback,
14
+ type ReactNode,
15
+ } from 'react';
16
+ import {
17
+ useAllDocsData,
18
+ useDocsData,
19
+ type GlobalPluginData,
20
+ type GlobalVersion,
21
+ } from '@docusaurus/plugin-content-docs/client';
22
+ import {DEFAULT_PLUGIN_ID} from '@docusaurus/constants';
23
+ import {useThemeConfig, type ThemeConfig} from '@docusaurus/theme-common';
24
+ import {ReactContextError, createStorageSlot} from '@docusaurus/theme-common';
25
+
26
+ type DocsVersionPersistence = ThemeConfig['docs']['versionPersistence'];
27
+
28
+ const storageKey = (pluginId: string) => `docs-preferred-version-${pluginId}`;
29
+
30
+ const DocsPreferredVersionStorage = {
31
+ save: (
32
+ pluginId: string,
33
+ persistence: DocsVersionPersistence,
34
+ versionName: string,
35
+ ): void => {
36
+ createStorageSlot(storageKey(pluginId), {persistence}).set(versionName);
37
+ },
38
+
39
+ read: (
40
+ pluginId: string,
41
+ persistence: DocsVersionPersistence,
42
+ ): string | null =>
43
+ createStorageSlot(storageKey(pluginId), {persistence}).get(),
44
+
45
+ clear: (pluginId: string, persistence: DocsVersionPersistence): void => {
46
+ createStorageSlot(storageKey(pluginId), {persistence}).del();
47
+ },
48
+ };
49
+
50
+ type DocsPreferredVersionName = string | null;
51
+
52
+ /** State for a single docs plugin instance */
53
+ type DocsPreferredVersionPluginState = {
54
+ preferredVersionName: DocsPreferredVersionName;
55
+ };
56
+
57
+ /**
58
+ * We need to store the state in storage globally, with one preferred version
59
+ * per docs plugin instance.
60
+ */
61
+ type DocsPreferredVersionState = {
62
+ [pluginId: string]: DocsPreferredVersionPluginState;
63
+ };
64
+
65
+ /**
66
+ * Initial state is always null as we can't read local storage from node SSR
67
+ */
68
+ const getInitialState = (pluginIds: string[]): DocsPreferredVersionState =>
69
+ Object.fromEntries(pluginIds.map((id) => [id, {preferredVersionName: null}]));
70
+
71
+ /**
72
+ * Read storage for all docs plugins, assigning each doc plugin a preferred
73
+ * version (if found)
74
+ */
75
+ function readStorageState({
76
+ pluginIds,
77
+ versionPersistence,
78
+ allDocsData,
79
+ }: {
80
+ pluginIds: string[];
81
+ versionPersistence: DocsVersionPersistence;
82
+ allDocsData: {[pluginId: string]: GlobalPluginData};
83
+ }): DocsPreferredVersionState {
84
+ /**
85
+ * The storage value we read might be stale, and belong to a version that does
86
+ * not exist in the site anymore. In such case, we remove the storage value to
87
+ * avoid downstream errors.
88
+ */
89
+ function restorePluginState(
90
+ pluginId: string,
91
+ ): DocsPreferredVersionPluginState {
92
+ const preferredVersionNameUnsafe = DocsPreferredVersionStorage.read(
93
+ pluginId,
94
+ versionPersistence,
95
+ );
96
+ const pluginData = allDocsData[pluginId]!;
97
+ const versionExists = pluginData.versions.some(
98
+ (version) => version.name === preferredVersionNameUnsafe,
99
+ );
100
+ if (versionExists) {
101
+ return {preferredVersionName: preferredVersionNameUnsafe};
102
+ }
103
+ DocsPreferredVersionStorage.clear(pluginId, versionPersistence);
104
+ return {preferredVersionName: null};
105
+ }
106
+ return Object.fromEntries(
107
+ pluginIds.map((id) => [id, restorePluginState(id)]),
108
+ );
109
+ }
110
+
111
+ function useVersionPersistence(): DocsVersionPersistence {
112
+ return useThemeConfig().docs.versionPersistence;
113
+ }
114
+
115
+ type ContextValue = [
116
+ state: DocsPreferredVersionState,
117
+ api: {
118
+ savePreferredVersion: (pluginId: string, versionName: string) => void;
119
+ },
120
+ ];
121
+
122
+ const Context = React.createContext<ContextValue | null>(null);
123
+
124
+ function useContextValue(): ContextValue {
125
+ const allDocsData = useAllDocsData();
126
+ const versionPersistence = useVersionPersistence();
127
+ const pluginIds = useMemo(() => Object.keys(allDocsData), [allDocsData]);
128
+
129
+ // Initial state is empty, as we can't read browser storage in node/SSR
130
+ const [state, setState] = useState(() => getInitialState(pluginIds));
131
+
132
+ // On mount, we set the state read from browser storage
133
+ useEffect(() => {
134
+ setState(readStorageState({allDocsData, versionPersistence, pluginIds}));
135
+ }, [allDocsData, versionPersistence, pluginIds]);
136
+
137
+ // The API that we expose to consumer hooks (memo for constant object)
138
+ const api = useMemo(() => {
139
+ function savePreferredVersion(pluginId: string, versionName: string) {
140
+ DocsPreferredVersionStorage.save(
141
+ pluginId,
142
+ versionPersistence,
143
+ versionName,
144
+ );
145
+ setState((s) => ({
146
+ ...s,
147
+ [pluginId]: {preferredVersionName: versionName},
148
+ }));
149
+ }
150
+
151
+ return {
152
+ savePreferredVersion,
153
+ };
154
+ }, [versionPersistence]);
155
+
156
+ return [state, api];
157
+ }
158
+
159
+ function DocsPreferredVersionContextProviderUnsafe({
160
+ children,
161
+ }: {
162
+ children: ReactNode;
163
+ }): ReactNode {
164
+ const value = useContextValue();
165
+ return <Context value={value}>{children}</Context>;
166
+ }
167
+
168
+ /**
169
+ * This is a maybe-layer. If the docs plugin is not enabled, this provider is a
170
+ * simple pass-through.
171
+ */
172
+ export function DocsPreferredVersionContextProvider({
173
+ children,
174
+ }: {
175
+ children: ReactNode;
176
+ }): ReactNode {
177
+ return (
178
+ <DocsPreferredVersionContextProviderUnsafe>
179
+ {children}
180
+ </DocsPreferredVersionContextProviderUnsafe>
181
+ );
182
+ }
183
+
184
+ function useDocsPreferredVersionContext(): ContextValue {
185
+ const value = useContext(Context);
186
+ if (!value) {
187
+ throw new ReactContextError('DocsPreferredVersionContextProvider');
188
+ }
189
+ return value;
190
+ }
191
+
192
+ /**
193
+ * Returns a read-write interface to a plugin's preferred version. The
194
+ * "preferred version" is defined as the last version that the user visited.
195
+ * For example, if a user is using v3, even when v4 is later published, the user
196
+ * would still be browsing v3 docs when she opens the website next time. Note,
197
+ * the `preferredVersion` attribute will always be `null` before mount.
198
+ */
199
+ export function useDocsPreferredVersion(
200
+ pluginId: string | undefined = DEFAULT_PLUGIN_ID,
201
+ ): {
202
+ preferredVersion: GlobalVersion | null;
203
+ savePreferredVersionName: (versionName: string) => void;
204
+ } {
205
+ const docsData = useDocsData(pluginId);
206
+ const [state, api] = useDocsPreferredVersionContext();
207
+
208
+ const {preferredVersionName} = state[pluginId]!;
209
+
210
+ const preferredVersion =
211
+ docsData.versions.find(
212
+ (version) => version.name === preferredVersionName,
213
+ ) ?? null;
214
+
215
+ const savePreferredVersionName = useCallback(
216
+ (versionName: string) => {
217
+ api.savePreferredVersion(pluginId, versionName);
218
+ },
219
+ [api, pluginId],
220
+ );
221
+
222
+ return {preferredVersion, savePreferredVersionName};
223
+ }
224
+
225
+ export function useDocsPreferredVersionByPluginId(): {
226
+ [pluginId: string]: GlobalVersion | null;
227
+ } {
228
+ const allDocsData = useAllDocsData();
229
+ const [state] = useDocsPreferredVersionContext();
230
+
231
+ function getPluginIdPreferredVersion(pluginId: string) {
232
+ const docsData = allDocsData[pluginId]!;
233
+ const {preferredVersionName} = state[pluginId]!;
234
+
235
+ return (
236
+ docsData.versions.find(
237
+ (version) => version.name === preferredVersionName,
238
+ ) ?? null
239
+ );
240
+ }
241
+ const pluginIds = Object.keys(allDocsData);
242
+ return Object.fromEntries(
243
+ pluginIds.map((id) => [id, getPluginIdPreferredVersion(id)]),
244
+ );
245
+ }
@@ -0,0 +1,15 @@
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 {describe, expect, it} from 'vitest';
9
+ import {getDocsVersionSearchTag} from './docsSearch';
10
+
11
+ describe('getDocsVersionSearchTag', () => {
12
+ it('works', () => {
13
+ expect(getDocsVersionSearchTag('foo', 'bar')).toBe('docs-foo-bar');
14
+ });
15
+ });
@@ -0,0 +1,57 @@
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 {
9
+ useAllDocsData,
10
+ useActivePluginAndVersion,
11
+ } from '@docusaurus/plugin-content-docs/client';
12
+ import {useDocsPreferredVersionByPluginId} from './docsPreferredVersion';
13
+
14
+ /** The search tag to append as each doc's metadata. */
15
+ export function getDocsVersionSearchTag(
16
+ pluginId: string,
17
+ versionName: string,
18
+ ): string {
19
+ return `docs-${pluginId}-${versionName}`;
20
+ }
21
+
22
+ /**
23
+ * Gets the relevant docs tags to search.
24
+ * This is the logic that powers the contextual search feature.
25
+ *
26
+ * If user is browsing Android 1.4 docs, he'll get presented with:
27
+ * - Android '1.4' docs
28
+ * - iOS 'preferred | latest' docs
29
+ *
30
+ * The result is generic and not coupled to Algolia/DocSearch on purpose.
31
+ */
32
+ export function useDocsContextualSearchTags(): string[] {
33
+ const allDocsData = useAllDocsData();
34
+ const activePluginAndVersion = useActivePluginAndVersion();
35
+ const docsPreferredVersionByPluginId = useDocsPreferredVersionByPluginId();
36
+
37
+ // This can't use more specialized hooks because we are mapping over all
38
+ // plugin instances.
39
+ function getDocPluginTags(pluginId: string) {
40
+ const activeVersion =
41
+ activePluginAndVersion?.activePlugin.pluginId === pluginId
42
+ ? activePluginAndVersion.activeVersion
43
+ : undefined;
44
+
45
+ const preferredVersion = docsPreferredVersionByPluginId[pluginId];
46
+
47
+ const latestVersion = allDocsData[pluginId]!.versions.find(
48
+ (v) => v.isLast,
49
+ )!;
50
+
51
+ const version = activeVersion ?? preferredVersion ?? latestVersion;
52
+
53
+ return getDocsVersionSearchTag(pluginId, version.name);
54
+ }
55
+
56
+ return [...Object.keys(allDocsData).map(getDocPluginTags)];
57
+ }
@@ -0,0 +1,50 @@
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 React, {useMemo, useContext, type ReactNode} from 'react';
9
+ import {ReactContextError} from '@docusaurus/theme-common';
10
+ import type {PropSidebar} from '@docusaurus/plugin-content-docs';
11
+
12
+ // Using a Symbol because null is a valid context value (a doc with no sidebar)
13
+ // Inspired by https://github.com/jamiebuilds/unstated-next/blob/master/src/unstated-next.tsx
14
+ const EmptyContext: unique symbol = Symbol('EmptyContext');
15
+
16
+ type ContextValue = {name: string; items: PropSidebar};
17
+
18
+ const Context = React.createContext<ContextValue | null | typeof EmptyContext>(
19
+ EmptyContext,
20
+ );
21
+
22
+ /**
23
+ * Provide the current sidebar to your children.
24
+ */
25
+ export function DocsSidebarProvider({
26
+ children,
27
+ name,
28
+ items,
29
+ }: {
30
+ children: ReactNode;
31
+ name: string | undefined;
32
+ items: PropSidebar | undefined;
33
+ }): ReactNode {
34
+ const stableValue: ContextValue | null = useMemo(
35
+ () => (name && items ? {name, items} : null),
36
+ [name, items],
37
+ );
38
+ return <Context value={stableValue}>{children}</Context>;
39
+ }
40
+
41
+ /**
42
+ * Gets the sidebar that's currently displayed, or `null` if there isn't one
43
+ */
44
+ export function useDocsSidebar(): ContextValue | null {
45
+ const value = useContext(Context);
46
+ if (value === EmptyContext) {
47
+ throw new ReactContextError('DocsSidebarProvider');
48
+ }
49
+ return value;
50
+ }