@apify/docusaurus-plugin-typedoc-api 4.2.10 → 4.2.11-1
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.
- package/lib/components/ApiItem.js +97 -2
- package/lib/components/ApiItem.js.map +1 -1
- package/lib/components/ApiPage.js +0 -3
- package/lib/components/ApiPage.js.map +1 -1
- package/lib/components/Markdown.js +0 -2
- package/lib/components/Markdown.js.map +1 -1
- package/lib/components/MemberGetterSetter.js +0 -1
- package/lib/components/MemberGetterSetter.js.map +1 -1
- package/lib/components/MemberSignatureBody.js +2 -7
- package/lib/components/MemberSignatureBody.js.map +1 -1
- package/lib/components/Reflection.js +0 -1
- package/lib/components/Reflection.js.map +1 -1
- package/lib/components/SourceLink.js +5 -1
- package/lib/components/SourceLink.js.map +1 -1
- package/lib/components/Type.js +2 -3
- package/lib/components/Type.js.map +1 -1
- package/lib/index.js +23 -10
- package/lib/index.js.map +1 -1
- package/lib/plugin/data.js +1 -9
- package/lib/plugin/data.js.map +1 -1
- package/lib/plugin/python/consts.js +47 -0
- package/lib/plugin/python/consts.js.map +1 -0
- package/lib/plugin/python/index.js +36 -0
- package/lib/plugin/python/index.js.map +1 -0
- package/lib/plugin/python/inheritance.js +71 -0
- package/lib/plugin/python/inheritance.js.map +1 -0
- package/lib/plugin/python/packageVersions.js +46 -0
- package/lib/plugin/python/packageVersions.js.map +1 -0
- package/lib/plugin/python/transformation.js +359 -0
- package/lib/plugin/python/transformation.js.map +1 -0
- package/lib/plugin/python/type-parsing/index.js +79 -0
- package/lib/plugin/python/type-parsing/index.js.map +1 -0
- package/lib/plugin/python/types.js +2 -0
- package/lib/plugin/python/types.js.map +1 -0
- package/lib/plugin/python/utils.js +106 -0
- package/lib/plugin/python/utils.js.map +1 -0
- package/lib/plugin/structure/0.23.js +0 -2
- package/lib/plugin/structure/0.23.js.map +1 -1
- package/lib/utils/icons.js +1 -2
- package/lib/utils/icons.js.map +1 -1
- package/lib/utils/reexports.js +96 -0
- package/lib/utils/reexports.js.map +1 -0
- package/package.json +5 -3
- package/src/components/ApiItem.tsx +103 -9
- package/src/components/ApiItemLayout.tsx +4 -2
- package/src/components/ApiOptionsLayout.tsx +18 -16
- package/src/components/ApiPage.tsx +0 -2
- package/src/components/DefaultValue.tsx +0 -1
- package/src/components/Flags.tsx +1 -1
- package/src/components/Markdown.tsx +0 -1
- package/src/components/Member.tsx +19 -17
- package/src/components/MemberGetterSetter.tsx +0 -1
- package/src/components/MemberSignatureBody.tsx +42 -38
- package/src/components/MemberSignatureTitle.tsx +18 -15
- package/src/components/Reflection.tsx +1 -1
- package/src/components/SourceLink.tsx +6 -8
- package/src/components/Type.tsx +6 -14
- package/src/components/VersionBanner.tsx +5 -1
- package/src/index.ts +39 -9
- package/src/plugin/data.ts +6 -12
- package/src/plugin/python/consts.ts +50 -0
- package/src/plugin/python/docspec-gen/__init__.py +0 -0
- package/src/plugin/python/docspec-gen/generate_ast.py +73 -0
- package/src/plugin/python/docspec-gen/google_docstring_processor.py +185 -0
- package/src/plugin/python/index.ts +47 -0
- package/src/plugin/python/inheritance.ts +80 -0
- package/src/plugin/python/packageVersions.ts +43 -0
- package/src/plugin/python/transformation.ts +444 -0
- package/src/plugin/python/type-parsing/index.ts +88 -0
- package/src/plugin/python/type-parsing/parse_types.py +82 -0
- package/src/plugin/python/types.ts +83 -0
- package/src/plugin/python/utils.ts +123 -0
- package/src/plugin/structure/0.23.ts +0 -2
- package/src/plugin/version.ts +2 -2
- package/src/types.ts +9 -0
- package/src/utils/icons.ts +4 -3
- package/src/utils/reexports.ts +105 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Given a JSON file containing a list of expressions, this script will parse each expression and output a JSON file containing an object with the parsed expressions.
|
|
3
|
+
Called from transformDocs.js.
|
|
4
|
+
|
|
5
|
+
Accepts one CLI argument: the path to the JSON file containing the expressions to parse.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import ast
|
|
9
|
+
import json
|
|
10
|
+
import sys
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
base_scalar_types = {
|
|
14
|
+
"str",
|
|
15
|
+
"int",
|
|
16
|
+
"float",
|
|
17
|
+
"bool",
|
|
18
|
+
"bytearray",
|
|
19
|
+
"timedelta",
|
|
20
|
+
"None",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def parse_expression(ast_node, full_expression):
|
|
25
|
+
"""
|
|
26
|
+
Turns the AST expression object into a typedoc-compliant dict
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
current_node_type = ast_node.__class__.__name__
|
|
30
|
+
|
|
31
|
+
if current_node_type == "BinOp" and ast_node.op.__class__.__name__ == "BitOr":
|
|
32
|
+
return {
|
|
33
|
+
"type": "union",
|
|
34
|
+
"types": [
|
|
35
|
+
parse_expression(ast_node.left, full_expression),
|
|
36
|
+
parse_expression(ast_node.right, full_expression),
|
|
37
|
+
],
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if current_node_type == "Tuple":
|
|
41
|
+
return [parse_expression(e, full_expression) for e in ast_node.elts]
|
|
42
|
+
|
|
43
|
+
if current_node_type == "Subscript":
|
|
44
|
+
if "id" in ast_node.value._fields and ast_node.value.id == "Annotated":
|
|
45
|
+
return parse_expression(ast_node.slice.dims[0], full_expression)
|
|
46
|
+
|
|
47
|
+
main_type = parse_expression(ast_node.value, full_expression)
|
|
48
|
+
type_argument = parse_expression(ast_node.slice, full_expression)
|
|
49
|
+
|
|
50
|
+
main_type["typeArguments"] = (
|
|
51
|
+
type_argument if isinstance(type_argument, list) else [type_argument]
|
|
52
|
+
)
|
|
53
|
+
return main_type
|
|
54
|
+
|
|
55
|
+
if current_node_type == "Constant":
|
|
56
|
+
return {"type": "literal", "value": ast_node.value}
|
|
57
|
+
|
|
58
|
+
# If the expression is not one of the types above, we simply print the expression
|
|
59
|
+
return {
|
|
60
|
+
"type": "reference",
|
|
61
|
+
"name": full_expression[ast_node.col_offset : ast_node.end_col_offset],
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
typedoc_types_path = sys.argv[1]
|
|
66
|
+
|
|
67
|
+
with open(typedoc_types_path, "r") as f:
|
|
68
|
+
typedoc_out = {}
|
|
69
|
+
expressions = json.load(f)
|
|
70
|
+
|
|
71
|
+
for expression in expressions:
|
|
72
|
+
try:
|
|
73
|
+
if typedoc_out.get(expression) is None:
|
|
74
|
+
typedoc_out[expression] = parse_expression(
|
|
75
|
+
ast.parse(expression).body[0].value, expression
|
|
76
|
+
)
|
|
77
|
+
except Exception as e:
|
|
78
|
+
print(f"Invalid expression encountered while parsing: {expression}")
|
|
79
|
+
print(f"Error: {e}")
|
|
80
|
+
|
|
81
|
+
with open(f"{os.path.splitext(typedoc_types_path)[0]}-parsed.json", "w") as f:
|
|
82
|
+
f.write(json.dumps(typedoc_out, indent=4))
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { TYPEDOC_KINDS } from './consts';
|
|
3
|
+
|
|
4
|
+
export type OID = number;
|
|
5
|
+
|
|
6
|
+
export interface TypeDocObject {
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
id: OID;
|
|
9
|
+
name: string;
|
|
10
|
+
kind: number;
|
|
11
|
+
kindString: string;
|
|
12
|
+
decorations?: { name: string; args: string }[];
|
|
13
|
+
children?: TypeDocObject[];
|
|
14
|
+
groups?: { title: string; children: OID[] }[];
|
|
15
|
+
flags: Record<string, boolean>;
|
|
16
|
+
module?: string;
|
|
17
|
+
inheritedFrom?: {
|
|
18
|
+
type: string;
|
|
19
|
+
target: OID;
|
|
20
|
+
name: string;
|
|
21
|
+
};
|
|
22
|
+
comment?: {
|
|
23
|
+
summary: { text: string; kind: 'text' }[];
|
|
24
|
+
blockTags?: { tag: string; content: any[] }[];
|
|
25
|
+
};
|
|
26
|
+
signatures?: TypeDocObject[];
|
|
27
|
+
sources?: {
|
|
28
|
+
fileName: string;
|
|
29
|
+
line: number;
|
|
30
|
+
character: number;
|
|
31
|
+
}[];
|
|
32
|
+
type?: TypeDocType;
|
|
33
|
+
symbolIdMap?: Record<number, { qualifiedName: string; sourceFileName: string }>;
|
|
34
|
+
extendedTypes?: TypeDocType[];
|
|
35
|
+
extendedBy?: TypeDocType[];
|
|
36
|
+
modifiers?: any[];
|
|
37
|
+
parameters?: TypeDocObject[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface DocspecObject {
|
|
41
|
+
members: DocspecObject[];
|
|
42
|
+
name: string;
|
|
43
|
+
type: keyof typeof TYPEDOC_KINDS;
|
|
44
|
+
location: {
|
|
45
|
+
filename: string;
|
|
46
|
+
lineno: number;
|
|
47
|
+
};
|
|
48
|
+
decorations?: { name: string; args: string }[];
|
|
49
|
+
bases?: DocspecType[];
|
|
50
|
+
datatype?: DocspecType;
|
|
51
|
+
return_type?: DocspecType;
|
|
52
|
+
value?: any;
|
|
53
|
+
docstring?: { content: string };
|
|
54
|
+
modifiers?: DocspecType[];
|
|
55
|
+
args?: { name: string; type: DocspecType; default_value: any; datatype: DocspecType }[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface TypeDocDocstring {
|
|
59
|
+
text: string;
|
|
60
|
+
returns?: string;
|
|
61
|
+
args?: Record<string, string>;
|
|
62
|
+
sections?: Record<string, any[]>[];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface DocspecDocstring {
|
|
66
|
+
text: string;
|
|
67
|
+
returns?: string;
|
|
68
|
+
args?: { param: string; desc: string }[];
|
|
69
|
+
sections?: Record<string, any[]>[];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type TypeDocType =
|
|
73
|
+
{
|
|
74
|
+
[key: string]: any;
|
|
75
|
+
type: 'reference';
|
|
76
|
+
name: string;
|
|
77
|
+
target?: number;
|
|
78
|
+
} | {
|
|
79
|
+
type: 'literal';
|
|
80
|
+
value: any;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export type DocspecType = string;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/* eslint-disable sort-keys */
|
|
2
|
+
import { GROUP_ORDER, TYPEDOC_KINDS } from './consts';
|
|
3
|
+
import type { DocspecObject, OID, TypeDocObject } from './types';
|
|
4
|
+
|
|
5
|
+
function* generateOID() {
|
|
6
|
+
let id = 1;
|
|
7
|
+
while (true) {
|
|
8
|
+
yield id++;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const oidGenerator = generateOID();
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Returns automatically incrementing OID. Every call to this function will return a new unique OID.
|
|
16
|
+
* @returns {number} The OID.
|
|
17
|
+
*/
|
|
18
|
+
export function getOID(): OID {
|
|
19
|
+
return oidGenerator.next().value as OID;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Given a TypeDoc object, returns the name of the group this object belongs to.
|
|
24
|
+
* @param object The TypeDoc object.
|
|
25
|
+
* @returns The group name and the source of the group name (either 'decorator' or 'predicate').
|
|
26
|
+
*/
|
|
27
|
+
export function getGroupName(object: TypeDocObject): {
|
|
28
|
+
groupName: string | undefined;
|
|
29
|
+
source: 'decorator' | 'predicate';
|
|
30
|
+
} {
|
|
31
|
+
if (object.decorations?.some((d) => d.name === 'docs_group')) {
|
|
32
|
+
const parsedGroupName = object.decorations
|
|
33
|
+
.find((d) => d.name === 'docs_group')
|
|
34
|
+
?.args.slice(2, -2);
|
|
35
|
+
|
|
36
|
+
if (parsedGroupName) {
|
|
37
|
+
return {
|
|
38
|
+
groupName: parsedGroupName,
|
|
39
|
+
source: 'decorator',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const groupPredicates: Record<string, (obj: TypeDocObject) => boolean> = {
|
|
45
|
+
'Scrapy integration': (x) =>
|
|
46
|
+
[
|
|
47
|
+
'ApifyScheduler',
|
|
48
|
+
'ActorDatasetPushPipeline',
|
|
49
|
+
'ApifyHttpProxyMiddleware',
|
|
50
|
+
'apply_apify_settings',
|
|
51
|
+
].includes(x.name),
|
|
52
|
+
'Data structures': (x) =>
|
|
53
|
+
Boolean(['BaseModel', 'TypedDict'].some((base) =>
|
|
54
|
+
(x?.bases as { includes: (x: string) => boolean })?.includes(base),
|
|
55
|
+
) || x?.decorations?.some((d) => d.name === 'dataclass')),
|
|
56
|
+
Errors: (x) => x.name.toLowerCase().includes('error'),
|
|
57
|
+
Classes: (x) => x.kindString === 'Class',
|
|
58
|
+
'Main Clients': (x) => ['ApifyClient', 'ApifyClientAsync'].includes(x.name),
|
|
59
|
+
'Async Resource Clients': (x) => x.name.toLowerCase().includes('async'),
|
|
60
|
+
'Resource Clients': (x) => x.kindString === 'Class' && x.name.toLowerCase().includes('client'),
|
|
61
|
+
Methods: (x) => x.kindString === 'Method',
|
|
62
|
+
Constructors: (x) => x.kindString === 'Constructor',
|
|
63
|
+
Properties: (x) => x.kindString === 'Property',
|
|
64
|
+
Constants: (x) => x.kindString === 'Enumeration',
|
|
65
|
+
'Enumeration members': (x) => x.kindString === 'Enumeration Member',
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const groupName = Object.entries(groupPredicates).find(([_, predicate]) =>
|
|
69
|
+
predicate(object),
|
|
70
|
+
)?.[0];
|
|
71
|
+
|
|
72
|
+
return { groupName, source: 'predicate' };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Recursively search arbitrary JS object for property `name: 'docs_group'`.
|
|
77
|
+
* @param object
|
|
78
|
+
*/
|
|
79
|
+
export function projectUsesDocsGroupDecorator(object: { name: string }): boolean {
|
|
80
|
+
if (object instanceof Object) {
|
|
81
|
+
if (object.name === 'docs_group') {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for (const key in object) {
|
|
86
|
+
if (projectUsesDocsGroupDecorator(object[key as keyof typeof object] as unknown as { name: string })) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Returns true if the given member should be hidden from the documentation.
|
|
97
|
+
*
|
|
98
|
+
* A member should be hidden if:
|
|
99
|
+
* - It has a `ignore_docs` decoration.
|
|
100
|
+
*
|
|
101
|
+
* @param member The member to check.
|
|
102
|
+
*/
|
|
103
|
+
export function isHidden(member: DocspecObject): boolean {
|
|
104
|
+
return (
|
|
105
|
+
!(member.type in TYPEDOC_KINDS) ||
|
|
106
|
+
member.decorations?.some((d) => d.name === 'ignore_docs') ||
|
|
107
|
+
member.name === 'ignore_docs'
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Comparator for enforcing the documentation groups order (examples of groups in {@link GROUP_ORDER}).
|
|
113
|
+
*
|
|
114
|
+
* The groups are sorted by the order in which they appear in {@link GROUP_ORDER}.
|
|
115
|
+
*
|
|
116
|
+
* This is compatible with the `Array.prototype.sort` method.
|
|
117
|
+
*/
|
|
118
|
+
export function groupSort(g1: string, g2: string) {
|
|
119
|
+
if (GROUP_ORDER.includes(g1) && GROUP_ORDER.includes(g2)) {
|
|
120
|
+
return GROUP_ORDER.indexOf(g1) - GROUP_ORDER.indexOf(g2);
|
|
121
|
+
}
|
|
122
|
+
return g1.localeCompare(g2);
|
|
123
|
+
}
|
package/src/plugin/version.ts
CHANGED
|
@@ -46,9 +46,9 @@ function createVersionMetadata({
|
|
|
46
46
|
const isLast = versionName === lastVersionName;
|
|
47
47
|
const versionOptions = options.versions[versionName] ?? {};
|
|
48
48
|
const versionLabel =
|
|
49
|
-
versionOptions.label ?? versionName === CURRENT_VERSION_NAME ? 'Next' : versionName;
|
|
49
|
+
(versionOptions.label ?? versionName === CURRENT_VERSION_NAME) ? 'Next' : versionName;
|
|
50
50
|
let versionPathPart =
|
|
51
|
-
versionOptions.path ?? versionName === CURRENT_VERSION_NAME ? 'next' : versionName;
|
|
51
|
+
(versionOptions.path ?? versionName === CURRENT_VERSION_NAME) ? 'next' : versionName;
|
|
52
52
|
|
|
53
53
|
if (isLast) {
|
|
54
54
|
versionPathPart = '';
|
package/src/types.ts
CHANGED
|
@@ -21,6 +21,9 @@ export interface DocusaurusPluginTypeDocApiOptions
|
|
|
21
21
|
minimal?: boolean;
|
|
22
22
|
packageJsonName?: string;
|
|
23
23
|
packages: (PackageConfig | string)[];
|
|
24
|
+
/**
|
|
25
|
+
* @deprecated Use `pythonOptions` and the bundled transformation script instead.
|
|
26
|
+
*/
|
|
24
27
|
pathToCurrentVersionTypedocJSON?: string;
|
|
25
28
|
projectRoot: string;
|
|
26
29
|
readmeName?: string;
|
|
@@ -33,8 +36,13 @@ export interface DocusaurusPluginTypeDocApiOptions
|
|
|
33
36
|
|
|
34
37
|
/**
|
|
35
38
|
* Enables the Python-specific rendering patches.
|
|
39
|
+
* If `pythonOptions` is specified, this is automatically set to `true`.
|
|
36
40
|
*/
|
|
37
41
|
python: boolean;
|
|
42
|
+
pythonOptions: {
|
|
43
|
+
moduleShortcutsPath?: string;
|
|
44
|
+
pythonModulePath?: string;
|
|
45
|
+
};
|
|
38
46
|
|
|
39
47
|
remarkPlugins: MDXPlugin[];
|
|
40
48
|
rehypePlugins: MDXPlugin[];
|
|
@@ -43,6 +51,7 @@ export interface DocusaurusPluginTypeDocApiOptions
|
|
|
43
51
|
disableVersioning?: boolean;
|
|
44
52
|
includeCurrentVersion?: boolean;
|
|
45
53
|
routeBasePath?: string;
|
|
54
|
+
reexports: { url: string, group?: string }[];
|
|
46
55
|
}
|
|
47
56
|
|
|
48
57
|
export interface GlobalData {
|
package/src/utils/icons.ts
CHANGED
|
@@ -28,10 +28,12 @@ const KIND_ICONS: Record<ReflectionKind, string> = {
|
|
|
28
28
|
1_048_576: 'symbol-field', // SetSignature
|
|
29
29
|
2_097_152: 'symbol-parameter', // TypeAlias
|
|
30
30
|
4_194_304: 'references', // Reference
|
|
31
|
-
8_388_608: 'references' // a Non-TS document (new in TypeDoc `0.26.0`, unused by `docusaurus-plugin-typedoc-api`)
|
|
31
|
+
8_388_608: 'references', // a Non-TS document (new in TypeDoc `0.26.0`, unused by `docusaurus-plugin-typedoc-api`)
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
export function getKindIcon(kind: ReflectionKind, name
|
|
34
|
+
export function getKindIcon(kind: ReflectionKind, name?: string): string | null {
|
|
35
|
+
if (!name) return null;
|
|
36
|
+
|
|
35
37
|
let icon = KIND_ICONS[kind];
|
|
36
38
|
|
|
37
39
|
// Use event icon when property starts with "on"
|
|
@@ -42,7 +44,6 @@ export function getKindIcon(kind: ReflectionKind, name: string): string {
|
|
|
42
44
|
return icon;
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
// eslint-disable-next-line complexity
|
|
46
47
|
export function getKindIconColor(kind: ReflectionKind): string {
|
|
47
48
|
switch (kind) {
|
|
48
49
|
// Function
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
|
|
4
|
+
import { load } from "cheerio";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
|
|
7
|
+
interface TypedocJSONFile {
|
|
8
|
+
children: TypedocJSONFile[];
|
|
9
|
+
groups: { title: string, children: number[] }[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface ExternalApiItem {
|
|
13
|
+
item: TypedocJSONFile;
|
|
14
|
+
groups: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function loadExternalApiItem(url: string): Promise<ExternalApiItem> {
|
|
18
|
+
console.log(`Loading external API item from ${url}...`);
|
|
19
|
+
const response = await fetch(url);
|
|
20
|
+
|
|
21
|
+
const $ = load(await response.text(), { decodeEntities: false })
|
|
22
|
+
const base64encoded = $('script[type="application/typedoc-data;base64"]')?.first()?.text();
|
|
23
|
+
|
|
24
|
+
if(!base64encoded) return null;
|
|
25
|
+
|
|
26
|
+
const jsonData = atob(base64encoded);
|
|
27
|
+
return JSON.parse(jsonData) as ExternalApiItem;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Recursively find the maximum numerical `id` property in a JS object
|
|
31
|
+
function getMaxId(obj: any) {
|
|
32
|
+
let maxId = 0;
|
|
33
|
+
for (const key in obj) {
|
|
34
|
+
if (typeof obj[key] === 'object') {
|
|
35
|
+
maxId = Math.max(maxId, getMaxId(obj[key]));
|
|
36
|
+
} else if (key === 'id') {
|
|
37
|
+
maxId = Math.max(maxId, obj[key]);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return maxId;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function incrementIds(obj: any, increment: number): number {
|
|
45
|
+
let max = 0;
|
|
46
|
+
for (const key in obj) {
|
|
47
|
+
if (key === 'children' && Array.isArray(obj[key]) && obj[key].every((c: any) => typeof c === 'number')) {
|
|
48
|
+
obj[key] = obj[key].map((c: number) => c + increment);
|
|
49
|
+
|
|
50
|
+
max = Math.max(max, ...obj[key]);
|
|
51
|
+
} else if (key === 'id' && Number.isInteger(obj[key])) {
|
|
52
|
+
obj[key] += increment;
|
|
53
|
+
|
|
54
|
+
max = Math.max(obj[key], max);
|
|
55
|
+
} else if (obj[key] && typeof obj[key] === 'object') {
|
|
56
|
+
max = Math.max(incrementIds(obj[key], increment), max);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return max;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function injectReexports(typedocJsonFilePath: string, reexports: { url: string, group?: string }[]): Promise<void> {
|
|
64
|
+
const typedocJson: TypedocJSONFile = await import(typedocJsonFilePath) as TypedocJSONFile;
|
|
65
|
+
|
|
66
|
+
let baseId = getMaxId(typedocJson);
|
|
67
|
+
|
|
68
|
+
const externalApiItems = await Promise.all(reexports.map(async ({url, group}) => ({
|
|
69
|
+
externalItem: await loadExternalApiItem(url),
|
|
70
|
+
customGroup: group,
|
|
71
|
+
})));
|
|
72
|
+
|
|
73
|
+
for (const { externalItem, customGroup } of externalApiItems) {
|
|
74
|
+
if (!externalItem) continue;
|
|
75
|
+
|
|
76
|
+
let { item, groups } = externalItem;
|
|
77
|
+
|
|
78
|
+
// Make sure the new item doesn't have any conflicting IDs
|
|
79
|
+
baseId = incrementIds(item, baseId);
|
|
80
|
+
|
|
81
|
+
// Add the new item to the root children
|
|
82
|
+
typedocJson.children.push(item);
|
|
83
|
+
|
|
84
|
+
if (customGroup) {
|
|
85
|
+
groups = [customGroup];
|
|
86
|
+
} else if (groups.length === 0) {
|
|
87
|
+
groups = ['Reexports'];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
for (const groupName of groups) {
|
|
91
|
+
// Assign the new item into the specified groups
|
|
92
|
+
const reexportsGroup = typedocJson.groups.find(g => g.title === groupName);
|
|
93
|
+
|
|
94
|
+
if (reexportsGroup) {
|
|
95
|
+
reexportsGroup.children.push(item.id);
|
|
96
|
+
} else {
|
|
97
|
+
typedocJson.groups.push({ title: groupName, children: [item.id] });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
console.log(`Reexported item ${item.name} from ${item.sources[0].fileName} to ${groups.join(', ')}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
fs.writeFileSync(typedocJsonFilePath, JSON.stringify(typedocJson, null, 4));
|
|
105
|
+
}
|