@gtkx/gir 0.9.0 → 0.9.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/gir",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "GObject Introspection file parser for GTKX",
5
5
  "keywords": [
6
6
  "gtk",
@@ -0,0 +1,370 @@
1
+ type GirLinkType =
2
+ | "class"
3
+ | "iface"
4
+ | "struct"
5
+ | "enum"
6
+ | "flags"
7
+ | "error"
8
+ | "callback"
9
+ | "method"
10
+ | "vfunc"
11
+ | "func"
12
+ | "ctor"
13
+ | "property"
14
+ | "signal"
15
+ | "const"
16
+ | "type"
17
+ | "id";
18
+
19
+ interface GirLink {
20
+ type: GirLinkType;
21
+ namespace: string | undefined;
22
+ target: string;
23
+ member: string | undefined;
24
+ }
25
+
26
+ const GIR_LINK_PATTERN = /\[([a-z]+)@([^\]]+)\]/gi;
27
+
28
+ function parseGirLink(type: string, reference: string): GirLink | undefined {
29
+ const linkType = type.toLowerCase() as GirLinkType;
30
+
31
+ const validTypes: GirLinkType[] = [
32
+ "class",
33
+ "iface",
34
+ "struct",
35
+ "enum",
36
+ "flags",
37
+ "error",
38
+ "callback",
39
+ "method",
40
+ "vfunc",
41
+ "func",
42
+ "ctor",
43
+ "property",
44
+ "signal",
45
+ "const",
46
+ "type",
47
+ "id",
48
+ ];
49
+
50
+ if (!validTypes.includes(linkType)) {
51
+ return undefined;
52
+ }
53
+
54
+ const parts = reference.split(".");
55
+ if (parts.length === 0) {
56
+ return undefined;
57
+ }
58
+
59
+ if (linkType === "property" || linkType === "signal") {
60
+ const colonIndex = reference.indexOf(":");
61
+ if (colonIndex !== -1) {
62
+ const beforeColon = reference.substring(0, colonIndex);
63
+ const afterColon = reference.substring(colonIndex + 1);
64
+ const beforeParts = beforeColon.split(".");
65
+ if (beforeParts.length >= 2) {
66
+ return {
67
+ type: linkType,
68
+ namespace: beforeParts[0],
69
+ target: beforeParts.slice(1).join("."),
70
+ member: afterColon.replace("::", ""),
71
+ };
72
+ }
73
+ return {
74
+ type: linkType,
75
+ namespace: undefined,
76
+ target: beforeColon,
77
+ member: afterColon.replace("::", ""),
78
+ };
79
+ }
80
+ }
81
+
82
+ if (parts.length === 1) {
83
+ return {
84
+ type: linkType,
85
+ namespace: undefined,
86
+ target: parts[0] ?? "",
87
+ member: undefined,
88
+ };
89
+ }
90
+
91
+ if (parts.length === 2) {
92
+ const first = parts[0] ?? "";
93
+ const second = parts[1] ?? "";
94
+ const isNamespace = first.length > 0 && first[0] === first[0]?.toUpperCase();
95
+
96
+ if (linkType === "func" || linkType === "const") {
97
+ return {
98
+ type: linkType,
99
+ namespace: first,
100
+ target: second,
101
+ member: undefined,
102
+ };
103
+ }
104
+
105
+ if (isNamespace) {
106
+ return {
107
+ type: linkType,
108
+ namespace: first,
109
+ target: second,
110
+ member: undefined,
111
+ };
112
+ }
113
+
114
+ return {
115
+ type: linkType,
116
+ namespace: undefined,
117
+ target: first,
118
+ member: second,
119
+ };
120
+ }
121
+
122
+ return {
123
+ type: linkType,
124
+ namespace: parts[0],
125
+ target: parts[1] ?? "",
126
+ member: parts.slice(2).join(".") || undefined,
127
+ };
128
+ }
129
+
130
+ function formatGirLinkForTsDoc(link: GirLink): string {
131
+ let displayText: string;
132
+ if (link.member) {
133
+ displayText = `${link.target}.${link.member}`;
134
+ } else {
135
+ displayText = link.target;
136
+ }
137
+
138
+ const linkTarget = link.namespace ? `${link.namespace}.${displayText}` : displayText;
139
+
140
+ switch (link.type) {
141
+ case "class":
142
+ case "iface":
143
+ case "struct":
144
+ case "enum":
145
+ case "flags":
146
+ case "error":
147
+ case "callback":
148
+ case "type":
149
+ return `{@link ${linkTarget}}`;
150
+
151
+ case "method":
152
+ case "vfunc":
153
+ case "func":
154
+ case "ctor":
155
+ return `{@link ${linkTarget}}`;
156
+
157
+ case "property":
158
+ return `{@link ${linkTarget}}`;
159
+
160
+ case "signal":
161
+ return `{@link ${linkTarget}}`;
162
+
163
+ case "const":
164
+ return `{@link ${linkTarget}}`;
165
+
166
+ case "id":
167
+ return `\`${link.target}\``;
168
+
169
+ default:
170
+ return `\`${displayText}\``;
171
+ }
172
+ }
173
+
174
+ function convertGirLinks(text: string): string {
175
+ return text.replace(GIR_LINK_PATTERN, (_, type: string, reference: string) => {
176
+ const link = parseGirLink(type, reference);
177
+ if (!link) {
178
+ return `\`${reference}\``;
179
+ }
180
+ return formatGirLinkForTsDoc(link);
181
+ });
182
+ }
183
+
184
+ const NAMESPACE_TO_DOCS_PATH: Record<string, string> = {
185
+ Gtk: "gtk4",
186
+ Gdk: "gdk4",
187
+ Gsk: "gsk4",
188
+ Adw: "adw1",
189
+ GLib: "glib",
190
+ GObject: "gobject",
191
+ Gio: "gio",
192
+ Pango: "Pango",
193
+ PangoCairo: "PangoCairo",
194
+ GdkPixbuf: "gdk-pixbuf",
195
+ Cairo: "cairo",
196
+ };
197
+
198
+ function getDocsBaseUrl(namespace: string | undefined): string {
199
+ if (!namespace) {
200
+ return "https://docs.gtk.org/gtk4";
201
+ }
202
+ const docsPath = NAMESPACE_TO_DOCS_PATH[namespace];
203
+ if (docsPath) {
204
+ return `https://docs.gtk.org/${docsPath}`;
205
+ }
206
+ return `https://docs.gtk.org/${namespace.toLowerCase()}`;
207
+ }
208
+
209
+ function convertHtmlImageElements(text: string, baseUrl: string): string {
210
+ let result = text;
211
+
212
+ result = result.replace(/<picture[^>]*>([\s\S]*?)<\/picture>/gi, (_, pictureContent: string) => {
213
+ const imgMatch = /<img[^>]*alt="([^"]*)"[^>]*src="([^"]*)"[^>]*\/?>/i.exec(pictureContent);
214
+ if (!imgMatch) {
215
+ const imgMatch2 = /<img[^>]*src="([^"]*)"[^>]*alt="([^"]*)"[^>]*\/?>/i.exec(pictureContent);
216
+ if (imgMatch2) {
217
+ const src = imgMatch2[1];
218
+ const alt = imgMatch2[2];
219
+ return `![${alt}](${baseUrl}/${src})`;
220
+ }
221
+ return "";
222
+ }
223
+ const alt = imgMatch[1];
224
+ const src = imgMatch[2];
225
+ return `![${alt}](${baseUrl}/${src})`;
226
+ });
227
+
228
+ result = result.replace(/<img[^>]*alt="([^"]*)"[^>]*src="([^"]*)"[^>]*\/?>/gi, (_, alt: string, src: string) => {
229
+ if (src.startsWith("http://") || src.startsWith("https://")) {
230
+ return `![${alt}](${src})`;
231
+ }
232
+ return `![${alt}](${baseUrl}/${src})`;
233
+ });
234
+
235
+ result = result.replace(/<img[^>]*src="([^"]*)"[^>]*alt="([^"]*)"[^>]*\/?>/gi, (_, src: string, alt: string) => {
236
+ if (src.startsWith("http://") || src.startsWith("https://")) {
237
+ return `![${alt}](${src})`;
238
+ }
239
+ return `![${alt}](${baseUrl}/${src})`;
240
+ });
241
+
242
+ result = result.replace(/<img[^>]*src="([^"]*)"[^>]*\/?>/gi, (_, src: string) => {
243
+ if (src.startsWith("http://") || src.startsWith("https://")) {
244
+ return `![](${src})`;
245
+ }
246
+ return `![](${baseUrl}/${src})`;
247
+ });
248
+
249
+ result = result.replace(/<source[^>]*\/?>/gi, "");
250
+
251
+ return result;
252
+ }
253
+
254
+ function convertMarkdownImageUrls(text: string, baseUrl: string): string {
255
+ return text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (match, alt: string, src: string) => {
256
+ if (src.startsWith("http://") || src.startsWith("https://")) {
257
+ return match;
258
+ }
259
+ return `![${alt}](${baseUrl}/${src})`;
260
+ });
261
+ }
262
+
263
+ function convertKbdElements(text: string): string {
264
+ return text.replace(/<kbd>([^<]*)<\/kbd>/gi, "`$1`");
265
+ }
266
+
267
+ function stripHtmlLinks(text: string): string {
268
+ return text.replace(/\[([^\]]+)\]\([^)]+\.html[^)]*\)/gi, "$1");
269
+ }
270
+
271
+ function convertAtAnnotations(text: string): string {
272
+ return text.replace(/(?<!\{)@([a-zA-Z_][a-zA-Z0-9_]*)\b(?!\s*\{)/g, "`$1`");
273
+ }
274
+
275
+ function escapeXmlStyleTags(text: string): string {
276
+ return text.replace(/<(\/?)(child|object|property|signal|template|style|item|attribute)>/gi, "`<$1$2>`");
277
+ }
278
+
279
+ function cleanupWhitespace(text: string): string {
280
+ let result = text.replace(/\n{3,}/g, "\n\n");
281
+ result = result.replace(/[ \t]+$/gm, "");
282
+ return result.trim();
283
+ }
284
+
285
+ export interface SanitizeDocOptions {
286
+ escapeXmlTags?: boolean;
287
+ namespace?: string;
288
+ }
289
+
290
+ export function sanitizeDoc(doc: string, options: SanitizeDocOptions = {}): string {
291
+ let result = doc;
292
+
293
+ const baseUrl = getDocsBaseUrl(options.namespace);
294
+ result = convertHtmlImageElements(result, baseUrl);
295
+ result = convertMarkdownImageUrls(result, baseUrl);
296
+ result = convertKbdElements(result);
297
+ result = stripHtmlLinks(result);
298
+ result = convertGirLinks(result);
299
+ result = convertAtAnnotations(result);
300
+
301
+ if (options.escapeXmlTags) {
302
+ result = escapeXmlStyleTags(result);
303
+ }
304
+
305
+ result = cleanupWhitespace(result);
306
+
307
+ return result;
308
+ }
309
+
310
+ export function formatDoc(doc: string | undefined, indent: string = "", options: SanitizeDocOptions = {}): string {
311
+ if (!doc) {
312
+ return "";
313
+ }
314
+
315
+ const sanitized = sanitizeDoc(doc, options);
316
+ if (!sanitized) {
317
+ return "";
318
+ }
319
+
320
+ const lines = sanitized.split("\n").map((line) => line.trim());
321
+ const firstLine = lines[0] ?? "";
322
+
323
+ if (lines.length === 1 && firstLine.length < 80) {
324
+ return `${indent}/** ${firstLine} */\n`;
325
+ }
326
+
327
+ const formattedLines = lines.map((line) => `${indent} * ${line}`);
328
+ return `${indent}/**\n${formattedLines.join("\n")}\n${indent} */\n`;
329
+ }
330
+
331
+ interface DocParameter {
332
+ name: string;
333
+ doc: string | undefined;
334
+ }
335
+
336
+ export function formatMethodDoc(
337
+ doc: string | undefined,
338
+ params: DocParameter[],
339
+ indent: string = " ",
340
+ options: SanitizeDocOptions = {},
341
+ ): string {
342
+ const sanitizedDoc = doc ? sanitizeDoc(doc, options) : undefined;
343
+
344
+ const hasDocumentation = sanitizedDoc || params.some((p) => p.doc);
345
+ if (!hasDocumentation) {
346
+ return "";
347
+ }
348
+
349
+ const lines: string[] = [];
350
+
351
+ if (sanitizedDoc) {
352
+ for (const line of sanitizedDoc.split("\n")) {
353
+ lines.push(` * ${line.trim()}`);
354
+ }
355
+ }
356
+
357
+ for (const param of params) {
358
+ if (param.doc && param.name && param.name !== "..." && param.name !== "") {
359
+ const sanitizedParamDoc = sanitizeDoc(param.doc, options);
360
+ const paramDocFirstLine = sanitizedParamDoc.split("\n")[0]?.trim() ?? "";
361
+ lines.push(` * @param ${param.name} - ${paramDocFirstLine}`);
362
+ }
363
+ }
364
+
365
+ if (lines.length === 0) {
366
+ return "";
367
+ }
368
+
369
+ return `${indent}/**\n${indent}${lines.join(`\n${indent}`)}\n${indent} */\n`;
370
+ }
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
+ export * from "./doc-sanitizer.js";
1
2
  export * from "./parser.js";
2
3
  export * from "./types.js";
package/src/parser.ts CHANGED
@@ -186,18 +186,22 @@ export class GirParser {
186
186
  }
187
187
  return methods
188
188
  .filter((method) => method["@_introspectable"] !== "0")
189
- .map((method) => ({
190
- name: String(method["@_name"] ?? ""),
191
- cIdentifier: String(method["@_c:identifier"] ?? ""),
192
- returnType: this.parseReturnType(method["return-value"] as Record<string, unknown> | undefined),
193
- parameters: this.parseParameters(
194
- (method.parameters && typeof method.parameters === "object" && method.parameters !== null
195
- ? method.parameters
196
- : {}) as Record<string, unknown>,
197
- ),
198
- throws: method["@_throws"] === "1",
199
- doc: extractDoc(method),
200
- }));
189
+ .map((method) => {
190
+ const returnValue = method["return-value"] as Record<string, unknown> | undefined;
191
+ return {
192
+ name: String(method["@_name"] ?? ""),
193
+ cIdentifier: String(method["@_c:identifier"] ?? ""),
194
+ returnType: this.parseReturnType(returnValue),
195
+ parameters: this.parseParameters(
196
+ (method.parameters && typeof method.parameters === "object" && method.parameters !== null
197
+ ? method.parameters
198
+ : {}) as Record<string, unknown>,
199
+ ),
200
+ throws: method["@_throws"] === "1",
201
+ doc: extractDoc(method),
202
+ returnDoc: returnValue ? extractDoc(returnValue) : undefined,
203
+ };
204
+ });
201
205
  }
202
206
 
203
207
  private parseConstructors(constructors: Record<string, unknown>[]): GirConstructor[] {
@@ -206,18 +210,22 @@ export class GirParser {
206
210
  }
207
211
  return constructors
208
212
  .filter((ctor) => ctor["@_introspectable"] !== "0")
209
- .map((ctor) => ({
210
- name: String(ctor["@_name"] ?? ""),
211
- cIdentifier: String(ctor["@_c:identifier"] ?? ""),
212
- returnType: this.parseReturnType(ctor["return-value"] as Record<string, unknown> | undefined),
213
- parameters: this.parseParameters(
214
- (ctor.parameters && typeof ctor.parameters === "object" && ctor.parameters !== null
215
- ? ctor.parameters
216
- : {}) as Record<string, unknown>,
217
- ),
218
- throws: ctor["@_throws"] === "1",
219
- doc: extractDoc(ctor),
220
- }));
213
+ .map((ctor) => {
214
+ const returnValue = ctor["return-value"] as Record<string, unknown> | undefined;
215
+ return {
216
+ name: String(ctor["@_name"] ?? ""),
217
+ cIdentifier: String(ctor["@_c:identifier"] ?? ""),
218
+ returnType: this.parseReturnType(returnValue),
219
+ parameters: this.parseParameters(
220
+ (ctor.parameters && typeof ctor.parameters === "object" && ctor.parameters !== null
221
+ ? ctor.parameters
222
+ : {}) as Record<string, unknown>,
223
+ ),
224
+ throws: ctor["@_throws"] === "1",
225
+ doc: extractDoc(ctor),
226
+ returnDoc: returnValue ? extractDoc(returnValue) : undefined,
227
+ };
228
+ });
221
229
  }
222
230
 
223
231
  private parseFunctions(functions: Record<string, unknown>[]): GirFunction[] {
@@ -226,18 +234,22 @@ export class GirParser {
226
234
  }
227
235
  return functions
228
236
  .filter((func) => func["@_introspectable"] !== "0")
229
- .map((func) => ({
230
- name: String(func["@_name"] ?? ""),
231
- cIdentifier: String(func["@_c:identifier"] ?? ""),
232
- returnType: this.parseReturnType(func["return-value"] as Record<string, unknown> | undefined),
233
- parameters: this.parseParameters(
234
- (func.parameters && typeof func.parameters === "object" && func.parameters !== null
235
- ? func.parameters
236
- : {}) as Record<string, unknown>,
237
- ),
238
- throws: func["@_throws"] === "1",
239
- doc: extractDoc(func),
240
- }));
237
+ .map((func) => {
238
+ const returnValue = func["return-value"] as Record<string, unknown> | undefined;
239
+ return {
240
+ name: String(func["@_name"] ?? ""),
241
+ cIdentifier: String(func["@_c:identifier"] ?? ""),
242
+ returnType: this.parseReturnType(returnValue),
243
+ parameters: this.parseParameters(
244
+ (func.parameters && typeof func.parameters === "object" && func.parameters !== null
245
+ ? func.parameters
246
+ : {}) as Record<string, unknown>,
247
+ ),
248
+ throws: func["@_throws"] === "1",
249
+ doc: extractDoc(func),
250
+ returnDoc: returnValue ? extractDoc(returnValue) : undefined,
251
+ };
252
+ });
241
253
  }
242
254
 
243
255
  private parseParameters(parametersNode: Record<string, unknown>): GirParameter[] {
package/src/types.ts CHANGED
@@ -178,6 +178,8 @@ export type GirMethod = {
178
178
  throws?: boolean;
179
179
  /** Documentation for the method. */
180
180
  doc?: string;
181
+ /** Documentation for the return value. */
182
+ returnDoc?: string;
181
183
  };
182
184
 
183
185
  /**
@@ -196,6 +198,8 @@ export type GirConstructor = {
196
198
  throws?: boolean;
197
199
  /** Documentation for the constructor. */
198
200
  doc?: string;
201
+ /** Documentation for the return value. */
202
+ returnDoc?: string;
199
203
  };
200
204
 
201
205
  /**
@@ -214,6 +218,8 @@ export type GirFunction = {
214
218
  throws?: boolean;
215
219
  /** Documentation for the function. */
216
220
  doc?: string;
221
+ /** Documentation for the return value. */
222
+ returnDoc?: string;
217
223
  };
218
224
 
219
225
  /**
@@ -344,6 +350,10 @@ export type FfiTypeDescriptor = {
344
350
  borrowed?: boolean;
345
351
  /** Inner type for ref types (as descriptor) or boxed types (as GLib type name string). */
346
352
  innerType?: FfiTypeDescriptor | string;
353
+ /** Library name for boxed types that need dynamic type lookup. */
354
+ lib?: string;
355
+ /** Explicit get_type function name for boxed types (when naive transformation doesn't work). */
356
+ getTypeFn?: string;
347
357
  /** Item type for array types. */
348
358
  itemType?: FfiTypeDescriptor;
349
359
  /** List type for arrays (glist, gslist) - indicates native GList/GSList iteration. */
@@ -414,6 +424,8 @@ export type RegisteredType = {
414
424
  namespace: string;
415
425
  transformedName: string;
416
426
  glibTypeName?: string;
427
+ sharedLibrary?: string;
428
+ glibGetType?: string;
417
429
  };
418
430
 
419
431
  const CLASS_RENAMES = new Map<string, string>([["Error", "GError"]]);
@@ -441,7 +453,7 @@ export class TypeRegistry {
441
453
  * @param namespace - The namespace containing the class
442
454
  * @param name - The class name
443
455
  */
444
- registerType(namespace: string, name: string): void {
456
+ registerNativeClass(namespace: string, name: string): void {
445
457
  const transformedName = normalizeTypeName(name, namespace);
446
458
  this.types.set(`${namespace}.${name}`, {
447
459
  kind: "class",
@@ -486,8 +498,16 @@ export class TypeRegistry {
486
498
  * @param namespace - The namespace containing the record
487
499
  * @param name - The record name
488
500
  * @param glibTypeName - Optional GLib type name for boxed type handling
501
+ * @param sharedLibrary - The shared library containing this record's type
502
+ * @param glibGetType - The GLib get_type function name
489
503
  */
490
- registerRecord(namespace: string, name: string, glibTypeName?: string): void {
504
+ registerRecord(
505
+ namespace: string,
506
+ name: string,
507
+ glibTypeName?: string,
508
+ sharedLibrary?: string,
509
+ glibGetType?: string,
510
+ ): void {
491
511
  const transformedName = normalizeTypeName(name, namespace);
492
512
  this.types.set(`${namespace}.${name}`, {
493
513
  kind: "record",
@@ -495,6 +515,8 @@ export class TypeRegistry {
495
515
  namespace,
496
516
  transformedName,
497
517
  glibTypeName,
518
+ sharedLibrary,
519
+ glibGetType,
498
520
  });
499
521
  }
500
522
 
@@ -557,7 +579,7 @@ export class TypeRegistry {
557
579
  const registry = new TypeRegistry();
558
580
  for (const ns of namespaces) {
559
581
  for (const cls of ns.classes) {
560
- registry.registerType(ns.name, cls.name);
582
+ registry.registerNativeClass(ns.name, cls.name);
561
583
  }
562
584
  for (const iface of ns.interfaces) {
563
585
  registry.registerInterface(ns.name, iface.name);
@@ -570,7 +592,13 @@ export class TypeRegistry {
570
592
  }
571
593
  for (const record of ns.records) {
572
594
  if (record.glibTypeName && !record.disguised) {
573
- registry.registerRecord(ns.name, record.name, record.glibTypeName);
595
+ registry.registerRecord(
596
+ ns.name,
597
+ record.name,
598
+ record.glibTypeName,
599
+ ns.sharedLibrary,
600
+ record.glibGetType,
601
+ );
574
602
  }
575
603
  }
576
604
  for (const callback of ns.callbacks) {
@@ -934,6 +962,8 @@ export class TypeMapper {
934
962
  type: "boxed",
935
963
  borrowed: isReturn,
936
964
  innerType: registered.glibTypeName ?? registered.transformedName,
965
+ lib: registered.sharedLibrary,
966
+ getTypeFn: registered.glibGetType,
937
967
  },
938
968
  externalType,
939
969
  kind: registered.kind,
@@ -1023,6 +1053,8 @@ export class TypeMapper {
1023
1053
  type: "boxed",
1024
1054
  borrowed: isReturn,
1025
1055
  innerType: registered.glibTypeName ?? registered.transformedName,
1056
+ lib: registered.sharedLibrary,
1057
+ getTypeFn: registered.glibGetType,
1026
1058
  },
1027
1059
  externalType: isExternal ? externalType : undefined,
1028
1060
  };
@@ -1081,6 +1113,8 @@ export class TypeMapper {
1081
1113
  type: "boxed",
1082
1114
  borrowed: isReturn,
1083
1115
  innerType: registered.glibTypeName ?? registered.transformedName,
1116
+ lib: registered.sharedLibrary,
1117
+ getTypeFn: registered.glibGetType,
1084
1118
  },
1085
1119
  externalType,
1086
1120
  kind: registered.kind,
@@ -1182,20 +1216,26 @@ export class TypeMapper {
1182
1216
 
1183
1217
  if (param.type.name === "Gtk.DrawingAreaDrawFunc" || param.type.name === "DrawingAreaDrawFunc") {
1184
1218
  this.onExternalTypeUsed?.({
1185
- namespace: "Cairo",
1219
+ namespace: "cairo",
1186
1220
  name: "Context",
1187
1221
  transformedName: "Context",
1188
1222
  kind: "record",
1189
1223
  });
1190
1224
  this.onSameNamespaceClassUsed?.("DrawingArea", "DrawingArea");
1191
1225
  return {
1192
- ts: "(self: DrawingArea, cr: Cairo.Context, width: number, height: number) => void",
1226
+ ts: "(self: DrawingArea, cr: cairo.Context, width: number, height: number) => void",
1193
1227
  ffi: {
1194
1228
  type: "callback",
1195
1229
  trampoline: "drawFunc",
1196
1230
  argTypes: [
1197
1231
  { type: "gobject", borrowed: true },
1198
- { type: "boxed", borrowed: true, innerType: "CairoContext" },
1232
+ {
1233
+ type: "boxed",
1234
+ borrowed: true,
1235
+ innerType: "CairoContext",
1236
+ lib: "libcairo-gobject.so.2",
1237
+ getTypeFn: "cairo_gobject_context_get_type",
1238
+ },
1199
1239
  { type: "int", size: 32, unsigned: false },
1200
1240
  { type: "int", size: 32, unsigned: false },
1201
1241
  ],