-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
/
generateIndex.ts
159 lines (132 loc) · 3.82 KB
/
generateIndex.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import { stat, mkdir, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { cwd } from 'node:process';
import { generatePath } from '@discordjs/api-extractor-utils';
import {
ApiDeclaredItem,
ApiItemContainerMixin,
ApiItem,
ApiModel,
type ApiPackage,
ApiItemKind,
} from '@microsoft/api-extractor-model';
import {
DocNodeKind,
type DocCodeSpan,
type DocNode,
type DocParagraph,
type DocPlainText,
TSDocConfiguration,
} from '@microsoft/tsdoc';
import { TSDocConfigFile } from '@microsoft/tsdoc-config';
import { request } from 'undici';
export interface MemberJSON {
kind: string;
name: string;
path: string;
summary: string | null;
}
export const PACKAGES = ['brokers', 'builders', 'collection', 'core', 'proxy', 'rest', 'util', 'voice', 'ws'];
let idx = 0;
export function createApiModel(data: any) {
const model = new ApiModel();
const tsdocConfiguration = new TSDocConfiguration();
const tsdocConfigFile = TSDocConfigFile.loadFromObject(data.metadata.tsdocConfig);
tsdocConfigFile.configureParser(tsdocConfiguration);
const apiPackage = ApiItem.deserialize(data, {
apiJsonFilename: '',
toolPackage: data.metadata.toolPackage,
toolVersion: data.metadata.toolVersion,
versionToDeserialize: data.metadata.schemaVersion,
tsdocConfiguration,
}) as ApiPackage;
model.addMember(apiPackage);
return model;
}
/**
* Attempts to resolve the summary text for the given item.
*
* @param item - The API item to resolve the summary text for.
*/
export function tryResolveSummaryText(item: ApiDeclaredItem): string | null {
if (!item.tsdocComment) {
return null;
}
const { summarySection } = item.tsdocComment;
let retVal = '';
// Recursively visit the nodes in the summary section.
const visitTSDocNode = (node: DocNode) => {
switch (node.kind) {
case DocNodeKind.CodeSpan:
retVal += (node as DocCodeSpan).code;
break;
case DocNodeKind.PlainText:
retVal += (node as DocPlainText).text;
break;
case DocNodeKind.Section:
case DocNodeKind.Paragraph: {
for (const child of (node as DocParagraph).nodes) {
visitTSDocNode(child);
}
break;
}
default: // We'll ignore all other nodes.
break;
}
};
for (const node of summarySection.nodes) {
visitTSDocNode(node);
}
if (retVal === '') {
return null;
}
return retVal;
}
export function visitNodes(item: ApiItem, tag: string) {
const members: (MemberJSON & { id: number })[] = [];
for (const member of item.members) {
if (!(member instanceof ApiDeclaredItem)) {
continue;
}
if (member.kind === ApiItemKind.Constructor) {
continue;
}
if (ApiItemContainerMixin.isBaseClassOf(member)) {
members.push(...visitNodes(member, tag));
}
members.push({
id: idx++,
name: member.displayName,
kind: member.kind,
summary: tryResolveSummaryText(member) ?? '',
path: generatePath(member.getHierarchy(), tag),
});
}
return members;
}
export async function generateIndex(model: ApiModel, packageName: string, tag = 'main') {
const members = visitNodes(model.tryGetPackageByName(packageName)!.entryPoints[0]!, tag);
const dir = 'searchIndex';
try {
(await stat(join(cwd(), 'public', dir))).isDirectory();
} catch {
await mkdir(join(cwd(), 'public', dir));
}
await writeFile(
join(cwd(), 'public', dir, `${packageName}-${tag}-index.json`),
JSON.stringify(members, undefined, 2),
);
}
export async function generateAllIndicies() {
for (const pkg of PACKAGES) {
const response = await request(`https://docs.discordjs.dev/api/info?package=${pkg}`);
const versions = await response.body.json();
for (const version of versions) {
idx = 0;
const versionRes = await request(`https://docs.discordjs.dev/docs/${pkg}/${version}.api.json`);
const data = await versionRes.body.json();
const model = createApiModel(data);
await generateIndex(model, pkg, version);
}
}
}