@apify/docusaurus-plugin-typedoc-api 4.2.4 → 4.2.6

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 (43) hide show
  1. package/assets/styles-8ad572ec.css +44 -0
  2. package/lib/components/ApiItem.js +53 -29
  3. package/lib/components/ApiItem.js.map +1 -1
  4. package/lib/components/ApiItemLayout.js +15 -8
  5. package/lib/components/ApiItemLayout.js.map +1 -1
  6. package/lib/components/ApiOptionsLayout.js +35 -0
  7. package/lib/components/ApiOptionsLayout.js.map +1 -0
  8. package/lib/components/Comment.js +3 -0
  9. package/lib/components/Comment.js.map +1 -1
  10. package/lib/components/Member.js +4 -1
  11. package/lib/components/Member.js.map +1 -1
  12. package/lib/components/MemberSignatureBody.js +57 -16
  13. package/lib/components/MemberSignatureBody.js.map +1 -1
  14. package/lib/components/MemberSignatureTitle.js +11 -1
  15. package/lib/components/MemberSignatureTitle.js.map +1 -1
  16. package/lib/components/Type.js +3 -1
  17. package/lib/components/Type.js.map +1 -1
  18. package/lib/index.js +4 -14
  19. package/lib/index.js.map +1 -1
  20. package/lib/plugin/data.js +38 -1
  21. package/lib/plugin/data.js.map +1 -1
  22. package/package.json +2 -1
  23. package/src/components/ApiItem.tsx +48 -32
  24. package/src/components/ApiItemLayout.tsx +11 -6
  25. package/src/components/ApiOptionsLayout.tsx +22 -0
  26. package/src/components/Comment.tsx +3 -0
  27. package/src/components/Member.tsx +6 -2
  28. package/src/components/MemberSignatureBody.tsx +67 -16
  29. package/src/components/MemberSignatureTitle.tsx +14 -1
  30. package/src/components/Type.tsx +3 -1
  31. package/src/components/styles.css +44 -0
  32. package/src/index.ts +11 -19
  33. package/src/plugin/data.ts +37 -2
  34. package/src/types.ts +5 -1
  35. package/lib/plugin/python-generator/index.js +0 -23
  36. package/lib/plugin/python-generator/index.js.map +0 -1
  37. package/lib/plugin/python-generator/pydoc-markdown.js +0 -72
  38. package/lib/plugin/python-generator/pydoc-markdown.js.map +0 -1
  39. package/lib/plugin/python-generator/transform-docs.js +0 -393
  40. package/lib/plugin/python-generator/transform-docs.js.map +0 -1
  41. package/src/plugin/python-generator/index.ts +0 -18
  42. package/src/plugin/python-generator/pydoc-markdown.ts +0 -70
  43. package/src/plugin/python-generator/transform-docs.ts +0 -417
@@ -1,417 +0,0 @@
1
- /* eslint-disable */
2
- import fs from 'fs';
3
- import { $ } from 'zx';
4
-
5
- const REPO_ROOT_PLACEHOLDER = 'REPO_ROOT_PLACEHOLDER';
6
-
7
- // TODO: Make these parametrizable (gitRepoUrls array option)
8
- const APIFY_CLIENT_REPO_URL = 'https://github.com/apify/apify-client-python';
9
- const APIFY_SDK_REPO_URL = 'https://github.com/apify/apify-sdk-python';
10
- const APIFY_SHARED_REPO_URL = 'https://github.com/apify/apify-shared-python';
11
- const CRAWLEE_PYTHON_REPO_URL = 'https://github.com/apify/crawlee-python';
12
-
13
- const REPO_URL_PER_PACKAGE = {
14
- 'apify': APIFY_SDK_REPO_URL,
15
- 'apify_client': APIFY_CLIENT_REPO_URL,
16
- 'apify_shared': APIFY_SHARED_REPO_URL,
17
- 'crawlee': CRAWLEE_PYTHON_REPO_URL,
18
- } as const;
19
-
20
- const TAG_PER_PACKAGE: Record<string, string> = {};
21
- let MODULE_SHORTCUTS: Record<string, string> = {};
22
-
23
- async function initPackageTags({
24
- moduleName
25
- }: {
26
- moduleName?: string,
27
- }) {
28
- // For each package, get the installed version, and set the tag to the corresponding version
29
- for (const pkg of ['apify', 'apify_client', 'apify_shared']) {
30
- try {
31
- const packageVersion = await $`python -c 'import ${pkg}; print(${pkg}.__version__)'`;
32
- if (packageVersion.exitCode === 0) {
33
- TAG_PER_PACKAGE[pkg] = `v${await packageVersion.text()}`;
34
- }
35
- } catch (e) {
36
- console.warn(`Failed to get version of package ${pkg}`);
37
- }
38
- }
39
-
40
- if(!moduleName) {
41
- const thisPackagePyprojectToml = fs.readFileSync('../pyproject.toml', 'utf8');
42
- moduleName = thisPackagePyprojectToml.match(/^name = "(.+)"$/m)?.[1];
43
- }
44
-
45
- // For the current package, set the tag to 'master'
46
- TAG_PER_PACKAGE[moduleName!] = 'master';
47
-
48
- return TAG_PER_PACKAGE;
49
- }
50
-
51
- async function initModuleShortcuts() {
52
- if(!fs.existsSync('./module_shortcuts.json')) {
53
- return console.warn('No module_shortcuts.json file found, skipping module shortcuts.');
54
- }
55
-
56
- MODULE_SHORTCUTS = JSON.parse(fs.readFileSync('./module_shortcuts.json', 'utf8'));
57
- }
58
-
59
- // Taken from https://github.com/TypeStrong/typedoc/blob/v0.23.24/src/lib/models/reflections/kind.ts, modified
60
- const TYPEDOC_KINDS = {
61
- 'class': {
62
- kind: 128,
63
- kindString: 'Class',
64
- },
65
- 'function': {
66
- kind: 2048,
67
- kindString: 'Method',
68
- },
69
- 'data': {
70
- kind: 1024,
71
- kindString: 'Property',
72
- },
73
- 'enum': {
74
- kind: 8,
75
- kindString: 'Enumeration',
76
- },
77
- 'enumValue': {
78
- kind: 16,
79
- kindString: 'Enumeration Member',
80
- },
81
- }
82
-
83
- const GROUP_ORDER = [
84
- 'Main Classes',
85
- 'Helper Classes',
86
- 'Errors',
87
- 'Constructors',
88
- 'Methods',
89
- 'Properties',
90
- 'Constants',
91
- 'Enumeration Members'
92
- ] as const;
93
-
94
- const groupSort = (g1: typeof GROUP_ORDER[number], g2: typeof GROUP_ORDER[number]) => {
95
- if(GROUP_ORDER.includes(g1) && GROUP_ORDER.includes(g2)){
96
- return GROUP_ORDER.indexOf(g1) - GROUP_ORDER.indexOf(g2)
97
- }
98
- return g1.localeCompare(g2);
99
- };
100
-
101
- function getGroupName(object: any) {
102
- const groupPredicates: Record<
103
- typeof GROUP_ORDER[number],
104
- (object: any) => boolean
105
- > = {
106
- 'Errors': (x) => x.name.toLowerCase().includes('error'),
107
- 'Main Classes': (x) => ['Dataset', 'KeyValueStore', 'RequestQueue'].includes(x.name) || x.name.endsWith('Crawler'),
108
- 'Helper Classes': (x) => x.kindString === 'Class',
109
- 'Methods': (x) => x.kindString === 'Method',
110
- 'Constructors': (x) => x.kindString === 'Constructor',
111
- 'Properties': (x) => x.kindString === 'Property',
112
- 'Constants': (x) => x.kindString === 'Enumeration',
113
- 'Enumeration Members': (x) => x.kindString === 'Enumeration Member',
114
- };
115
-
116
- const [group] = Object.entries(groupPredicates).find(
117
- ([_, predicate]) => predicate(object)
118
- )!;
119
-
120
- return group;
121
- }
122
-
123
- // Strips the Optional[] type from the type string, and replaces generic types with just the main type
124
- function getBaseType(type: any) {
125
- return type?.replace(/Optional\[(.*)\]/g, '$1').replace('ListPage[Dict]', 'ListPage');
126
- }
127
-
128
- // Returns whether a type is a custom class, or a primitive type
129
- function isCustomClass(type: string) {
130
- return !['dict', 'list', 'str', 'int', 'float', 'bool'].includes(type.toLowerCase());
131
- }
132
-
133
- // Infer the Typedoc type from the docspec type
134
- function inferTypedocType(docspecType: any): Record<string, any> | undefined {
135
- const typeWithoutOptional = getBaseType(docspecType);
136
- if (!typeWithoutOptional) {
137
- return undefined;
138
- }
139
-
140
- // Typically, if a type is a custom class, it will be a reference in Typedoc
141
- return isCustomClass(typeWithoutOptional) ? {
142
- type: 'reference',
143
- name: docspecType
144
- } : {
145
- type: 'intrinsic',
146
- name: docspecType,
147
- }
148
- }
149
-
150
- // Sorts the groups of a Typedoc member, and sorts the children of each group
151
- function sortChildren(typedocMember: any) {
152
- for (let group of typedocMember.groups) {
153
- group.children
154
- .sort((a: any, b: any) => {
155
- const firstName = typedocMember.children.find((x: any) => x.id === a).name;
156
- const secondName = typedocMember.children.find((x: any) => x.id === b).name;
157
- return firstName.localeCompare(secondName);
158
- });
159
- }
160
- typedocMember.groups.sort((a: { title: typeof GROUP_ORDER[number] }, b: { title: typeof GROUP_ORDER[number] }) => groupSort(a.title, b.title));
161
- }
162
-
163
- // Parses the arguments and return value description of a method from its docstring
164
- function extractArgsAndReturns(docstring: string) {
165
- const parameters = (docstring
166
- .split('Args:')[1] ?? '').split('Returns:')[0] // Get the part between Args: and Returns:
167
- .split(/(^|\n)\s*([\w]+)\s*\(.*?\)\s*:\s*/) // Magic regex which splits the arguments into an array, and removes the argument types
168
- .filter(x => x.length > 1) // Remove empty strings
169
- .reduce((acc, curr, idx, arr) => { // Collect the argument names and types into an object
170
- if(idx % 2 === 0){
171
- return {...acc, [curr]: arr[idx+1]} // If the index is even, the current string is an argument name, and the next string is its type
172
- }
173
- return acc;
174
- }, {} as Record<string, string>);
175
-
176
- const returns = (docstring
177
- .split('Returns:')[1] ?? '').split('Raises:')[0] // Get the part between Returns: and Raises:
178
- .split(':')[1]?.trim() || undefined; // Split the return value into its type and description, return description
179
-
180
-
181
- return { parameters, returns };
182
- }
183
-
184
- // Objects with decorators named 'ignore_docs' or with empty docstrings will be ignored
185
- function isHidden(member: any) {
186
- return member.decorations?.some((d: { name: string }) => d.name === 'ignore_docs') || member.name === 'ignore_docs';
187
- }
188
-
189
- // Each object in the Typedoc structure has an unique ID,
190
- // we'll just increment it for each object we convert
191
- let oid = 1;
192
-
193
- const symbolIdMap: { qualifiedName: string, sourceFileName: string }[] = [];
194
-
195
- // Converts a docspec object to a Typedoc object, including all its children
196
- function convertObject(obj: any, parent: any, module: any) {
197
- const rootModuleName: string = module.name.split('.')[0];
198
- for (let member of obj.members ?? []) {
199
- let typedocKind = TYPEDOC_KINDS[member.type as keyof typeof TYPEDOC_KINDS];
200
-
201
- if(member.bases?.includes('Enum')) {
202
- typedocKind = TYPEDOC_KINDS['enum'];
203
- }
204
-
205
- let typedocType = inferTypedocType(member.datatype);
206
-
207
- if (member.decorations?.some((d: { name: string }) => ['property', 'dualproperty'].includes(d.name))) {
208
- typedocKind = TYPEDOC_KINDS['data'];
209
- typedocType = inferTypedocType(member.return_type ?? member.datatype);
210
- }
211
-
212
- if(parent.kindString === 'Enumeration') {
213
- typedocKind = TYPEDOC_KINDS['enumValue'];
214
- typedocType = {
215
- type: 'literal',
216
- value: member.value,
217
- }
218
- }
219
-
220
- if(member.type in TYPEDOC_KINDS && !isHidden(member)) {
221
- // Get the URL of the member in GitHub
222
- const repoBaseUrl = `${REPO_URL_PER_PACKAGE[rootModuleName as keyof typeof REPO_URL_PER_PACKAGE]}/blob/${TAG_PER_PACKAGE[rootModuleName] ?? 'master'}`;
223
- const filePathInRepo = member.location.filename.replace(REPO_ROOT_PLACEHOLDER, '');
224
- const fileGitHubUrl = member.location.filename.replace(REPO_ROOT_PLACEHOLDER, repoBaseUrl);
225
- const memberGitHubUrl = `${fileGitHubUrl}#L${member.location.lineno}`;
226
-
227
- symbolIdMap.push({
228
- qualifiedName: member.name,
229
- sourceFileName: filePathInRepo,
230
- });
231
-
232
- // Get the module name of the member, and check if it has a shortcut (reexport from an ancestor module)
233
- const fullName = `${module.name}.${member.name}`;
234
- let moduleName = module.name;
235
- if (fullName in MODULE_SHORTCUTS) {
236
- moduleName = MODULE_SHORTCUTS[fullName].replace(`.${member.name}`, '');
237
- }
238
-
239
- // Create the Typedoc member object
240
- let typedocMember = {
241
- id: oid++,
242
- name: member.name,
243
- module: moduleName, // This is an extension to the original Typedoc structure, to support showing where the member is exported from
244
- ...typedocKind,
245
- flags: {},
246
- comment: member.docstring ? {
247
- summary: [{
248
- kind: 'text',
249
- text: member.docstring?.content,
250
- }],
251
- } : undefined,
252
- type: typedocType,
253
- children: [],
254
- groups: [],
255
- sources: [{
256
- filename: filePathInRepo,
257
- line: member.location.lineno,
258
- character: 1,
259
- url: memberGitHubUrl,
260
- }],
261
- signatures: [] as any[],
262
- };
263
-
264
- if(typedocMember.kindString === 'Method') {
265
- const { parameters, returns } = extractArgsAndReturns(member.docstring?.content ?? '');
266
-
267
- typedocMember.signatures = [{
268
- id: oid++,
269
- name: member.name,
270
- modifiers: member.modifiers ?? [],
271
- kind: 4096,
272
- kindString: 'Call signature',
273
- flags: {},
274
- comment: member.docstring ? {
275
- summary: [{
276
- kind: 'text',
277
- text: member.docstring?.content
278
- .replace(/\**(Args|Arguments|Returns)[\s\S]+/, ''),
279
- }],
280
- blockTags: returns ? [
281
- { tag: '@returns', content: [{ kind: 'text', text: returns }] },
282
- ] : undefined,
283
- } : undefined,
284
- type: inferTypedocType(member.return_type),
285
- parameters: member.args
286
- .filter((arg: any) => (arg.name !== 'self' && arg.name !== 'cls'))
287
- .map((arg: any) => ({
288
- id: oid++,
289
- name: arg.name,
290
- kind: 32768,
291
- kindString: 'Parameter',
292
- flags: {
293
- isOptional: arg.datatype?.includes('Optional') ? 'true' : undefined,
294
- 'keyword-only': arg.type === 'KEYWORD_ONLY' ? 'true' : undefined,
295
- },
296
- type: inferTypedocType(arg.datatype),
297
- comment: parameters[arg.name] ? {
298
- summary: [{
299
- kind: 'text',
300
- text: parameters[arg.name]
301
- }]
302
- } : undefined,
303
- defaultValue: arg.default_value,
304
- })),
305
- }];
306
- }
307
-
308
- if(typedocMember.name === '__init__') {
309
- typedocMember.kind = 512;
310
- typedocMember.kindString = 'Constructor';
311
- }
312
-
313
- convertObject(member, typedocMember, module);
314
-
315
- const groupName = getGroupName(typedocMember);
316
-
317
- const group = parent.groups.find((g: { title: string }) => g.title === groupName);
318
- if (group) {
319
- group.children.push(typedocMember.id);
320
- } else {
321
- parent.groups.push({
322
- title: groupName,
323
- children: [typedocMember.id],
324
- });
325
- }
326
-
327
- sortChildren(typedocMember);
328
- parent.children.push(typedocMember);
329
- }
330
- }
331
- }
332
-
333
- export async function pydocToTypedoc({
334
- pydocFile,
335
- pydocJson,
336
- outFile,
337
- moduleName,
338
- }: {
339
- pydocFile?: string,
340
- pydocJson?: string,
341
- outFile: string,
342
- moduleName?: string,
343
- }) {
344
- await initPackageTags({ moduleName });
345
- await initModuleShortcuts();
346
-
347
- // Root object of the Typedoc structure
348
- const typedocApiReference = {
349
- 'id': 0,
350
- 'name': 'apify-client',
351
- 'kind': 1,
352
- 'kindString': 'Project',
353
- 'flags': {},
354
- 'originalName': '',
355
- 'children': [],
356
- 'groups': [],
357
- 'sources': [
358
- {
359
- 'fileName': 'src/index.ts',
360
- 'line': 1,
361
- 'character': 0,
362
- 'url': `http://example.com/blob/123456/src/dummy.py`,
363
- }
364
- ],
365
- 'symbolIdMap': {},
366
- };
367
-
368
- // Load the docspec dump files of this module and of apify-shared
369
- const thisPackageDocspecDump = pydocJson ?? fs.readFileSync(pydocFile!, 'utf8');
370
- const thisPackageModules = thisPackageDocspecDump.split('\n').filter((line) => line !== '');
371
-
372
- // Convert all the modules, store them in the root object
373
- for (const module of [...thisPackageModules]) {
374
- const parsedModule = JSON.parse(module);
375
- convertObject(parsedModule, typedocApiReference, parsedModule);
376
- };
377
-
378
- // Recursively fix references (collect names->ids of all the named entities and then inject those in the reference objects)
379
- const namesToIds: Record<string, string> = {};
380
- function collectIds(obj: Record<string, any>) {
381
- for (const child of obj.children ?? []) {
382
- namesToIds[child.name] = child.id;
383
- collectIds(child);
384
- }
385
- }
386
- collectIds(typedocApiReference);
387
-
388
- function fixRefs(obj: Record<string, any>) {
389
- for (const child of obj.children ?? []) {
390
- if (child.type?.type === 'reference') {
391
- child.type.id = namesToIds[child.type.name];
392
- }
393
- if (child.signatures) {
394
- for (const sig of child.signatures) {
395
- for (const param of sig.parameters ?? []) {
396
- if (param.type?.type === 'reference') {
397
- param.type.id = namesToIds[param.type.name];
398
- }
399
- }
400
- if (sig.type?.type === 'reference') {
401
- sig.type.id = namesToIds[sig.type.name];
402
- }
403
- }
404
- }
405
- fixRefs(child);
406
- }
407
- }
408
- fixRefs(typedocApiReference);
409
-
410
- // Sort the children of the root object
411
- sortChildren(typedocApiReference);
412
-
413
- typedocApiReference.symbolIdMap = Object.fromEntries(Object.entries(symbolIdMap));
414
-
415
- // Write the Typedoc structure to the output file
416
- fs.writeFileSync(outFile, JSON.stringify(typedocApiReference, null, 4));
417
- }