forked from milesj/docusaurus-plugin-typedoc-api
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sidebar.ts
135 lines (111 loc) · 3.41 KB
/
sidebar.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { JSONOutput } from 'typedoc';
import { normalizeUrl } from '@docusaurus/utils';
import { DeclarationReflectionMap, PackageReflectionGroup, SidebarItem } from '../types';
import { removeScopes } from '../utils/links';
import { createReflectionMap } from './data';
export function groupSidebarItems(
map: DeclarationReflectionMap,
groups: JSONOutput.ReflectionGroup[],
): SidebarItem[] {
const items: SidebarItem[] = [];
const categories = groups.flatMap(group => {
// Prefer @category annotation over built-in grouping
return group.categories || group
});
const sortedCategories = categories.sort((a, b) => a.title.localeCompare(b.title));
function getLastItemInGroup(index: number) {
const length = sortedCategories[index]?.children?.length;
return length ? sortedCategories[index]?.children?.[length - 1] : undefined;
}
sortedCategories.forEach((group, groupIndex) => {
const { children } = group;
if (!children || children.length === 0) {
return;
}
items.push({
collapsed: true,
collapsible: true,
items: children.map((id, index) => {
const child = map[id];
// We map previous/next from here since the sidebar is grouped by type,
// and we only want to link based on this order.
const previousId = index === 0 ? getLastItemInGroup(groupIndex - 1) : children[index - 1];
const nextId =
index === children.length - 1
? groups[groupIndex + 1]?.children?.[0]
: children[index + 1];
if (previousId) {
child.previousId = previousId;
}
if (nextId) {
child.nextId = nextId;
}
return {
href: child.permalink,
label: child.name,
type: 'link',
};
}),
label: group.title,
type: 'category',
});
});
return items;
}
export function extractReflectionSidebar(pkg: JSONOutput.ProjectReflection): SidebarItem[] {
return pkg.groups ? groupSidebarItems(createReflectionMap(pkg.children), pkg.groups) : [];
}
export function extractSidebar(
packages: PackageReflectionGroup[],
scopes: string[],
changelogs: boolean,
): SidebarItem[] {
if (packages.length === 0) {
return [];
}
const items: SidebarItem[] = packages.map((pkg) => {
const subItems: SidebarItem[] = [];
pkg.entryPoints.forEach((entry) => {
// Index entry point should always bubble up reflection groups
if (entry.index) {
subItems.push(...extractReflectionSidebar(entry.reflection));
// Otherwise nest non-index entry points behind categories
} else {
subItems.push({
collapsed: true,
collapsible: true,
items: extractReflectionSidebar(entry.reflection),
label: entry.label,
type: 'category',
});
}
});
// Always include the overview as the 1st item
const indexHref = pkg.entryPoints.find((entry) => entry.index)?.reflection.permalink ?? '';
subItems.unshift({
href: indexHref,
label: 'Overview',
type: 'link',
});
if (pkg.changelogPath && changelogs) {
subItems.push({
href: normalizeUrl([indexHref, 'changelog']),
label: 'Changelog',
type: 'link',
});
}
return {
collapsed: true,
collapsible: true,
items: subItems,
label: removeScopes(pkg.packageName, scopes),
type: 'category',
} as const;
});
const sidebar = items.filter((item) => 'items' in item && items.length > 0);
// Collapse sidebar when only 1 package
if (packages.length === 1 && sidebar.length === 1 && sidebar[0].type === 'category') {
return sidebar[0].items;
}
return sidebar;
}