@ts-for-gir/generator-json 4.0.0-beta.39 → 4.0.0-beta.41
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/README.md +72 -50
- package/package.json +10 -6
- package/src/gir-metadata-deserializer.ts +34 -0
- package/src/gir-metadata-index.ts +66 -0
- package/src/gir-metadata-serializer.ts +237 -0
- package/src/gir-metadata-types.ts +132 -0
- package/src/index.ts +3 -1
- package/src/json-definition-generator.ts +77 -28
- package/src/typedoc-pipeline.ts +581 -0
- package/src/json-generator.ts +0 -425
package/README.md
CHANGED
|
@@ -18,78 +18,100 @@
|
|
|
18
18
|
|
|
19
19
|
# JSON Generator
|
|
20
20
|
|
|
21
|
-
JSON output generator for `ts-for-gir`. This package
|
|
21
|
+
JSON output generator for `ts-for-gir`. This package uses [TypeDoc](https://typedoc.org/) to produce standardized **TypeDoc JSON Schema 2.0** output, enriched with GIR-specific metadata.
|
|
22
22
|
|
|
23
|
-
##
|
|
23
|
+
## How It Works
|
|
24
24
|
|
|
25
|
-
The
|
|
25
|
+
The generator uses a two-step process:
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
-
|
|
27
|
+
1. **Generate `.d.ts` files** into a temporary directory using the TypeScript type definition generator
|
|
28
|
+
2. **Run TypeDoc programmatically** over those files to produce standardized JSON, enriched with GIR-specific metadata via a custom `SerializerComponent`
|
|
29
|
+
|
|
30
|
+
This approach combines the best of both worlds: TypeDoc's standardized, well-documented JSON schema with GIR-specific introspection data that would otherwise be lost during TypeScript generation.
|
|
31
31
|
|
|
32
32
|
## Features
|
|
33
33
|
|
|
34
|
-
- **
|
|
35
|
-
- **
|
|
36
|
-
- **Metadata
|
|
37
|
-
- **Type
|
|
34
|
+
- **Standardized Output**: Produces [TypeDoc JSON Schema 2.0](https://typedoc.org/guides/documents/#json-output), compatible with the TypeDoc ecosystem
|
|
35
|
+
- **GIR Metadata Enrichment**: Adds `girMetadata` fields to each reflection with GIR-specific data (C types, signal flags, property access, parameter directions, etc.)
|
|
36
|
+
- **Namespace Metadata**: Includes `girNamespaceMetadata` at the project root with C prefixes, library version, and dependency information
|
|
37
|
+
- **Complete Type Information**: Full TypeScript type information including generics, overloads, and JSDoc
|
|
38
38
|
|
|
39
39
|
## JSON Structure
|
|
40
40
|
|
|
41
|
-
The
|
|
41
|
+
The output follows TypeDoc's JSON Schema 2.0 with additional GIR metadata:
|
|
42
42
|
|
|
43
43
|
```json
|
|
44
44
|
{
|
|
45
|
-
"
|
|
46
|
-
"name": "
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
45
|
+
"schemaVersion": "2.0",
|
|
46
|
+
"name": "Gtk-4.0",
|
|
47
|
+
"variant": "project",
|
|
48
|
+
"kind": 1,
|
|
49
|
+
"children": [
|
|
50
|
+
{
|
|
51
|
+
"name": "Gtk",
|
|
52
|
+
"variant": "declaration",
|
|
53
|
+
"kind": 4,
|
|
54
|
+
"children": [
|
|
55
|
+
{
|
|
56
|
+
"name": "Widget",
|
|
57
|
+
"kind": 128,
|
|
58
|
+
"girMetadata": {
|
|
59
|
+
"girKind": "class",
|
|
60
|
+
"resolveNames": ["GtkWidget"],
|
|
61
|
+
"classMetadata": {
|
|
62
|
+
"isAbstract": true,
|
|
63
|
+
"interfaces": ["Gtk.Accessible", "Gtk.Buildable"],
|
|
64
|
+
"signalNames": ["destroy", "show", "hide"]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
],
|
|
71
|
+
"girNamespaceMetadata": {
|
|
72
|
+
"namespace": "Gtk",
|
|
73
|
+
"version": "4.0",
|
|
74
|
+
"packageName": "Gtk-4.0",
|
|
75
|
+
"cPrefixes": ["Gtk"],
|
|
76
|
+
"libraryVersion": "4.20.3",
|
|
77
|
+
"dependencies": [
|
|
78
|
+
{ "namespace": "Gsk", "version": "4.0" },
|
|
79
|
+
{ "namespace": "Gdk", "version": "4.0" }
|
|
80
|
+
]
|
|
81
|
+
}
|
|
57
82
|
}
|
|
58
83
|
```
|
|
59
84
|
|
|
60
|
-
##
|
|
61
|
-
|
|
62
|
-
Types are serialized with a consistent structure:
|
|
85
|
+
## GIR Metadata
|
|
63
86
|
|
|
64
|
-
|
|
65
|
-
- **Arrays**: `{ "kind": "array", "type": {...}, "depth": 1 }`
|
|
66
|
-
- **Unions**: `{ "kind": "or", "types": [...] }`
|
|
67
|
-
- **Tuples**: `{ "kind": "tuple", "types": [...] }`
|
|
68
|
-
- **Nullable**: `{ "kind": "null", "type": {...} }`
|
|
69
|
-
- **Native**: `{ "kind": "native", "type": "string" }`
|
|
87
|
+
Each TypeDoc reflection can include a `girMetadata` field with GIR-specific data:
|
|
70
88
|
|
|
71
|
-
|
|
89
|
+
| GIR Kind | Metadata | Fields |
|
|
90
|
+
|----------|----------|--------|
|
|
91
|
+
| `class` | `classMetadata` | `isAbstract`, `interfaces`, `signalNames` |
|
|
92
|
+
| `record` | `recordMetadata` | `isForeign`, `isSimple`, `structFor` |
|
|
93
|
+
| `enum` / `bitfield` | `enumMetadata` | `isFlags` |
|
|
94
|
+
| `method` / `virtual-method` / `static-method` | `functionMetadata` | `isVirtual`, `isStatic`, `parameterDirections`, `nullableParams`, `optionalParams` |
|
|
95
|
+
| `property` | `propertyMetadata` | `readable`, `writable`, `constructOnly` |
|
|
96
|
+
| `signal` | `signalMetadata` | `signalName`, `detailed` |
|
|
97
|
+
| `constructor` | `functionMetadata` | `parameterDirections`, `nullableParams`, `optionalParams` |
|
|
98
|
+
| `constant`, `alias`, `callback`, `field` | — | Common metadata only |
|
|
72
99
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
```json
|
|
76
|
-
{
|
|
77
|
-
"kind": "class|interface|function|...",
|
|
78
|
-
"name": "ElementName",
|
|
79
|
-
"doc": "Documentation string",
|
|
80
|
-
"metadata": {...},
|
|
81
|
-
"private": false,
|
|
82
|
-
...
|
|
83
|
-
}
|
|
84
|
-
```
|
|
100
|
+
All GIR elements also include common metadata when available: `resolveNames` (C type names), `introducedVersion`, `deprecated`, `deprecatedVersion`, `deprecatedDoc`.
|
|
85
101
|
|
|
86
102
|
## Usage
|
|
87
103
|
|
|
88
|
-
|
|
104
|
+
```bash
|
|
105
|
+
# Generate JSON for a specific module
|
|
106
|
+
ts-for-gir json Gtk-4.0 --outdir ./json-output
|
|
107
|
+
|
|
108
|
+
# Generate with verbose output (pretty-printed JSON)
|
|
109
|
+
ts-for-gir json Gtk-4.0 --outdir ./json-output --verbose
|
|
110
|
+
```
|
|
89
111
|
|
|
90
112
|
The JSON output can be useful for:
|
|
91
113
|
- Building documentation websites
|
|
92
|
-
- Creating API analysis tools
|
|
114
|
+
- Creating API analysis and exploration tools
|
|
93
115
|
- Generating bindings for other languages
|
|
94
116
|
- Data processing and transformation pipelines
|
|
95
117
|
- IDE integration and tooling
|
|
@@ -98,6 +120,6 @@ The JSON output can be useful for:
|
|
|
98
120
|
|
|
99
121
|
The JSON generator integrates with the ts-for-gir ecosystem through:
|
|
100
122
|
- **Reporter System**: Comprehensive logging and error reporting
|
|
101
|
-
- **Generator Interface**: Standard lifecycle methods (start
|
|
102
|
-
- **
|
|
123
|
+
- **Generator Interface**: Standard lifecycle methods (`start`, `generate`, `finish`)
|
|
124
|
+
- **TypeDoc**: Programmatic usage of TypeDoc for JSON serialization with custom `SerializerComponent`
|
|
103
125
|
- **Configuration**: Respects all standard ts-for-gir options and settings
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ts-for-gir/generator-json",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.41",
|
|
4
4
|
"description": "JSON generator for ts-for-gir",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"module": "src/index.ts",
|
|
@@ -36,13 +36,17 @@
|
|
|
36
36
|
"json"
|
|
37
37
|
],
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@
|
|
39
|
+
"@ts-for-gir/tsconfig": "^4.0.0-beta.41",
|
|
40
|
+
"@types/node": "^24.12.0",
|
|
40
41
|
"typescript": "^5.9.3"
|
|
41
42
|
},
|
|
42
43
|
"dependencies": {
|
|
43
|
-
"@gi.ts/parser": "^4.0.0-beta.
|
|
44
|
-
"@ts-for-gir/generator-base": "^4.0.0-beta.
|
|
45
|
-
"@ts-for-gir/
|
|
46
|
-
"@ts-for-gir/
|
|
44
|
+
"@gi.ts/parser": "^4.0.0-beta.41",
|
|
45
|
+
"@ts-for-gir/generator-base": "^4.0.0-beta.41",
|
|
46
|
+
"@ts-for-gir/generator-typescript": "^4.0.0-beta.41",
|
|
47
|
+
"@ts-for-gir/gir-module-metadata": "^4.0.0-beta.41",
|
|
48
|
+
"@ts-for-gir/lib": "^4.0.0-beta.41",
|
|
49
|
+
"@ts-for-gir/reporter": "^4.0.0-beta.41",
|
|
50
|
+
"typedoc": "^0.28.17"
|
|
47
51
|
}
|
|
48
52
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { DeclarationReflection, type DeserializerComponent } from "typedoc";
|
|
2
|
+
|
|
3
|
+
import type { GirEnrichedReflection, GirNamespaceMetadata, GirReflectionMetadata } from "./gir-metadata-types.ts";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* TypeDoc deserializer component that restores GIR-specific metadata
|
|
7
|
+
* from JSON output back onto Reflection instances during merge mode.
|
|
8
|
+
*
|
|
9
|
+
* This is the counterpart to {@link GirMetadataSerializer} — it reads
|
|
10
|
+
* the `girMetadata` and `girNamespaceMetadata` fields from the JSON
|
|
11
|
+
* and attaches them as custom properties on the deserialized reflections.
|
|
12
|
+
*/
|
|
13
|
+
export class GirMetadataDeserializer implements DeserializerComponent {
|
|
14
|
+
readonly priority = -1;
|
|
15
|
+
|
|
16
|
+
supports(model: unknown, obj: unknown): boolean {
|
|
17
|
+
if (!(model instanceof DeclarationReflection)) return false;
|
|
18
|
+
if (typeof obj !== "object" || obj === null) return false;
|
|
19
|
+
return "girMetadata" in obj || "girNamespaceMetadata" in obj;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
fromObject(model: unknown, obj: unknown): void {
|
|
23
|
+
if (!(model instanceof DeclarationReflection)) return;
|
|
24
|
+
const jsonObj = obj as Record<string, unknown>;
|
|
25
|
+
const enriched = model as DeclarationReflection & GirEnrichedReflection;
|
|
26
|
+
|
|
27
|
+
if (jsonObj.girMetadata) {
|
|
28
|
+
enriched.girMetadata = jsonObj.girMetadata as GirReflectionMetadata;
|
|
29
|
+
}
|
|
30
|
+
if (jsonObj.girNamespaceMetadata) {
|
|
31
|
+
enriched.girNamespaceMetadata = jsonObj.girNamespaceMetadata as GirNamespaceMetadata;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type GirModule, IntrospectedBaseClass, IntrospectedClass } from "@ts-for-gir/lib";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A flat lookup index mapping TypeDoc reflection names to GIR introspected objects.
|
|
5
|
+
*
|
|
6
|
+
* Keys follow the pattern used by TypeDoc's `getFullName(".")` with the module prefix stripped:
|
|
7
|
+
* - Namespace members: `"Widget"`, `"init"`
|
|
8
|
+
* - Class members: `"Widget.show"`, `"Widget.visible"`
|
|
9
|
+
* - Signals: `"Widget.destroy"` (signal name)
|
|
10
|
+
*/
|
|
11
|
+
export type GirLookupIndex = Map<string, unknown>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Build a lookup index from a GirModule that maps TypeDoc reflection names
|
|
15
|
+
* to GIR introspected objects.
|
|
16
|
+
*/
|
|
17
|
+
export function buildGirLookupIndex(module: GirModule): GirLookupIndex {
|
|
18
|
+
const index: GirLookupIndex = new Map();
|
|
19
|
+
|
|
20
|
+
for (const [name, member] of module.members) {
|
|
21
|
+
const members = Array.isArray(member) ? member : [member];
|
|
22
|
+
|
|
23
|
+
for (const m of members) {
|
|
24
|
+
index.set(name, m);
|
|
25
|
+
|
|
26
|
+
if (m instanceof IntrospectedBaseClass) {
|
|
27
|
+
indexClassMembers(index, name, m);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return index;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function indexClassMembers(index: GirLookupIndex, className: string, cls: IntrospectedBaseClass): void {
|
|
36
|
+
for (const fn of cls.members) {
|
|
37
|
+
index.set(`${className}.${fn.name}`, fn);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
for (const prop of cls.props) {
|
|
41
|
+
index.set(`${className}.${prop.name}`, prop);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
for (const field of cls.fields) {
|
|
45
|
+
// Don't overwrite if a property with same name already exists
|
|
46
|
+
const key = `${className}.${field.name}`;
|
|
47
|
+
if (!index.has(key)) {
|
|
48
|
+
index.set(key, field);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
for (const ctor of cls.constructors) {
|
|
53
|
+
index.set(`${className}.${ctor.name}`, ctor);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
for (const cb of cls.callbacks) {
|
|
57
|
+
index.set(`${className}.${cb.name}`, cb);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (cls instanceof IntrospectedClass) {
|
|
61
|
+
for (const signal of cls.signals) {
|
|
62
|
+
// Use a signal-specific prefix to avoid collisions with methods
|
|
63
|
+
index.set(`signal:${className}.${signal.name}`, signal);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IntrospectedAlias,
|
|
3
|
+
IntrospectedBaseClass,
|
|
4
|
+
IntrospectedCallback,
|
|
5
|
+
IntrospectedClass,
|
|
6
|
+
IntrospectedClassFunction,
|
|
7
|
+
IntrospectedConstant,
|
|
8
|
+
IntrospectedConstructor,
|
|
9
|
+
IntrospectedEnum,
|
|
10
|
+
IntrospectedError,
|
|
11
|
+
IntrospectedField,
|
|
12
|
+
IntrospectedFunction,
|
|
13
|
+
type IntrospectedFunctionParameter,
|
|
14
|
+
IntrospectedProperty,
|
|
15
|
+
IntrospectedRecord,
|
|
16
|
+
IntrospectedSignal,
|
|
17
|
+
IntrospectedStaticClassFunction,
|
|
18
|
+
IntrospectedVirtualClassFunction,
|
|
19
|
+
} from "@ts-for-gir/lib";
|
|
20
|
+
import { DeclarationReflection, type SerializerComponent } from "typedoc";
|
|
21
|
+
|
|
22
|
+
import type { GirLookupIndex } from "./gir-metadata-index.ts";
|
|
23
|
+
import type {
|
|
24
|
+
GirClassMetadata,
|
|
25
|
+
GirElementKind,
|
|
26
|
+
GirEnumMetadata,
|
|
27
|
+
GirFunctionMetadata,
|
|
28
|
+
GirRecordMetadata,
|
|
29
|
+
GirReflectionMetadata,
|
|
30
|
+
} from "./gir-metadata-types.ts";
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* TypeDoc serializer component that enriches JSON output with GIR-specific metadata.
|
|
34
|
+
*
|
|
35
|
+
* For each `DeclarationReflection`, it looks up the corresponding GIR introspected
|
|
36
|
+
* object via the pre-built lookup index and adds a `girMetadata` field to the JSON.
|
|
37
|
+
*/
|
|
38
|
+
export class GirMetadataSerializer implements SerializerComponent<DeclarationReflection> {
|
|
39
|
+
readonly priority = -1;
|
|
40
|
+
|
|
41
|
+
constructor(private readonly index: GirLookupIndex) {}
|
|
42
|
+
|
|
43
|
+
supports(item: unknown): boolean {
|
|
44
|
+
return item instanceof DeclarationReflection;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
toObject(item: DeclarationReflection, obj: Partial<Record<string, unknown>>): Partial<Record<string, unknown>> {
|
|
48
|
+
const key = this.getLookupKey(item);
|
|
49
|
+
const girObj = this.index.get(key);
|
|
50
|
+
|
|
51
|
+
if (!girObj) return obj;
|
|
52
|
+
|
|
53
|
+
const metadata = this.buildMetadata(girObj);
|
|
54
|
+
if (metadata) {
|
|
55
|
+
obj.girMetadata = metadata;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return obj;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private getLookupKey(reflection: DeclarationReflection): string {
|
|
62
|
+
const fullName = reflection.getFullName(".");
|
|
63
|
+
// Strip the namespace prefix (first segment, e.g. "freetype2" from "freetype2.Bitmap.$gtype")
|
|
64
|
+
const dotIndex = fullName.indexOf(".");
|
|
65
|
+
return dotIndex >= 0 ? fullName.substring(dotIndex + 1) : fullName;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Dispatch table mapping GIR class constructors to their metadata builders.
|
|
70
|
+
* Order matters: subclasses must appear before superclasses (e.g.
|
|
71
|
+
* IntrospectedRecord before IntrospectedBaseClass, IntrospectedError before IntrospectedEnum).
|
|
72
|
+
*/
|
|
73
|
+
private static readonly METADATA_DISPATCH: Array<
|
|
74
|
+
// biome-ignore lint/suspicious/noExplicitAny: heterogeneous constructors and handlers require any
|
|
75
|
+
[abstract new (...args: any[]) => unknown, (self: GirMetadataSerializer, obj: any) => GirReflectionMetadata]
|
|
76
|
+
> = [
|
|
77
|
+
[IntrospectedRecord, (s, o) => s.buildRecordMetadata(o)],
|
|
78
|
+
[IntrospectedClass, (s, o) => s.buildClassMetadata(o)],
|
|
79
|
+
[IntrospectedBaseClass, (s, o) => s.buildBaseMetadata(o, "interface")],
|
|
80
|
+
[IntrospectedError, (s, o) => s.buildEnumMetadata(o, true)],
|
|
81
|
+
[IntrospectedEnum, (s, o) => s.buildEnumMetadata(o, false)],
|
|
82
|
+
[IntrospectedConstructor, (s, o) => s.buildFunctionLikeMetadata(o, "constructor")],
|
|
83
|
+
[IntrospectedVirtualClassFunction, (s, o) => s.buildFunctionLikeMetadata(o, "virtual-method", { isVirtual: true })],
|
|
84
|
+
[IntrospectedStaticClassFunction, (s, o) => s.buildFunctionLikeMetadata(o, "static-method", { isStatic: true })],
|
|
85
|
+
[IntrospectedClassFunction, (s, o) => s.buildFunctionLikeMetadata(o, "method")],
|
|
86
|
+
[IntrospectedCallback, (s, o) => s.buildFunctionLikeMetadata(o, "callback")],
|
|
87
|
+
[IntrospectedFunction, (s, o) => s.buildFunctionLikeMetadata(o, "function")],
|
|
88
|
+
[IntrospectedProperty, (s, o) => s.buildPropertyMetadata(o)],
|
|
89
|
+
[IntrospectedField, (s, o) => s.buildBaseMetadata(o, "field")],
|
|
90
|
+
[IntrospectedSignal, (s, o) => s.buildSignalMetadata(o)],
|
|
91
|
+
[IntrospectedConstant, (s, o) => s.buildBaseMetadata(o, "constant")],
|
|
92
|
+
[IntrospectedAlias, (s, o) => s.buildBaseMetadata(o, "alias")],
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
private buildMetadata(girObj: unknown): GirReflectionMetadata | null {
|
|
96
|
+
for (const [ctor, handler] of GirMetadataSerializer.METADATA_DISPATCH) {
|
|
97
|
+
if (girObj instanceof ctor) {
|
|
98
|
+
return handler(this, girObj);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private buildBaseMetadata(
|
|
105
|
+
girObj: {
|
|
106
|
+
resolve_names?: string[];
|
|
107
|
+
metadata?: {
|
|
108
|
+
introducedVersion?: string;
|
|
109
|
+
deprecated?: boolean;
|
|
110
|
+
deprecatedVersion?: string;
|
|
111
|
+
deprecatedDoc?: string;
|
|
112
|
+
};
|
|
113
|
+
},
|
|
114
|
+
girKind: GirElementKind,
|
|
115
|
+
): GirReflectionMetadata {
|
|
116
|
+
const metadata: GirReflectionMetadata = { girKind };
|
|
117
|
+
|
|
118
|
+
if (girObj.resolve_names && girObj.resolve_names.length > 0) {
|
|
119
|
+
metadata.resolveNames = girObj.resolve_names;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const m = girObj.metadata;
|
|
123
|
+
if (m) {
|
|
124
|
+
if (m.introducedVersion) metadata.introducedVersion = m.introducedVersion;
|
|
125
|
+
if (m.deprecated) metadata.deprecated = m.deprecated;
|
|
126
|
+
if (m.deprecatedVersion) metadata.deprecatedVersion = m.deprecatedVersion;
|
|
127
|
+
if (m.deprecatedDoc) metadata.deprecatedDoc = m.deprecatedDoc;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return metadata;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private buildClassMetadata(cls: IntrospectedClass): GirReflectionMetadata {
|
|
134
|
+
const metadata = this.buildBaseMetadata(cls, "class");
|
|
135
|
+
|
|
136
|
+
const classMetadata: GirClassMetadata = {};
|
|
137
|
+
if (cls.isAbstract) classMetadata.isAbstract = true;
|
|
138
|
+
if (cls.interfaces.length > 0) {
|
|
139
|
+
classMetadata.interfaces = cls.interfaces.map((i) => `${i.namespace}.${i.name}`);
|
|
140
|
+
}
|
|
141
|
+
if (cls.signals.length > 0) {
|
|
142
|
+
classMetadata.signalNames = cls.signals.map((s) => s.name);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (Object.keys(classMetadata).length > 0) {
|
|
146
|
+
metadata.classMetadata = classMetadata;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return metadata;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private buildRecordMetadata(record: IntrospectedRecord): GirReflectionMetadata {
|
|
153
|
+
const metadata = this.buildBaseMetadata(record, "record");
|
|
154
|
+
|
|
155
|
+
const recordMetadata: GirRecordMetadata = {
|
|
156
|
+
isForeign: record.isForeign(),
|
|
157
|
+
isSimple: record.isSimple(),
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
if (record.structFor) {
|
|
161
|
+
recordMetadata.structFor = `${record.structFor.namespace}.${record.structFor.name}`;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
metadata.recordMetadata = recordMetadata;
|
|
165
|
+
|
|
166
|
+
return metadata;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private buildEnumMetadata(enumObj: IntrospectedEnum, isFlags: boolean): GirReflectionMetadata {
|
|
170
|
+
const metadata = this.buildBaseMetadata(enumObj, isFlags ? "bitfield" : "enum");
|
|
171
|
+
const enumMetadata: GirEnumMetadata = { isFlags };
|
|
172
|
+
metadata.enumMetadata = enumMetadata;
|
|
173
|
+
return metadata;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private extractFunctionParams(params: IntrospectedFunctionParameter[]): Partial<GirFunctionMetadata> {
|
|
177
|
+
const result: Partial<GirFunctionMetadata> = {};
|
|
178
|
+
|
|
179
|
+
const directions: Record<string, string> = {};
|
|
180
|
+
const nullable: string[] = [];
|
|
181
|
+
const optional: string[] = [];
|
|
182
|
+
|
|
183
|
+
for (const p of params) {
|
|
184
|
+
directions[p.name] = p.direction.toString();
|
|
185
|
+
if (p.isNullable) nullable.push(p.name);
|
|
186
|
+
if (p.isOptional) optional.push(p.name);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (Object.keys(directions).length > 0) result.parameterDirections = directions;
|
|
190
|
+
if (nullable.length > 0) result.nullableParams = nullable;
|
|
191
|
+
if (optional.length > 0) result.optionalParams = optional;
|
|
192
|
+
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private buildFunctionLikeMetadata(
|
|
197
|
+
fn: IntrospectedFunction | IntrospectedClassFunction | IntrospectedConstructor,
|
|
198
|
+
girKind: GirElementKind,
|
|
199
|
+
extra?: Partial<GirFunctionMetadata>,
|
|
200
|
+
): GirReflectionMetadata {
|
|
201
|
+
const metadata = this.buildBaseMetadata(fn, girKind);
|
|
202
|
+
|
|
203
|
+
const fnMeta: GirFunctionMetadata = {
|
|
204
|
+
...this.extractFunctionParams(fn.parameters),
|
|
205
|
+
...extra,
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
if (Object.keys(fnMeta).length > 0) {
|
|
209
|
+
metadata.functionMetadata = fnMeta;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return metadata;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private buildPropertyMetadata(prop: IntrospectedProperty): GirReflectionMetadata {
|
|
216
|
+
const metadata = this.buildBaseMetadata(prop, "property");
|
|
217
|
+
metadata.propertyMetadata = {
|
|
218
|
+
readable: prop.readable,
|
|
219
|
+
writable: prop.writable,
|
|
220
|
+
constructOnly: prop.constructOnly,
|
|
221
|
+
};
|
|
222
|
+
return metadata;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
private buildSignalMetadata(signal: IntrospectedSignal): GirReflectionMetadata {
|
|
226
|
+
const metadata = this.buildBaseMetadata(signal, "signal");
|
|
227
|
+
metadata.signalMetadata = {
|
|
228
|
+
signalName: signal.name,
|
|
229
|
+
detailed: signal.detailed,
|
|
230
|
+
...(signal.action ? { action: true } : {}),
|
|
231
|
+
...(signal.noRecurse ? { noRecurse: true } : {}),
|
|
232
|
+
...(signal.noHooks ? { noHooks: true } : {}),
|
|
233
|
+
...(signal.when ? { when: signal.when } : {}),
|
|
234
|
+
};
|
|
235
|
+
return metadata;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for GIR-specific metadata added to TypeDoc JSON output.
|
|
3
|
+
*
|
|
4
|
+
* These types describe the `girMetadata` field added to each TypeDoc reflection
|
|
5
|
+
* and the `girNamespaceMetadata` field added to the project root.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type GirElementKind =
|
|
9
|
+
| "class"
|
|
10
|
+
| "interface"
|
|
11
|
+
| "record"
|
|
12
|
+
| "enum"
|
|
13
|
+
| "bitfield"
|
|
14
|
+
| "function"
|
|
15
|
+
| "method"
|
|
16
|
+
| "virtual-method"
|
|
17
|
+
| "static-method"
|
|
18
|
+
| "constructor"
|
|
19
|
+
| "property"
|
|
20
|
+
| "field"
|
|
21
|
+
| "signal"
|
|
22
|
+
| "constant"
|
|
23
|
+
| "alias"
|
|
24
|
+
| "callback";
|
|
25
|
+
|
|
26
|
+
export interface GirReflectionMetadata {
|
|
27
|
+
/** The kind of GIR element this reflection corresponds to */
|
|
28
|
+
girKind: GirElementKind;
|
|
29
|
+
/** Registered type names (c:type, glib:type-name) */
|
|
30
|
+
resolveNames?: string[];
|
|
31
|
+
/** Version when this element was introduced */
|
|
32
|
+
introducedVersion?: string;
|
|
33
|
+
/** Whether this element is deprecated */
|
|
34
|
+
deprecated?: boolean;
|
|
35
|
+
/** Version when this element was deprecated */
|
|
36
|
+
deprecatedVersion?: string;
|
|
37
|
+
/** Deprecation message */
|
|
38
|
+
deprecatedDoc?: string;
|
|
39
|
+
/** Class/Interface-specific metadata */
|
|
40
|
+
classMetadata?: GirClassMetadata;
|
|
41
|
+
/** Function/Method-specific metadata */
|
|
42
|
+
functionMetadata?: GirFunctionMetadata;
|
|
43
|
+
/** Property-specific metadata */
|
|
44
|
+
propertyMetadata?: GirPropertyMetadata;
|
|
45
|
+
/** Signal-specific metadata */
|
|
46
|
+
signalMetadata?: GirSignalMetadata;
|
|
47
|
+
/** Record-specific metadata */
|
|
48
|
+
recordMetadata?: GirRecordMetadata;
|
|
49
|
+
/** Enum-specific metadata */
|
|
50
|
+
enumMetadata?: GirEnumMetadata;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface GirClassMetadata {
|
|
54
|
+
isAbstract?: boolean;
|
|
55
|
+
interfaces?: string[];
|
|
56
|
+
signalNames?: string[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface GirFunctionMetadata {
|
|
60
|
+
isVirtual?: boolean;
|
|
61
|
+
isStatic?: boolean;
|
|
62
|
+
/** Parameter directions keyed by parameter name */
|
|
63
|
+
parameterDirections?: Record<string, string>;
|
|
64
|
+
/** Names of parameters that are nullable */
|
|
65
|
+
nullableParams?: string[];
|
|
66
|
+
/** Names of parameters that are optional */
|
|
67
|
+
optionalParams?: string[];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface GirPropertyMetadata {
|
|
71
|
+
readable: boolean;
|
|
72
|
+
writable: boolean;
|
|
73
|
+
constructOnly: boolean;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface GirSignalMetadata {
|
|
77
|
+
/** Original signal name (kebab-case) */
|
|
78
|
+
signalName: string;
|
|
79
|
+
/** Whether this is a detailed signal */
|
|
80
|
+
detailed: boolean;
|
|
81
|
+
/** Whether this signal can be emitted directly from user code */
|
|
82
|
+
action?: boolean;
|
|
83
|
+
/** Whether this signal prevents recursive emission */
|
|
84
|
+
noRecurse?: boolean;
|
|
85
|
+
/** Whether this signal disables emission hooks */
|
|
86
|
+
noHooks?: boolean;
|
|
87
|
+
/** Default handler timing relative to signal emission */
|
|
88
|
+
when?: "first" | "last" | "cleanup";
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface GirRecordMetadata {
|
|
92
|
+
isForeign: boolean;
|
|
93
|
+
isSimple: boolean;
|
|
94
|
+
/** Class this record is a GType struct for */
|
|
95
|
+
structFor?: string;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface GirEnumMetadata {
|
|
99
|
+
/** Whether this enum represents flags (bitfield) */
|
|
100
|
+
isFlags: boolean;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface GirNamespaceMetadata {
|
|
104
|
+
namespace: string;
|
|
105
|
+
version: string;
|
|
106
|
+
packageName: string;
|
|
107
|
+
cPrefixes: string[];
|
|
108
|
+
libraryVersion: string;
|
|
109
|
+
dependencies: Array<{ namespace: string; version: string }>;
|
|
110
|
+
/** NPM package version (e.g. "4.20.3-4.0.0-beta.41") */
|
|
111
|
+
packageVersion?: string;
|
|
112
|
+
/** Human-readable display name, e.g. "GTK" */
|
|
113
|
+
displayName?: string;
|
|
114
|
+
/** Short description of the library */
|
|
115
|
+
description?: string;
|
|
116
|
+
/** Logo/icon URL */
|
|
117
|
+
logoUrl?: string;
|
|
118
|
+
/** Project website URL */
|
|
119
|
+
websiteUrl?: string;
|
|
120
|
+
/** URL to upstream C API documentation */
|
|
121
|
+
cDocsUrl?: string;
|
|
122
|
+
/** SPDX license identifier */
|
|
123
|
+
license?: string;
|
|
124
|
+
/** Category for grouping on documentation homepage */
|
|
125
|
+
category?: string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** A DeclarationReflection extended with optional GIR-specific metadata. */
|
|
129
|
+
export interface GirEnrichedReflection {
|
|
130
|
+
girMetadata?: GirReflectionMetadata;
|
|
131
|
+
girNamespaceMetadata?: GirNamespaceMetadata;
|
|
132
|
+
}
|
package/src/index.ts
CHANGED