@apify/docusaurus-plugin-typedoc-api 3.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 (165) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +290 -0
  3. package/assets/styles-8ad572ec.css +303 -0
  4. package/lib/components/AnchorLink.js +22 -0
  5. package/lib/components/AnchorLink.js.map +1 -0
  6. package/lib/components/ApiChangelog.js +28 -0
  7. package/lib/components/ApiChangelog.js.map +1 -0
  8. package/lib/components/ApiDataContext.js +16 -0
  9. package/lib/components/ApiDataContext.js.map +1 -0
  10. package/lib/components/ApiIndex.js +80 -0
  11. package/lib/components/ApiIndex.js.map +1 -0
  12. package/lib/components/ApiItem.js +86 -0
  13. package/lib/components/ApiItem.js.map +1 -0
  14. package/lib/components/ApiItemLayout.js +69 -0
  15. package/lib/components/ApiItemLayout.js.map +1 -0
  16. package/lib/components/ApiPage.js +69 -0
  17. package/lib/components/ApiPage.js.map +1 -0
  18. package/lib/components/Breadcrumb.js +38 -0
  19. package/lib/components/Breadcrumb.js.map +1 -0
  20. package/lib/components/Comment.js +56 -0
  21. package/lib/components/Comment.js.map +1 -0
  22. package/lib/components/CommentBadges.js +35 -0
  23. package/lib/components/CommentBadges.js.map +1 -0
  24. package/lib/components/DefaultValue.js +49 -0
  25. package/lib/components/DefaultValue.js.map +1 -0
  26. package/lib/components/Flags.js +27 -0
  27. package/lib/components/Flags.js.map +1 -0
  28. package/lib/components/Footer.js +18 -0
  29. package/lib/components/Footer.js.map +1 -0
  30. package/lib/components/Hierarchy.js +27 -0
  31. package/lib/components/Hierarchy.js.map +1 -0
  32. package/lib/components/Icon.js +27 -0
  33. package/lib/components/Icon.js.map +1 -0
  34. package/lib/components/Index.js +87 -0
  35. package/lib/components/Index.js.map +1 -0
  36. package/lib/components/Markdown.js +204 -0
  37. package/lib/components/Markdown.js.map +1 -0
  38. package/lib/components/Member.js +68 -0
  39. package/lib/components/Member.js.map +1 -0
  40. package/lib/components/MemberDeclaration.js +64 -0
  41. package/lib/components/MemberDeclaration.js.map +1 -0
  42. package/lib/components/MemberGetterSetter.js +61 -0
  43. package/lib/components/MemberGetterSetter.js.map +1 -0
  44. package/lib/components/MemberReference.js +38 -0
  45. package/lib/components/MemberReference.js.map +1 -0
  46. package/lib/components/MemberSignatureBody.js +91 -0
  47. package/lib/components/MemberSignatureBody.js.map +1 -0
  48. package/lib/components/MemberSignatureTitle.js +52 -0
  49. package/lib/components/MemberSignatureTitle.js.map +1 -0
  50. package/lib/components/MemberSignatures.js +61 -0
  51. package/lib/components/MemberSignatures.js.map +1 -0
  52. package/lib/components/MemberSources.js +33 -0
  53. package/lib/components/MemberSources.js.map +1 -0
  54. package/lib/components/Members.js +51 -0
  55. package/lib/components/Members.js.map +1 -0
  56. package/lib/components/MembersGroup.js +39 -0
  57. package/lib/components/MembersGroup.js.map +1 -0
  58. package/lib/components/Parameter.js +145 -0
  59. package/lib/components/Parameter.js.map +1 -0
  60. package/lib/components/Reflection.js +112 -0
  61. package/lib/components/Reflection.js.map +1 -0
  62. package/lib/components/SourceLink.js +37 -0
  63. package/lib/components/SourceLink.js.map +1 -0
  64. package/lib/components/Type.js +341 -0
  65. package/lib/components/Type.js.map +1 -0
  66. package/lib/components/TypeAndParent.js +27 -0
  67. package/lib/components/TypeAndParent.js.map +1 -0
  68. package/lib/components/TypeParameters.js +36 -0
  69. package/lib/components/TypeParameters.js.map +1 -0
  70. package/lib/components/TypeParametersGeneric.js +27 -0
  71. package/lib/components/TypeParametersGeneric.js.map +1 -0
  72. package/lib/components/VersionBanner.js +39 -0
  73. package/lib/components/VersionBanner.js.map +1 -0
  74. package/lib/hooks/useBreadcrumbs.js +9 -0
  75. package/lib/hooks/useBreadcrumbs.js.map +1 -0
  76. package/lib/hooks/useGitRefName.js +9 -0
  77. package/lib/hooks/useGitRefName.js.map +1 -0
  78. package/lib/hooks/useMinimalLayout.js +9 -0
  79. package/lib/hooks/useMinimalLayout.js.map +1 -0
  80. package/lib/hooks/useReflection.js +19 -0
  81. package/lib/hooks/useReflection.js.map +1 -0
  82. package/lib/hooks/useReflectionMap.js +9 -0
  83. package/lib/hooks/useReflectionMap.js.map +1 -0
  84. package/lib/index.js +320 -0
  85. package/lib/index.js.map +1 -0
  86. package/lib/markdownLoader.js +11 -0
  87. package/lib/markdownLoader.js.map +1 -0
  88. package/lib/plugin/data.js +332 -0
  89. package/lib/plugin/data.js.map +1 -0
  90. package/lib/plugin/sidebar.js +105 -0
  91. package/lib/plugin/sidebar.js.map +1 -0
  92. package/lib/plugin/structure/0.23.js +48 -0
  93. package/lib/plugin/structure/0.23.js.map +1 -0
  94. package/lib/plugin/url.js +49 -0
  95. package/lib/plugin/url.js.map +1 -0
  96. package/lib/plugin/version.js +83 -0
  97. package/lib/plugin/version.js.map +1 -0
  98. package/lib/types.js +2 -0
  99. package/lib/types.js.map +1 -0
  100. package/lib/utils/hierarchy.js +35 -0
  101. package/lib/utils/hierarchy.js.map +1 -0
  102. package/lib/utils/icons.js +124 -0
  103. package/lib/utils/icons.js.map +1 -0
  104. package/lib/utils/links.js +10 -0
  105. package/lib/utils/links.js.map +1 -0
  106. package/lib/utils/markdown.js +69 -0
  107. package/lib/utils/markdown.js.map +1 -0
  108. package/lib/utils/visibility.js +25 -0
  109. package/lib/utils/visibility.js.map +1 -0
  110. package/package.json +57 -0
  111. package/src/components/AnchorLink.tsx +14 -0
  112. package/src/components/ApiChangelog.tsx +26 -0
  113. package/src/components/ApiDataContext.ts +17 -0
  114. package/src/components/ApiIndex.tsx +109 -0
  115. package/src/components/ApiItem.tsx +110 -0
  116. package/src/components/ApiItemLayout.tsx +96 -0
  117. package/src/components/ApiPage.tsx +78 -0
  118. package/src/components/Breadcrumb.tsx +41 -0
  119. package/src/components/Comment.tsx +74 -0
  120. package/src/components/CommentBadges.tsx +40 -0
  121. package/src/components/DefaultValue.tsx +48 -0
  122. package/src/components/Flags.tsx +29 -0
  123. package/src/components/Footer.tsx +13 -0
  124. package/src/components/Hierarchy.tsx +27 -0
  125. package/src/components/Icon.tsx +20 -0
  126. package/src/components/Index.tsx +109 -0
  127. package/src/components/Markdown.tsx +241 -0
  128. package/src/components/Member.tsx +64 -0
  129. package/src/components/MemberDeclaration.tsx +67 -0
  130. package/src/components/MemberGetterSetter.tsx +69 -0
  131. package/src/components/MemberReference.tsx +43 -0
  132. package/src/components/MemberSignatureBody.tsx +121 -0
  133. package/src/components/MemberSignatureTitle.tsx +65 -0
  134. package/src/components/MemberSignatures.tsx +64 -0
  135. package/src/components/MemberSources.tsx +42 -0
  136. package/src/components/Members.tsx +62 -0
  137. package/src/components/MembersGroup.tsx +47 -0
  138. package/src/components/Parameter.tsx +165 -0
  139. package/src/components/README.md +9 -0
  140. package/src/components/Reflection.tsx +136 -0
  141. package/src/components/SourceLink.tsx +46 -0
  142. package/src/components/Type.tsx +377 -0
  143. package/src/components/TypeAndParent.tsx +26 -0
  144. package/src/components/TypeParameters.tsx +37 -0
  145. package/src/components/TypeParametersGeneric.tsx +25 -0
  146. package/src/components/VersionBanner.tsx +44 -0
  147. package/src/components/styles.css +303 -0
  148. package/src/hooks/useBreadcrumbs.ts +6 -0
  149. package/src/hooks/useGitRefName.ts +6 -0
  150. package/src/hooks/useMinimalLayout.ts +6 -0
  151. package/src/hooks/useReflection.ts +18 -0
  152. package/src/hooks/useReflectionMap.ts +7 -0
  153. package/src/index.ts +420 -0
  154. package/src/markdownLoader.ts +10 -0
  155. package/src/plugin/data.ts +389 -0
  156. package/src/plugin/sidebar.ts +139 -0
  157. package/src/plugin/structure/0.23.ts +58 -0
  158. package/src/plugin/url.ts +49 -0
  159. package/src/plugin/version.ts +118 -0
  160. package/src/types.ts +165 -0
  161. package/src/utils/hierarchy.ts +46 -0
  162. package/src/utils/icons.ts +103 -0
  163. package/src/utils/links.ts +10 -0
  164. package/src/utils/markdown.ts +82 -0
  165. package/src/utils/visibility.ts +31 -0
@@ -0,0 +1,389 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import * as TypeDoc from 'typedoc';
4
+ import { JSONOutput, ReflectionKind } from 'typedoc';
5
+ import ts from 'typescript';
6
+ import { normalizeUrl } from '@docusaurus/utils';
7
+ import type {
8
+ DeclarationReflectionMap,
9
+ DocusaurusPluginTypeDocApiOptions,
10
+ PackageReflectionGroup,
11
+ ResolvedPackageConfig,
12
+ } from '../types';
13
+ import { migrateToVersion0230 } from './structure/0.23';
14
+ import { getKindSlug, getPackageSlug, joinUrl } from './url';
15
+
16
+ function shouldEmit(projectRoot: string, tsconfigPath: string) {
17
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
18
+ const { config, error } = ts.readConfigFile(tsconfigPath, (name) =>
19
+ fs.readFileSync(name, 'utf8'),
20
+ );
21
+
22
+ if (error) {
23
+ throw new Error(`Failed to load ${tsconfigPath}`);
24
+ }
25
+
26
+ const result = ts.parseJsonConfigFileContent(config, ts.sys, projectRoot, {}, tsconfigPath);
27
+
28
+ if (result.errors.length > 0) {
29
+ throw new Error(`Failed to parse ${tsconfigPath}`);
30
+ }
31
+
32
+ return result.projectReferences && result.projectReferences.length > 0 ? 'docs' : 'none';
33
+ }
34
+
35
+ // Persist build state as a global, since the plugin is re-evaluated every hot reload.
36
+ // Because of this, we can't use state in the plugin or module scope.
37
+ if (!global.typedocBuild) {
38
+ global.typedocBuild = { count: 0 };
39
+ }
40
+
41
+ export async function generateJson(
42
+ projectRoot: string,
43
+ entryPoints: string[],
44
+ outFile: string,
45
+ options: DocusaurusPluginTypeDocApiOptions,
46
+ ): Promise<boolean> {
47
+ /* eslint-disable sort-keys */
48
+
49
+ // Running the TypeDoc compiler is pretty slow...
50
+ // We should only load on the 1st build, and use cache for subsequent reloads.
51
+ if (global.typedocBuild.count > 0 && fs.existsSync(outFile)) {
52
+ return true;
53
+ }
54
+
55
+ const app = new TypeDoc.Application();
56
+ const tsconfig = path.join(projectRoot, options.tsconfigName!);
57
+
58
+ app.options.addReader(new TypeDoc.TSConfigReader());
59
+ app.options.addReader(new TypeDoc.TypeDocReader());
60
+
61
+ app.bootstrap({
62
+ skipErrorChecking: true,
63
+ // Only emit when using project references
64
+ emit: shouldEmit(projectRoot, tsconfig),
65
+ // Only document the public API by default
66
+ excludeExternals: true,
67
+ excludeInternal: true,
68
+ excludePrivate: true,
69
+ excludeProtected: true,
70
+ // Enable verbose logging when debugging
71
+ logLevel: options.debug ? 'Verbose' : 'Info',
72
+ inlineTags: [
73
+ '@link',
74
+ '@inheritDoc',
75
+ '@label',
76
+ '@linkcode',
77
+ '@linkplain',
78
+ '@apilink',
79
+ '@doclink',
80
+ ] as `@${string}`[],
81
+ ...options.typedocOptions,
82
+ // Control how config and packages are detected
83
+ tsconfig,
84
+ entryPoints: entryPoints.map((ep) => path.join(projectRoot, ep)),
85
+ entryPointStrategy: 'expand',
86
+ exclude: options.exclude,
87
+ // We use a fake category title so that we can fallback to the parent group
88
+ defaultCategory: 'CATEGORY',
89
+ });
90
+
91
+ const project = app.convert();
92
+
93
+ if (project) {
94
+ await app.generateJson(project, outFile);
95
+
96
+ global.typedocBuild.count += 1;
97
+
98
+ return true;
99
+ }
100
+
101
+ return false;
102
+ }
103
+
104
+ export function createReflectionMap(
105
+ items: JSONOutput.DeclarationReflection[] = [],
106
+ ): DeclarationReflectionMap {
107
+ const map: DeclarationReflectionMap = {};
108
+
109
+ items.forEach((item) => {
110
+ map[item.id] = item;
111
+ });
112
+
113
+ return map;
114
+ }
115
+
116
+ export function loadPackageJsonAndDocs(
117
+ initialDir: string,
118
+ pkgFileName: string = 'package.json',
119
+ readmeFileName: string = 'README.md',
120
+ changelogFileName: string = 'CHANGELOG.md',
121
+ ) {
122
+ let currentDir = initialDir;
123
+
124
+ while (!fs.existsSync(path.join(currentDir, pkgFileName))) {
125
+ currentDir = path.dirname(currentDir);
126
+ }
127
+
128
+ const readmePath = path.join(currentDir, readmeFileName);
129
+ const changelogPath = path.join(currentDir, changelogFileName);
130
+
131
+ return {
132
+ packageJson: JSON.parse(fs.readFileSync(path.join(currentDir, pkgFileName), 'utf8')) as {
133
+ name: string;
134
+ version: string;
135
+ },
136
+ readmePath: fs.existsSync(readmePath) ? readmePath : '',
137
+ changelogPath: fs.existsSync(changelogPath) ? changelogPath : '',
138
+ };
139
+ }
140
+
141
+ export function addMetadataToReflections(
142
+ project: JSONOutput.ProjectReflection,
143
+ packageSlug: string,
144
+ urlPrefix: string,
145
+ ): JSONOutput.ProjectReflection {
146
+ const permalink = `/${joinUrl(urlPrefix, packageSlug)}`;
147
+
148
+ if (project.children) {
149
+ // eslint-disable-next-line no-param-reassign
150
+ project.children = project.children.map((child) => {
151
+ migrateToVersion0230(child);
152
+
153
+ const kindSlugPart = getKindSlug(child);
154
+ const childSlug = kindSlugPart ? `/${kindSlugPart}/${child.name}` : `#${child.name}`;
155
+ const childPermalink = permalink + childSlug;
156
+
157
+ // We need to go another level deeper and only use fragments
158
+ if (child.kind === ReflectionKind.Namespace && child.children) {
159
+ // eslint-disable-next-line no-param-reassign
160
+ child.children = child.children.map((grandChild) => ({
161
+ ...grandChild,
162
+ permalink: normalizeUrl([`${childPermalink}#${grandChild.name}`]),
163
+ }));
164
+ }
165
+
166
+ return {
167
+ ...child,
168
+ permalink: normalizeUrl([childPermalink]),
169
+ };
170
+ });
171
+ }
172
+
173
+ return {
174
+ ...project,
175
+ permalink: normalizeUrl([permalink]),
176
+ };
177
+ }
178
+
179
+ function mergeReflections(base: JSONOutput.ProjectReflection, next: JSONOutput.ProjectReflection) {
180
+ if (Array.isArray(base.children) && Array.isArray(next.children)) {
181
+ base.children.push(...next.children);
182
+ }
183
+
184
+ if (Array.isArray(base.groups) && Array.isArray(next.groups)) {
185
+ next.groups.forEach((group) => {
186
+ const baseGroup = base.groups?.find((g) => g.title === group.title);
187
+
188
+ if (baseGroup) {
189
+ baseGroup.children?.push(...(group.children ?? []));
190
+ } else {
191
+ base.groups?.push(group);
192
+ }
193
+ });
194
+
195
+ // We can remove refs since were merging all reflections into one
196
+ // eslint-disable-next-line no-param-reassign
197
+ base.groups = base.groups.filter((group) => group.title !== 'References');
198
+ }
199
+ }
200
+
201
+ function sortReflectionGroups(reflections: JSONOutput.ProjectReflection[]) {
202
+ reflections.forEach((reflection) => {
203
+ const map = createReflectionMap(reflection.children);
204
+ const sort = (a: number, b: number) => (map[a].name < map[b].name ? -1 : 1);
205
+
206
+ reflection.categories?.forEach((category) => {
207
+ category.children?.sort(sort);
208
+ });
209
+
210
+ reflection.groups?.forEach((group) => {
211
+ group.children?.sort(sort);
212
+
213
+ group.categories?.forEach((category) => {
214
+ category.children?.sort(sort);
215
+ });
216
+ });
217
+ });
218
+ }
219
+
220
+ function matchesEntryPoint(
221
+ sourceFile: string,
222
+ entryPoint: string,
223
+ { deep, single }: { deep: boolean; single: boolean },
224
+ ): boolean {
225
+ // Single package
226
+ if (single) {
227
+ return (
228
+ // src/index.ts === src/index.ts
229
+ (!deep && sourceFile === entryPoint) ||
230
+ // index.ts === src/index.ts
231
+ (!deep && sourceFile === path.basename(entryPoint)) ||
232
+ // some/deep/file.ts === ...
233
+ deep
234
+ );
235
+ }
236
+
237
+ // Multiple packages
238
+ return (
239
+ // packages/foo/src/index.ts === packages/foo/src/index.ts
240
+ // foo/src/index.ts ~ packages/foo/src/index.ts
241
+ (!deep && (sourceFile === entryPoint || entryPoint.endsWith(sourceFile))) ||
242
+ // packages/foo/src/some/deep/file.ts === packages/foo/src/
243
+ (deep && sourceFile.startsWith(entryPoint))
244
+ );
245
+ }
246
+
247
+ function extractReflectionModules(
248
+ project: JSONOutput.ProjectReflection,
249
+ isSinglePackage: boolean,
250
+ ): JSONOutput.ProjectReflection[] {
251
+ const modules: JSONOutput.ProjectReflection[] = [];
252
+
253
+ const inheritChildren = () => {
254
+ project.children?.forEach((child) => {
255
+ if (child.kind === ReflectionKind.Module) {
256
+ modules.push(child);
257
+ }
258
+ });
259
+ };
260
+
261
+ // Single packages are extremely difficult, as the TypeDoc structure is
262
+ // different for every kind of package entry point pattern
263
+ if (isSinglePackage) {
264
+ const hasNoModules = project.children?.every((child) => child.kind !== ReflectionKind.Module);
265
+
266
+ if (hasNoModules) {
267
+ // No "module" children:
268
+ // - Polyrepos
269
+ // - Monorepos with 1 package
270
+ modules.push(project);
271
+ } else {
272
+ // Has "module" children:
273
+ // - Polyrepos with deep imports
274
+ // - Polyrepos with multi-imports
275
+ // - Monorepos
276
+ inheritChildren();
277
+ }
278
+
279
+ // Multiple packages are extremely simple, as every package is a module reflection
280
+ // as a child on the top-level project reflection
281
+ } else {
282
+ inheritChildren();
283
+ }
284
+
285
+ return modules;
286
+ }
287
+
288
+ export function flattenAndGroupPackages(
289
+ packageConfigs: ResolvedPackageConfig[],
290
+ project: JSONOutput.ProjectReflection,
291
+ urlPrefix: string,
292
+ options: DocusaurusPluginTypeDocApiOptions,
293
+ versioned: boolean = false,
294
+ ): PackageReflectionGroup[] {
295
+ const isSinglePackage = packageConfigs.length === 1;
296
+ const modules = extractReflectionModules(project, isSinglePackage);
297
+
298
+ // Loop through every TypeDoc module and group based on package and entry point
299
+ const packages: Record<string, PackageReflectionGroup> = {};
300
+ const packagesWithDeepImports: JSONOutput.ProjectReflection[] = [];
301
+
302
+ modules.forEach((mod) => {
303
+ const relSourceFile = mod.sources?.[0]?.fileName ?? '';
304
+
305
+ packageConfigs.some((cfg) =>
306
+ Object.entries(cfg.entryPoints).some(([importPath, entry]) => {
307
+ const relEntryPoint = joinUrl(cfg.packagePath, entry.path);
308
+ const isUsingDeepImports = !entry.path.match(/\.tsx?$/);
309
+
310
+ if (
311
+ !matchesEntryPoint(relSourceFile, relEntryPoint, {
312
+ deep: isUsingDeepImports,
313
+ single: isSinglePackage,
314
+ })
315
+ ) {
316
+ return false;
317
+ }
318
+
319
+ // We have a matching entry point, so store the record
320
+ if (!packages[cfg.packagePath]) {
321
+ const { packageJson, readmePath, changelogPath } = loadPackageJsonAndDocs(
322
+ path.join(options.projectRoot, cfg.packagePath),
323
+ options.packageJsonName,
324
+ options.readmeName,
325
+ options.changelogName,
326
+ );
327
+
328
+ packages[cfg.packagePath] = {
329
+ entryPoints: [],
330
+ packageName: (versioned && cfg.packageName) || packageJson.name,
331
+ packageVersion: (versioned && cfg.packageVersion) || packageJson.version,
332
+ readmePath,
333
+ changelogPath,
334
+ };
335
+
336
+ // eslint-disable-next-line no-param-reassign
337
+ cfg.packageName = packages[cfg.packagePath].packageName;
338
+ // eslint-disable-next-line no-param-reassign
339
+ cfg.packageVersion = packages[cfg.packagePath].packageVersion;
340
+ }
341
+
342
+ // Add metadata to package and children reflections
343
+ const urlSlug = getPackageSlug(cfg, importPath, isSinglePackage);
344
+ const reflection = addMetadataToReflections(mod, urlSlug, urlPrefix);
345
+ const existingEntry = packages[cfg.packagePath].entryPoints.find(
346
+ (ep) => ep.urlSlug === urlSlug,
347
+ );
348
+
349
+ if (existingEntry) {
350
+ if (isUsingDeepImports) {
351
+ mergeReflections(existingEntry.reflection, reflection);
352
+ } else {
353
+ // eslint-disable-next-line no-console
354
+ console.error(`Entry point ${urlSlug} already defined. How did you get here?`);
355
+ }
356
+ } else {
357
+ packages[cfg.packagePath].entryPoints.push({
358
+ index: importPath === 'index',
359
+ label: entry.label,
360
+ reflection,
361
+ urlSlug,
362
+ });
363
+
364
+ if (isUsingDeepImports) {
365
+ packagesWithDeepImports.push(reflection);
366
+ }
367
+ }
368
+
369
+ // Update the reflection name since its useless
370
+ reflection.name =
371
+ importPath === 'index'
372
+ ? packages[cfg.packagePath].packageName
373
+ : joinUrl(packages[cfg.packagePath].packageName, importPath);
374
+
375
+ return true;
376
+ }),
377
+ );
378
+ });
379
+
380
+ // Since we merged multiple reflections together, we'll need to sort groups manually
381
+ sortReflectionGroups(packagesWithDeepImports);
382
+
383
+ // Sort packages by name
384
+ return Object.values(packages).sort((a, b) => a.packageName.localeCompare(b.packageName));
385
+ }
386
+
387
+ export function formatPackagesWithoutHostInfo(packages: PackageReflectionGroup[]) {
388
+ return packages.map(({ changelogPath, readmePath, ...pkg }) => pkg);
389
+ }
@@ -0,0 +1,139 @@
1
+ import { JSONOutput } from 'typedoc';
2
+ import { normalizeUrl } from '@docusaurus/utils';
3
+ import type {
4
+ DeclarationReflectionMap,
5
+ DocusaurusPluginTypeDocApiOptions,
6
+ PackageReflectionGroup,
7
+ SidebarItem,
8
+ } from '../types';
9
+ import { removeScopes } from '../utils/links';
10
+ import { createReflectionMap } from './data';
11
+
12
+ export function groupSidebarItems(
13
+ map: DeclarationReflectionMap,
14
+ groups: JSONOutput.ReflectionGroup[],
15
+ ): SidebarItem[] {
16
+ const items: SidebarItem[] = [];
17
+ const sortedGroups = [...groups].sort((a, b) => a.title.localeCompare(b.title));
18
+
19
+ function getLastItemInGroup(index: number) {
20
+ const length = sortedGroups[index]?.children?.length;
21
+
22
+ return length ? sortedGroups[index]?.children?.[length - 1] : undefined;
23
+ }
24
+
25
+ sortedGroups.forEach((group, groupIndex) => {
26
+ const { children } = group;
27
+
28
+ if (!children || children.length === 0) {
29
+ return;
30
+ }
31
+
32
+ items.push({
33
+ collapsed: true,
34
+ collapsible: true,
35
+ items: children.map((id, index) => {
36
+ const child = map[id];
37
+
38
+ // We map previous/next from here since the sidebar is grouped by type,
39
+ // and we only want to link based on this order.
40
+ const previousId = index === 0 ? getLastItemInGroup(groupIndex - 1) : children[index - 1];
41
+ const nextId =
42
+ index === children.length - 1
43
+ ? groups[groupIndex + 1]?.children?.[0]
44
+ : children[index + 1];
45
+
46
+ if (previousId) {
47
+ child.previousId = previousId;
48
+ }
49
+
50
+ if (nextId) {
51
+ child.nextId = nextId;
52
+ }
53
+
54
+ return {
55
+ href: child.permalink,
56
+ label: child.name,
57
+ type: 'link',
58
+ };
59
+ }),
60
+ label: group.title,
61
+ type: 'category',
62
+ });
63
+ });
64
+
65
+ return items;
66
+ }
67
+
68
+ export function extractReflectionSidebar(pkg: JSONOutput.ProjectReflection): SidebarItem[] {
69
+ return pkg.groups ? groupSidebarItems(createReflectionMap(pkg.children), pkg.groups) : [];
70
+ }
71
+
72
+ export function extractSidebar(
73
+ packages: PackageReflectionGroup[],
74
+ scopes: string[],
75
+ changelogs: boolean,
76
+ sortSidebar: NonNullable<DocusaurusPluginTypeDocApiOptions['sortSidebar']>,
77
+ ): SidebarItem[] {
78
+ if (packages.length === 0) {
79
+ return [];
80
+ }
81
+
82
+ const items: SidebarItem[] = packages.map((pkg) => {
83
+ let subItems: SidebarItem[] = [];
84
+
85
+ pkg.entryPoints.forEach((entry) => {
86
+ // Index entry point should always bubble up reflection groups
87
+ if (entry.index) {
88
+ subItems.push(...extractReflectionSidebar(entry.reflection));
89
+ // Otherwise nest non-index entry points behind categories
90
+ } else {
91
+ subItems.push({
92
+ collapsed: true,
93
+ collapsible: true,
94
+ items: extractReflectionSidebar(entry.reflection),
95
+ label: entry.label,
96
+ type: 'category',
97
+ });
98
+ }
99
+ });
100
+
101
+ // Always include the overview as the 1st item
102
+ const indexHref = pkg.entryPoints.find((entry) => entry.index)?.reflection.permalink ?? '';
103
+
104
+ subItems = subItems.sort((a, d) =>
105
+ sortSidebar('label' in a ? a.label : '', 'label' in d ? d.label : ''),
106
+ );
107
+
108
+ subItems.unshift({
109
+ href: indexHref,
110
+ label: 'Overview',
111
+ type: 'link',
112
+ });
113
+
114
+ if (pkg.changelogPath && changelogs) {
115
+ subItems.push({
116
+ href: normalizeUrl([indexHref, 'changelog']),
117
+ label: 'Changelog',
118
+ type: 'link',
119
+ });
120
+ }
121
+
122
+ return {
123
+ collapsed: true,
124
+ collapsible: true,
125
+ items: subItems,
126
+ label: removeScopes(pkg.packageName, scopes),
127
+ type: 'category',
128
+ } as const;
129
+ });
130
+
131
+ const sidebar = items.filter((item) => 'items' in item && items.length > 0);
132
+
133
+ // Collapse sidebar when only 1 package
134
+ if (packages.length === 1 && sidebar.length === 1 && sidebar[0].type === 'category') {
135
+ return sidebar[0].items;
136
+ }
137
+
138
+ return sidebar;
139
+ }
@@ -0,0 +1,58 @@
1
+ /* eslint-disable no-param-reassign */
2
+
3
+ import { JSONOutput } from 'typedoc';
4
+
5
+ interface OldComment {
6
+ shortText?: string;
7
+ text?: string;
8
+ tags?: { tag: string; text: string }[];
9
+ }
10
+
11
+ interface OldDeclarationReflection {
12
+ typeParameter?: JSONOutput.TypeParameterReflection[];
13
+ }
14
+
15
+ // https://github.com/TypeStrong/typedoc/releases/tag/v0.23.0
16
+ // https://github.com/milesj/docusaurus-plugin-typedoc-api/pull/50
17
+ export function migrateToVersion0230(reflection: JSONOutput.DeclarationReflection) {
18
+ if (Array.isArray(reflection.getSignature)) {
19
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
20
+ reflection.getSignature = reflection.getSignature[0];
21
+ }
22
+
23
+ if (Array.isArray(reflection.setSignature)) {
24
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
25
+ reflection.setSignature = reflection.setSignature[0];
26
+ }
27
+
28
+ if ('typeParameter' in reflection) {
29
+ reflection.typeParameters = (reflection as OldDeclarationReflection).typeParameter;
30
+ }
31
+
32
+ if (
33
+ reflection.comment &&
34
+ ('shortText' in reflection.comment ||
35
+ 'text' in reflection.comment ||
36
+ 'tags' in reflection.comment)
37
+ ) {
38
+ const comment = reflection.comment as OldComment;
39
+ const summary: JSONOutput.CommentDisplayPart[] = [];
40
+
41
+ if (comment.shortText) {
42
+ summary.push({ kind: 'text', text: comment.shortText });
43
+ }
44
+
45
+ if (comment.text) {
46
+ summary.push({ kind: 'text', text: comment.text });
47
+ }
48
+
49
+ reflection.comment = {
50
+ blockTags: comment.tags?.map((tag) => ({
51
+ content: [{ kind: 'text', text: tag.text }],
52
+ name: tag.tag,
53
+ tag: `@${tag.tag}`,
54
+ })),
55
+ summary,
56
+ };
57
+ }
58
+ }
@@ -0,0 +1,49 @@
1
+ import path from 'path';
2
+ import { JSONOutput, ReflectionKind } from 'typedoc';
3
+ import type { ResolvedPackageConfig } from '../types';
4
+
5
+ export function joinUrl(...paths: string[]): string {
6
+ return path.join(...paths).replace(/\\/g, '/');
7
+ }
8
+
9
+ export function getKindSlug(decl: JSONOutput.DeclarationReflection): string {
10
+ switch (decl.kind) {
11
+ case ReflectionKind.Module:
12
+ return 'package';
13
+ case ReflectionKind.Namespace:
14
+ return 'namespace';
15
+ case ReflectionKind.Enum:
16
+ return 'enum';
17
+ case ReflectionKind.Function:
18
+ return 'function';
19
+ case ReflectionKind.Class:
20
+ return 'class';
21
+ case ReflectionKind.Interface:
22
+ return 'interface';
23
+ default:
24
+ return '';
25
+ }
26
+ }
27
+
28
+ export function getPackageSlug(
29
+ pkgConfig: ResolvedPackageConfig,
30
+ importPath: string,
31
+ isSinglePackage: boolean,
32
+ ): string {
33
+ // Monorepo with 1 package has special handling
34
+ if (isSinglePackage && pkgConfig.packageSlug !== '.') {
35
+ return '.';
36
+ }
37
+
38
+ // packages/foo -> foo
39
+ const slug = pkgConfig.packageSlug ?? path.basename(pkgConfig.packagePath);
40
+
41
+ // bar/baz -> bar-baz
42
+ const importName = importPath.replace(/\\/g, '-');
43
+
44
+ if (importName === 'index') {
45
+ return slug;
46
+ }
47
+
48
+ return `${slug}-${importName}`;
49
+ }