@gjsify/gtk-host 0.45.0 → 0.46.0
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/esm/conformance/diagnostics.js +1 -1
- package/lib/esm/conformance/index.js +1 -1
- package/lib/esm/descriptors/adw.js +1 -1
- package/lib/esm/generated/widgets.js +1 -1
- package/lib/esm/host.js +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/list/controller.js +1 -1
- package/lib/esm/policies.js +1 -1
- package/lib/esm/probe.js +1 -1
- package/lib/esm/props.js +1 -1
- package/lib/esm/registry.js +1 -1
- package/lib/esm/style/document.js +1 -0
- package/lib/esm/style/gtk-props.js +1 -1
- package/lib/esm/style/index.js +1 -1
- package/lib/esm/style/layout.js +1 -1
- package/lib/esm/style/paint.js +1 -1
- package/lib/esm/style/sheet.js +3 -3
- package/lib/esm/style/theme.js +3 -0
- package/lib/esm/style/tokens.js +1 -1
- package/lib/types/descriptors/index.d.ts +1 -1
- package/lib/types/generated/props.d.ts +611 -822
- package/lib/types/generated/widgets.d.ts +1 -1
- package/lib/types/generator/emit-types.d.mts +1 -1
- package/lib/types/generator/emit.d.mts +16 -6
- package/lib/types/generator/girs-vocabulary.d.mts +45 -0
- package/lib/types/generator/main.d.mts +16 -8
- package/lib/types/generator/model.d.mts +95 -0
- package/lib/types/generator/names.d.mts +19 -0
- package/lib/types/generator/vocabulary-dts.d.mts +47 -0
- package/lib/types/host.d.ts +1 -1
- package/lib/types/policies.d.ts +7 -1
- package/lib/types/props.d.ts +13 -1
- package/lib/types/registry.d.ts +1 -1
- package/lib/types/style/document.d.ts +22 -0
- package/lib/types/style/index.d.ts +6 -3
- package/lib/types/style/layout.d.ts +34 -0
- package/lib/types/style/sheet.d.ts +0 -5
- package/lib/types/style/theme.d.ts +158 -0
- package/lib/types/style/theme.spec.d.ts +2 -0
- package/lib/types/style/tokens.d.ts +76 -0
- package/lib/types/style/tokens.spec.d.ts +2 -0
- package/lib/types/types.d.ts +63 -0
- package/package.json +14 -15
- package/lib/types/generator/gir.d.mts +0 -190
- package/lib/types/generator/mini.fixture.d.mts +0 -30
- package/lib/types/generator/surface.d.mts +0 -62
- package/lib/types/generator/tsmap.d.mts +0 -73
|
@@ -43,8 +43,84 @@ export interface StyleTokens {
|
|
|
43
43
|
* scale would let a project's typo resolve against a value nobody chose, which is
|
|
44
44
|
* the failure the declared-vocabulary rule exists to prevent — and it would make
|
|
45
45
|
* "the values come from the project" false in the common case.
|
|
46
|
+
*
|
|
47
|
+
* That decision stands, and {@link TAILWIND_DEFAULT_TOKENS} is not a retreat from
|
|
48
|
+
* it: the measured gap is that a project REPLACING this default with its own
|
|
49
|
+
* generated scales loses `0` and `full`, which nothing in its `@theme` was ever
|
|
50
|
+
* going to declare. The answer is an opt-in a reader can see in their own code, not
|
|
51
|
+
* a wider default nobody chose. This constant stays as small as it is.
|
|
46
52
|
*/
|
|
47
53
|
export declare const MINIMAL_TOKENS: StyleTokens;
|
|
54
|
+
/**
|
|
55
|
+
* The Tailwind defaults a project's own `@theme` does not replace — OPT-IN.
|
|
56
|
+
*
|
|
57
|
+
* MEASURED, and this is the highest-frequency finding of the whole exercise. Running
|
|
58
|
+
* one production-shaped application's real class vocabulary — 87 distinct utilities,
|
|
59
|
+
* 826 occurrences — through this partition with tokens generated mechanically from
|
|
60
|
+
* its Tailwind v4 `@theme` resolves **81 of 87 distinct and 803 of 826 occurrences**.
|
|
61
|
+
* Five of the six failures are one thing: `rounded-full` (11 uses) and
|
|
62
|
+
* `inset-0`/`left-0`/`right-0`/`top-0` (9 between them). The project's declared
|
|
63
|
+
* scales simply have no `full` and no `0`.
|
|
64
|
+
*
|
|
65
|
+
* They have no reason to. **`0` and `full` are not design decisions.** A token source
|
|
66
|
+
* emits the values a designer chose; `inset-0` means "flush" and `rounded-full` means
|
|
67
|
+
* "a pill", and neither is a number anybody picked. A project that declares its whole
|
|
68
|
+
* palette still leans on Tailwind for the STRUCTURAL tokens, and finds out one class
|
|
69
|
+
* at a time.
|
|
70
|
+
*
|
|
71
|
+
* So this set is deliberately NOT a copy of Tailwind's default theme, and the name
|
|
72
|
+
* would be a lie if it carried the numeric ladder: shipping `spacing-4` … `spacing-96`
|
|
73
|
+
* would be shipping a design decision the project has already made differently, which
|
|
74
|
+
* is the opposite of the point. It carries the structural tokens and the keyword sets
|
|
75
|
+
* — the ones a `@theme` has no reason to name — and nothing that is a value someone
|
|
76
|
+
* chose.
|
|
77
|
+
*
|
|
78
|
+
* THREE DIVERGENCES FROM TAILWIND'S OWN NUMBERS, each forced and each measured:
|
|
79
|
+
*
|
|
80
|
+
* - **Every length is px, not rem.** Tailwind v4's spacing is rem-based. A `rem`
|
|
81
|
+
* token reaches CSS padding unchanged and is a NAMED ERROR the moment the same
|
|
82
|
+
* token is asked to become a margin, because `Gtk.Widget:margin-top` is a `gint`
|
|
83
|
+
* of device pixels with no unit conversion behind it. A rem scale here would
|
|
84
|
+
* therefore trade "the token is missing" for "the token throws on half the
|
|
85
|
+
* families", which is worse.
|
|
86
|
+
* - **`full` is `9999px`, not `calc(infinity * 1px)`.** GTK's parser has no
|
|
87
|
+
* infinity, and a border radius larger than the box is clamped anyway.
|
|
88
|
+
* - **`inherit` is absent from the colours.** `color: inherit` parses, but
|
|
89
|
+
* `alpha(inherit, 0.5)` does not (measured: *"inherit" is not a valid color
|
|
90
|
+
* name*), so `bg-inherit/50` would be a refusal rather than a colour. The other
|
|
91
|
+
* four keywords survive the alpha modifier and are carried.
|
|
92
|
+
*
|
|
93
|
+
* Opting in is a VISIBLE LINE in the consumer's code, which is the whole design:
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* configureStyle({ tokens: mergeTokens(TAILWIND_DEFAULT_TOKENS, projectTokens) });
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* Use {@link mergeTokens} and not a spread. `{ ...TAILWIND_DEFAULT_TOKENS,
|
|
100
|
+
* ...projectTokens }` replaces whole SCALES, so a project declaring any `spacing` at
|
|
101
|
+
* all loses `0` again — which is the exact bug this constant exists to answer.
|
|
102
|
+
*/
|
|
103
|
+
export declare const TAILWIND_DEFAULT_TOKENS: StyleTokens;
|
|
104
|
+
/**
|
|
105
|
+
* Several token sets into one, merging PER TOKEN and not per scale.
|
|
106
|
+
*
|
|
107
|
+
* The distinction is the whole function. `{ ...defaults, ...project }` is an object
|
|
108
|
+
* spread over the SCALE names, so a project that declares any `spacing` replaces the
|
|
109
|
+
* default `spacing` wholesale and loses `0` — silently, and visible only as
|
|
110
|
+
* `inset-0` throwing much later. Later sets win token by token, which is what a
|
|
111
|
+
* reader means by "my values on top of the defaults".
|
|
112
|
+
*/
|
|
113
|
+
export declare function mergeTokens(...sets: readonly StyleTokens[]): StyleTokens;
|
|
114
|
+
/**
|
|
115
|
+
* The sentence a scale-miss error adds when Tailwind's defaults DO define the token.
|
|
116
|
+
*
|
|
117
|
+
* The measured six failures each become a one-line fix with this and stay a search
|
|
118
|
+
* without it: "not in the borderRadius scale. Known: l, m, s" sends a reader to
|
|
119
|
+
* invent a radius, where naming the opt-in sends them to the line that was missing.
|
|
120
|
+
* Empty for a token nothing would have answered, so an ordinary typo is not offered
|
|
121
|
+
* a remedy that would not have helped.
|
|
122
|
+
*/
|
|
123
|
+
export declare function tailwindDefaultHint(scaleName: string, token: string): string;
|
|
48
124
|
/** A token's value, or `undefined` when the scale is absent or does not carry it. */
|
|
49
125
|
export declare const lookupToken: (scale: Scale | undefined, token: string) => string | undefined;
|
|
50
126
|
/**
|
package/lib/types/types.d.ts
CHANGED
|
@@ -140,6 +140,20 @@ export type ChildPolicy = {
|
|
|
140
140
|
slots: Record<string, string>;
|
|
141
141
|
defaultSlot: string;
|
|
142
142
|
remove?: string;
|
|
143
|
+
/**
|
|
144
|
+
* Slots whose adder hands the child to an inner `Gtk.ListBox`, and which
|
|
145
|
+
* therefore need the same wrap `indexed` declares — keyed by slot, because a
|
|
146
|
+
* widget can have one such slot and two ordinary ones.
|
|
147
|
+
*
|
|
148
|
+
* MEASURED on GTK 4.22.4, and it is the wrap or a leak: `gtk_list_box_remove`
|
|
149
|
+
* does NOT unwrap. A `Gtk.ListBox` given a non-row child puts it inside an
|
|
150
|
+
* implicit `GtkListBoxRow`, and removing the ORIGINAL child then answers
|
|
151
|
+
* `Gtk-WARNING **: Tried to remove non-child 0x…` and leaves it parented —
|
|
152
|
+
* with a plain `Gtk.Label` and with a `Gtk.Button` alike. `Adw.ExpanderRow`'s
|
|
153
|
+
* `add_row` is that adder, so its disclosure slot declares the wrap and the
|
|
154
|
+
* host addresses the row it made.
|
|
155
|
+
*/
|
|
156
|
+
wrapSlots?: Readonly<Record<string, 'list-box-row'>>;
|
|
143
157
|
}
|
|
144
158
|
/**
|
|
145
159
|
* `Gtk.Stack`, `Adw.NavigationView`: children addressed by name/tag.
|
|
@@ -156,6 +170,55 @@ export type ChildPolicy = {
|
|
|
156
170
|
remove: string;
|
|
157
171
|
nameFrom: string;
|
|
158
172
|
titled: boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Take the child out of view BEFORE the parent removes it, and put its
|
|
175
|
+
* own `visible` back afterwards. Declared per widget, because it is a
|
|
176
|
+
* defect in one of them rather than a property of being keyed.
|
|
177
|
+
*
|
|
178
|
+
* The defect is libadwaita's. `stack_remove` — what both
|
|
179
|
+
* `adw_view_stack_remove` and dispose call — clears `visible_child`, then
|
|
180
|
+
* does `g_clear_object (&page->widget)`, and never touches
|
|
181
|
+
* `last_visible_child`, which can still point at that same page. A later
|
|
182
|
+
* reader then dereferences a page whose widget is NULL:
|
|
183
|
+
*
|
|
184
|
+
* Gtk-CRITICAL **: gtk_widget_set_child_visible: assertion 'GTK_IS_WIDGET (widget)' failed
|
|
185
|
+
*
|
|
186
|
+
* Source: `refs/libadwaita/src/adw-view-stack.c` — `stack_remove` at 1184,
|
|
187
|
+
* the stale read at 934 in `transition_done_cb`. Read at 42f647f
|
|
188
|
+
* (1.10.alpha.1); that file is byte-identical at the 1.9.3 tag, which is
|
|
189
|
+
* what is installed here, so one reading covers both.
|
|
190
|
+
*
|
|
191
|
+
* MEASURED on libadwaita 1.9.3 / GTK 4.22.4 / GJS 1.88.1. Reproducer, no
|
|
192
|
+
* renderer involved: add `a` and `b`, present a window holding the stack,
|
|
193
|
+
* `set_visible_child_name('b')`, `remove(a)`, then let the window go away.
|
|
194
|
+
* Each precondition alone is silent, a stack never made visible included —
|
|
195
|
+
* `set_visible_child` only records `last_visible_child` when
|
|
196
|
+
* `gtk_widget_is_visible` answers yes. `Gtk.Stack` and
|
|
197
|
+
* `Adw.NavigationView`, the other two `keyed` descriptors, do not
|
|
198
|
+
* reproduce it at all, which is why this is a field and not the kind.
|
|
199
|
+
*
|
|
200
|
+
* WHICH read fires decides what a test has to do, so it is measured rather
|
|
201
|
+
* than listed: the UNMAP one. `AdwAnimation` connects `adw_animation_skip`
|
|
202
|
+
* to its widget's `unmap` (`adw-animation.c`) and the skip runs
|
|
203
|
+
* `transition_done_cb`, so merely hiding the window is enough and
|
|
204
|
+
* destroying it does the same — while a queued resize plus draw, and a
|
|
205
|
+
* direct `measure()`, both stayed quiet. The file's other reads (snapshot,
|
|
206
|
+
* size-allocate, measure) are real paths this reproducer does not reach.
|
|
207
|
+
*
|
|
208
|
+
* Hiding first is libadwaita's OWN cleanup: the visibility notify runs
|
|
209
|
+
* `update_child_visible`, which does clear `last_visible_child`. Measured
|
|
210
|
+
* SUFFICIENT and not merely necessary — 400 randomised
|
|
211
|
+
* add/remove/switch/reorder steps against a live 200 ms transition, three
|
|
212
|
+
* seeds, 44/23/25 criticals unpatched against 0/0/0 patched.
|
|
213
|
+
*
|
|
214
|
+
* The restore is load-bearing. `reorderMode` answers `remove-all` for
|
|
215
|
+
* `keyed`, and measured, a reversal that hides without restoring leaves the
|
|
216
|
+
* stack with no visible child and no way back: the last line of
|
|
217
|
+
* `adw_view_stack_set_visible_child_name` is
|
|
218
|
+
* `if (gtk_widget_get_visible (page->widget)) set_visible_child (...)`, so
|
|
219
|
+
* for a hidden page it is a no-op with no warning at all.
|
|
220
|
+
*/
|
|
221
|
+
hideBeforeRemove?: boolean;
|
|
159
222
|
}
|
|
160
223
|
/** `Gtk.Grid`: position is data on the child, so document order carries nothing. */
|
|
161
224
|
| {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/gtk-host",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.0",
|
|
4
4
|
"description": "Framework-agnostic GTK4/Adwaita host: the element model UI-framework renderers bind to",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -71,11 +71,11 @@
|
|
|
71
71
|
"build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
|
|
72
72
|
"build:types": "gjsify tsc",
|
|
73
73
|
"build:test": "gjsify run build:test:gjs",
|
|
74
|
-
"build:test:node": "gjsify build src/test.mts --app node --outfile dist/test.node.mjs --define
|
|
75
|
-
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs --define
|
|
74
|
+
"build:test:node": "gjsify build src/test.mts --app node --outfile dist/test.node.mjs --define __VUE_OPTIONS_API__=false --define __VUE_PROD_DEVTOOLS__=false --define __VUE_PROD_HYDRATION_MISMATCH_DETAILS__=false --define \"process.env.NODE_ENV='production'\" --exclude-globals navigator",
|
|
75
|
+
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs --define __VUE_OPTIONS_API__=false --define __VUE_PROD_DEVTOOLS__=false --define __VUE_PROD_HYDRATION_MISMATCH_DETAILS__=false --define \"process.env.NODE_ENV='production'\" --exclude-globals navigator",
|
|
76
76
|
"test": "gjsify run build:gjsify && gjsify run build:test && gjsify run test:gjs",
|
|
77
77
|
"test:gjs": "gjsify run test.gjs.mjs",
|
|
78
|
-
"test:gjs-on-node": "gjsify run build:gjsify && gjsify run build:test:node &&
|
|
78
|
+
"test:gjs-on-node": "gjsify run build:gjsify && gjsify run build:test:node && node dist/test.node.mjs",
|
|
79
79
|
"generate": "gjsify build src/generator/main.mts --app gjs --outfile tmp/generate.gjs.mjs && gjsify run tmp/generate.gjs.mjs -- --out src/generated && gjsify format src/generated"
|
|
80
80
|
},
|
|
81
81
|
"keywords": [
|
|
@@ -86,14 +86,14 @@
|
|
|
86
86
|
"host"
|
|
87
87
|
],
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@girs/adw-1": "
|
|
90
|
-
"@girs/gdk-4.0": "
|
|
91
|
-
"@girs/gio-2.0": "
|
|
92
|
-
"@girs/gjs": "
|
|
93
|
-
"@girs/glib-2.0": "
|
|
94
|
-
"@girs/gobject-2.0": "
|
|
95
|
-
"@girs/gtk-4.0": "
|
|
96
|
-
"@girs/pango-1.0": "
|
|
89
|
+
"@girs/adw-1": "4.6.0",
|
|
90
|
+
"@girs/gdk-4.0": "4.6.0",
|
|
91
|
+
"@girs/gio-2.0": "4.6.0",
|
|
92
|
+
"@girs/gjs": "4.6.0",
|
|
93
|
+
"@girs/glib-2.0": "4.6.0",
|
|
94
|
+
"@girs/gobject-2.0": "4.6.0",
|
|
95
|
+
"@girs/gtk-4.0": "4.6.0",
|
|
96
|
+
"@girs/pango-1.0": "4.6.0"
|
|
97
97
|
},
|
|
98
98
|
"peerDependencies": {
|
|
99
99
|
"@vue/runtime-core": "^3.5.0",
|
|
@@ -116,13 +116,12 @@
|
|
|
116
116
|
}
|
|
117
117
|
},
|
|
118
118
|
"devDependencies": {
|
|
119
|
-
"@gjsify/cli": "^0.
|
|
119
|
+
"@gjsify/cli": "^0.46.0",
|
|
120
120
|
"@vue/runtime-core": "^3.5.0",
|
|
121
121
|
"solid-js": "^1.9.0",
|
|
122
|
-
"@gjsify/unit": "^0.
|
|
122
|
+
"@gjsify/unit": "^0.46.0",
|
|
123
123
|
"@types/node": "^25.9.2",
|
|
124
124
|
"typescript": "^6.0.3",
|
|
125
|
-
"@gjsify/domparser": "^0.45.0",
|
|
126
125
|
"@gjsify/node-gi": "file:../../node-gi/node-gi",
|
|
127
126
|
"vue": "^3.5.41",
|
|
128
127
|
"vue-tsc": "^3.3.11",
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Read the GIR XML into a plain model.
|
|
3
|
-
*
|
|
4
|
-
* WHY THE XML AND NOT THE TYPELIB. Both carry the structure — measured on gtk
|
|
5
|
-
* 4.22.4, `GIRepository` 3.0 answers class enumeration, abstractness, properties
|
|
6
|
-
* with `CONSTRUCT_ONLY`, signals, methods and property enum types, and its
|
|
7
|
-
* concrete-widget set is IDENTICAL to the XML's. What the typelib does not carry,
|
|
8
|
-
* and offers no API that could, is documentation, default values and
|
|
9
|
-
* since-versions: it strips them by design, which is why gi-docgen reads the GIR.
|
|
10
|
-
* ADR 0028 § 6 makes these surfaces a PUBLISHED artifact whose point is what a
|
|
11
|
-
* consumer's editor shows on hover, so the richer input wins.
|
|
12
|
-
*
|
|
13
|
-
* WHY @gjsify/domparser. Measured on the 6.2 MB `Gtk-4.0.gir`: 232 ms, RSS 53 MB
|
|
14
|
-
* -> 96 MB, and its `application/xml` mode is right where it has to be —
|
|
15
|
-
* selectors are case-SENSITIVE (`CLASS` matches nothing), namespaced tags work
|
|
16
|
-
* (`glib\:signal` -> 352), namespaced attributes work (`[glib\:type-name]` ->
|
|
17
|
-
* 445). No new dependency, and a tier-1 package gets dogfooded against a real
|
|
18
|
-
* 6 MB document.
|
|
19
|
-
*
|
|
20
|
-
* ONE FROZEN WART TO KNOW ABOUT: in XML mode `tagName` is LOWERCASED and
|
|
21
|
-
* `nodeName` UPPERCASED, both wrong by the XML spec and both deliberately frozen
|
|
22
|
-
* (ADR 0026 § Decision 4) because a measured consumer switches on lowercase tag
|
|
23
|
-
* literals at 24 sites. Harmless here — every GIR tag is lowercase already — but
|
|
24
|
-
* a generator for a mixed-case dialect could not use this reader as-is.
|
|
25
|
-
*/
|
|
26
|
-
/**
|
|
27
|
-
* A GIR type reference, with the array flag kept SEPARATE.
|
|
28
|
-
*
|
|
29
|
-
* Not a nicety: `<property name="css-classes"><array><type name="utf8"/></array>`
|
|
30
|
-
* is `string[]`, and a reader that asked for a descendant `<type>` would answer
|
|
31
|
-
* `string` — for a property authored as `cssClasses={['card']}` on every second
|
|
32
|
-
* widget. `querySelector` searches descendants, so the array case has to be
|
|
33
|
-
* checked FIRST, on own children only.
|
|
34
|
-
*/
|
|
35
|
-
export interface GirType {
|
|
36
|
-
/** Qualified where GIR wrote a reference (`Gtk.Orientation`), bare for a C scalar (`gboolean`). */
|
|
37
|
-
readonly name: string;
|
|
38
|
-
readonly array: boolean;
|
|
39
|
-
}
|
|
40
|
-
export interface GirProperty {
|
|
41
|
-
readonly name: string;
|
|
42
|
-
readonly writable: boolean;
|
|
43
|
-
readonly readable: boolean;
|
|
44
|
-
readonly constructOnly: boolean;
|
|
45
|
-
readonly type: GirType;
|
|
46
|
-
/** GIR carries it, the typelib does not — `GTK_ORIENTATION_HORIZONTAL`. */
|
|
47
|
-
readonly defaultValue?: string;
|
|
48
|
-
readonly deprecated: boolean;
|
|
49
|
-
/** GIR's `version` attribute — the release that introduced this member. */
|
|
50
|
-
readonly since?: string;
|
|
51
|
-
readonly doc?: string;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* The GObject nick a GIR enum member would get if GIR did not say.
|
|
55
|
-
*
|
|
56
|
-
* GIR writes `baseline_fill`; the nick GObject registered is `baseline-fill`. This
|
|
57
|
-
* is the FALLBACK for a `<member>` with no `glib:nick` — the attribute itself is
|
|
58
|
-
* the answer wherever it exists, because the substitution is right for Gtk and Adw
|
|
59
|
-
* by luck and not by construction: some nicks keep an underscore it would have
|
|
60
|
-
* replaced, and nothing but the attribute knows which one survived.
|
|
61
|
-
*
|
|
62
|
-
* The count that used to sit here is now `ts-for-gir/scripts/check-nick-derivation.mjs`,
|
|
63
|
-
* which owns the corpus this measures over. It also settles what looked like a
|
|
64
|
-
* contradiction: this file said 97 and ts-for-gir said 889 over the SAME 705 GIRs,
|
|
65
|
-
* and both were right — the derivations differ. 889 counts a fallback that also
|
|
66
|
-
* lowercases, which adds the 792 members whose GIR name carries uppercase and whose
|
|
67
|
-
* nick preserves it. This one does not lowercase, so 97 is its number. Quote a
|
|
68
|
-
* derived-nick count without naming its derivation and you get that pair back.
|
|
69
|
-
*/
|
|
70
|
-
export declare const nickOf: (member: string) => string;
|
|
71
|
-
export interface GirParam {
|
|
72
|
-
readonly name: string;
|
|
73
|
-
readonly type: GirType;
|
|
74
|
-
/** GIR's `direction`, which defaults to `in` when the attribute is absent. */
|
|
75
|
-
readonly direction: 'in' | 'out' | 'inout';
|
|
76
|
-
/**
|
|
77
|
-
* GIR's `caller-allocates`. It decides whether a non-`in` slot holds anything
|
|
78
|
-
* at all — see `renderParam` in `surface.mts`, which is the only reader.
|
|
79
|
-
*/
|
|
80
|
-
readonly callerAllocates: boolean;
|
|
81
|
-
}
|
|
82
|
-
export interface GirSignal {
|
|
83
|
-
readonly name: string;
|
|
84
|
-
/**
|
|
85
|
-
* WITHOUT the emitting object. GIR lists a signal's `<parameters>` free of the
|
|
86
|
-
* instance (unlike a `<method>`), and the host strips the instance too —
|
|
87
|
-
* `next(...args.slice(1))` in `signals.ts`. The two line up exactly, which is
|
|
88
|
-
* why a generated handler signature can be taken from here verbatim.
|
|
89
|
-
*/
|
|
90
|
-
readonly params: readonly GirParam[];
|
|
91
|
-
readonly deprecated: boolean;
|
|
92
|
-
/** GIR's `version` attribute — the release that introduced this signal. */
|
|
93
|
-
readonly since?: string;
|
|
94
|
-
readonly doc?: string;
|
|
95
|
-
}
|
|
96
|
-
export interface GirClass {
|
|
97
|
-
/** The GType name — `GtkBox`. Absent for a class GIR declares without one. */
|
|
98
|
-
readonly gtype: string;
|
|
99
|
-
/** GIR-local name — `Box`. */
|
|
100
|
-
readonly name: string;
|
|
101
|
-
readonly namespace: string;
|
|
102
|
-
readonly kind: 'class' | 'interface';
|
|
103
|
-
readonly abstract: boolean;
|
|
104
|
-
/** Namespace-qualified parent — `Gtk.Widget` — or null at the root. */
|
|
105
|
-
readonly parent: string | null;
|
|
106
|
-
/** Qualified interfaces (`<implements>`), or an interface's `<prerequisite>`s. */
|
|
107
|
-
readonly implements: readonly string[];
|
|
108
|
-
readonly methods: readonly string[];
|
|
109
|
-
readonly signals: readonly GirSignal[];
|
|
110
|
-
readonly properties: readonly GirProperty[];
|
|
111
|
-
readonly doc?: string;
|
|
112
|
-
}
|
|
113
|
-
export interface GirEnum {
|
|
114
|
-
readonly gtype: string;
|
|
115
|
-
/** Namespace-qualified — `Gtk.Orientation`. */
|
|
116
|
-
readonly qualified: string;
|
|
117
|
-
readonly flags: boolean;
|
|
118
|
-
/** The NICKS, which is what a string-accepting surface needs. */
|
|
119
|
-
readonly members: readonly string[];
|
|
120
|
-
}
|
|
121
|
-
export interface GirNamespace {
|
|
122
|
-
readonly name: string;
|
|
123
|
-
readonly version: string;
|
|
124
|
-
/** Classes AND interfaces, in one list: `implements` resolves against the same index. */
|
|
125
|
-
readonly classes: readonly GirClass[];
|
|
126
|
-
readonly enums: readonly GirEnum[];
|
|
127
|
-
/** Every other named type GIR declares — records, unions, callbacks, aliases. */
|
|
128
|
-
readonly otherTypes: readonly string[];
|
|
129
|
-
}
|
|
130
|
-
export declare function readNamespace(xml: string): GirNamespace;
|
|
131
|
-
/** Every class and interface across the namespaces read, keyed the way GIR references them. */
|
|
132
|
-
export declare function indexClasses(namespaces: readonly GirNamespace[]): Map<string, GirClass>;
|
|
133
|
-
/**
|
|
134
|
-
* Walk to the root, or as far as the loaded namespaces reach.
|
|
135
|
-
*
|
|
136
|
-
* A chain that leaves the loaded set is not an error: `Gtk.Widget`'s own parent
|
|
137
|
-
* is `GObject.InitiallyUnowned`, and loading GObject-2.0 to learn that would buy
|
|
138
|
-
* nothing. What matters is whether `Gtk.Widget` is ON the chain.
|
|
139
|
-
*/
|
|
140
|
-
export declare function ancestors(cls: GirClass, index: Map<string, GirClass>): GirClass[];
|
|
141
|
-
/**
|
|
142
|
-
* Every declaration a class's members can come from — self, ancestors, interfaces.
|
|
143
|
-
*
|
|
144
|
-
* The interfaces are not optional and the measurement says why: `GtkBox` declares
|
|
145
|
-
* four properties of its own and `orientation` is NOT among them. It lives on
|
|
146
|
-
* `Gtk.Orientable`, an `<implements>` of `GtkBox`, because GObject installs
|
|
147
|
-
* interface properties on the implementor at runtime while GIR keeps them once,
|
|
148
|
-
* on the interface. A class-only reader therefore emits a surface in which
|
|
149
|
-
* `<gtk-box orientation="vertical">` — the most-written GtkBox attribute there is
|
|
150
|
-
* — is a type error.
|
|
151
|
-
*
|
|
152
|
-
* Order is self, then the parent chain, then interfaces of each, so a nearer
|
|
153
|
-
* declaration of the same property name wins.
|
|
154
|
-
*/
|
|
155
|
-
export declare function declarations(cls: GirClass, index: Map<string, GirClass>): GirClass[];
|
|
156
|
-
/**
|
|
157
|
-
* Concrete descendants of a root class — the set a renderer can actually create.
|
|
158
|
-
*
|
|
159
|
-
* The root is a PARAMETER so a fixture can exercise this with a five-class GIR of
|
|
160
|
-
* its own. Hard-coding `GtkWidget` would leave the walk, the abstract filter and
|
|
161
|
-
* the namespace-crossing parent chain testable only against the real 6.2 MB file,
|
|
162
|
-
* where an off-by-one is invisible.
|
|
163
|
-
*/
|
|
164
|
-
export declare function concreteWidgets(namespaces: readonly GirNamespace[], root?: string): GirClass[];
|
|
165
|
-
/**
|
|
166
|
-
* The placement carriers: concrete classes that are NOT widgets and yet hold one.
|
|
167
|
-
*
|
|
168
|
-
* GTK4's list widgets do not take children. A `Gtk.ListView` installs no `append`,
|
|
169
|
-
* `add`, `insert`, `prepend`, `remove` or `set_child` at all — measured against its
|
|
170
|
-
* prototype — because what it takes is a factory, and the factory hands back a
|
|
171
|
-
* carrier whose `child` is where a row's subtree goes. Those carriers are plain
|
|
172
|
-
* `GObject.Object` descendants: `GObject.type_is_a(Gtk.ListItem, Gtk.Widget)` is
|
|
173
|
-
* FALSE, measured on gjs 1.88.1 / GTK 4.22.4.
|
|
174
|
-
*
|
|
175
|
-
* So "every concrete descendant of GtkWidget" is one class short of the set a
|
|
176
|
-
* renderer must be able to name, and this is the other half. It is a RULE and not a
|
|
177
|
-
* list on purpose: a hand-written list is the kind of curated data ADR 0028 § 2
|
|
178
|
-
* reserves for what the GIR cannot express, and the GIR expresses this perfectly
|
|
179
|
-
* well — a carrier is a concrete non-widget that declares both halves of a
|
|
180
|
-
* one-child slot.
|
|
181
|
-
*
|
|
182
|
-
* Measured across Gtk-4.0 + Adw-1, the rule selects exactly four:
|
|
183
|
-
* `GtkListItem`, `GtkListHeader`, `GtkColumnViewCell` and `AdwToggle`. The fourth is
|
|
184
|
-
* the argument for the rule — it was not on the hand-written list that preceded it,
|
|
185
|
-
* has the identical shape, and would have been an arbitrary gap.
|
|
186
|
-
*
|
|
187
|
-
* What this does NOT do is give them a policy. A generated row is always
|
|
188
|
-
* `uncurated`; which method adopts the child stays curated, exactly as for widgets.
|
|
189
|
-
*/
|
|
190
|
-
export declare function placementCarriers(namespaces: readonly GirNamespace[]): GirClass[];
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A five-class GIR, so the generator is testable without the 6.2 MB one.
|
|
3
|
-
*
|
|
4
|
-
* Every element here earns its place by exercising a branch the real GIR cannot
|
|
5
|
-
* exercise ON DEMAND:
|
|
6
|
-
*
|
|
7
|
-
* - `Orientable.label` is a `gint` and `Box.label` a `utf8`, so the two bases of
|
|
8
|
-
* `MiniBoxProps` disagree and the `Omit` machinery has to fire. Measured, the
|
|
9
|
-
* real Gtk+Adw hierarchy produces ZERO such conflicts, which left that code
|
|
10
|
-
* shipped and unexercised — this is what turns it into a tested path.
|
|
11
|
-
* - `baseline_fill` is a two-word enum member, so the GIR-underscore-to-nick
|
|
12
|
-
* substitution is visible.
|
|
13
|
-
* - `css-classes` is an ARRAY of a scalar, the case a descendant `<type>` lookup
|
|
14
|
-
* gets wrong by answering `string` for `string[]`.
|
|
15
|
-
* - `locked` is readable and NOT writable, so the writable filter has something to
|
|
16
|
-
* drop.
|
|
17
|
-
* - `MiniGLThing` has two adjacent capitals, so `tagOf`'s acronym rule and the
|
|
18
|
-
* Volar-resolution gap both have a case.
|
|
19
|
-
* - `Nameless` has no `glib:type-name`, and `NotAWidget` does not descend from the
|
|
20
|
-
* root — the two reasons a class is skipped.
|
|
21
|
-
*
|
|
22
|
-
* Embedded as a string rather than a file: the test bundle runs under gjs from a
|
|
23
|
-
* path that is not the source tree, and a fixture that cannot be found is a test
|
|
24
|
-
* that silently checks nothing.
|
|
25
|
-
*/
|
|
26
|
-
export declare const MINI_GIR = "<?xml version=\"1.0\"?>\n<repository version=\"1.2\"\n xmlns=\"http://www.gtk.org/introspection/core/1.0\"\n xmlns:c=\"http://www.gtk.org/introspection/c/1.0\"\n xmlns:glib=\"http://www.gtk.org/introspection/glib/1.0\">\n <namespace name=\"Mini\" version=\"1.0\">\n <enumeration name=\"Align\" glib:type-name=\"MiniAlign\">\n <member name=\"fill\" value=\"0\"/>\n <member name=\"baseline_fill\" value=\"1\"/>\n <!-- A nick GIR CARRIES and the substitution would get wrong. 97 members\n across this workspace's GIRs are shaped like this. -->\n <member name=\"two_words\" value=\"2\" glib:nick=\"renamed\"/>\n </enumeration>\n <bitfield name=\"StateFlags\" glib:type-name=\"MiniStateFlags\">\n <member name=\"active\" value=\"1\"/>\n </bitfield>\n <record name=\"Rect\" c:type=\"MiniRect\"/>\n <interface name=\"Orientable\" glib:type-name=\"MiniOrientable\">\n <doc xml:space=\"preserve\">Anything with an orientation. Second sentence, dropped.</doc>\n <property name=\"orientation\" writable=\"1\">\n <doc xml:space=\"preserve\">Which way round it goes.</doc>\n <type name=\"Align\"/>\n </property>\n <property name=\"label\" writable=\"1\">\n <type name=\"gint\"/>\n </property>\n </interface>\n <class name=\"Widget\" glib:type-name=\"MiniWidget\" abstract=\"1\" parent=\"GObject.Object\">\n <property name=\"visible\" writable=\"1\"><type name=\"gboolean\"/></property>\n <property name=\"css-classes\" writable=\"1\"><array><type name=\"utf8\"/></array></property>\n <property name=\"locked\"><type name=\"gint\"/></property>\n <property name=\"area\" writable=\"1\"><type name=\"Rect\"/></property>\n <glib:signal name=\"destroy\"/>\n <method name=\"show\"/>\n </class>\n <class name=\"Box\" glib:type-name=\"MiniBox\" parent=\"Widget\">\n <implements name=\"Orientable\"/>\n <property name=\"spacing\" writable=\"1\"><type name=\"gint\"/></property>\n <property name=\"label\" writable=\"1\"><type name=\"utf8\"/></property>\n <property name=\"old-thing\" writable=\"1\" deprecated=\"1\"><type name=\"gboolean\"/></property>\n <glib:signal name=\"row-activated\" version=\"1.2\">\n <parameters>\n <parameter name=\"row\"><type name=\"Widget\"/></parameter>\n <parameter name=\"how\"><type name=\"Align\"/></parameter>\n </parameters>\n </glib:signal>\n <method name=\"append\"/>\n <method name=\"remove\"/>\n </class>\n <class name=\"GLThing\" glib:type-name=\"MiniGLThing\" parent=\"Widget\">\n <property name=\"mode\" writable=\"1\"><type name=\"Align\"/></property>\n <property name=\"flags\" writable=\"1\"><type name=\"StateFlags\"/></property>\n </class>\n <class name=\"Nameless\" parent=\"Widget\"/>\n <class name=\"NotAWidget\" glib:type-name=\"MiniNotAWidget\" parent=\"GObject.Object\"/>\n </namespace>\n</repository>\n";
|
|
27
|
-
/** The fixture's own namespace-to-package map, which the real one has no entry for. */
|
|
28
|
-
export declare const MINI_PACKAGES: {
|
|
29
|
-
readonly Mini: "@girs/mini-1.0";
|
|
30
|
-
};
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Build the declaration graph the type surfaces are emitted from.
|
|
3
|
-
*
|
|
4
|
-
* ONE INTERFACE PER GIR DECLARATION, carrying its OWN members and extending its
|
|
5
|
-
* bases — not one flat interface per widget. The measurement decides it: the 164
|
|
6
|
-
* concrete widgets have 6768 writable property slots between them and only 561
|
|
7
|
-
* distinct property names. Flattening would emit the same `visible?: boolean`
|
|
8
|
-
* 164 times; mirroring GIR's own inheritance emits it once, on `GtkWidgetProps`,
|
|
9
|
-
* and the diff of a GTK update then shows what actually changed.
|
|
10
|
-
*
|
|
11
|
-
* THE CONFLICT MACHINERY IS NOT DEFENSIVE. TypeScript requires a multiply
|
|
12
|
-
* inherited member to be IDENTICAL in every base — `string` and `string | null`
|
|
13
|
-
* are not — and GTK's interfaces do redeclare class properties. So a base that
|
|
14
|
-
* loses a member is emitted as `Omit<Base, 'name'>`, because a local redeclaration
|
|
15
|
-
* does NOT repair incompatible bases (it turns one error into another).
|
|
16
|
-
*/
|
|
17
|
-
import { type GirClass, type GirNamespace } from './gir.mjs';
|
|
18
|
-
import { type Universe } from './tsmap.mjs';
|
|
19
|
-
export interface PropMember {
|
|
20
|
-
readonly kebab: string;
|
|
21
|
-
readonly camel: string;
|
|
22
|
-
readonly ts: string;
|
|
23
|
-
readonly doc?: string;
|
|
24
|
-
readonly deprecated: boolean;
|
|
25
|
-
readonly since?: string;
|
|
26
|
-
}
|
|
27
|
-
export interface SignalMember {
|
|
28
|
-
readonly signal: string;
|
|
29
|
-
readonly prop: string;
|
|
30
|
-
/** Already rendered — `(row: Gtk.ListBoxRow) => void`. */
|
|
31
|
-
readonly ts: string;
|
|
32
|
-
readonly doc?: string;
|
|
33
|
-
readonly deprecated: boolean;
|
|
34
|
-
readonly since?: string;
|
|
35
|
-
}
|
|
36
|
-
export interface Declaration {
|
|
37
|
-
/** GIR-qualified — `Gtk.Box`. The graph is keyed on this, the way GIR references. */
|
|
38
|
-
readonly key: string;
|
|
39
|
-
readonly gtype: string;
|
|
40
|
-
readonly kind: 'class' | 'interface';
|
|
41
|
-
/** `GtkBoxProps`. */
|
|
42
|
-
readonly iface: string;
|
|
43
|
-
readonly bases: readonly string[];
|
|
44
|
-
readonly props: readonly PropMember[];
|
|
45
|
-
readonly signals: readonly SignalMember[];
|
|
46
|
-
readonly doc?: string;
|
|
47
|
-
}
|
|
48
|
-
export interface SurfaceModel {
|
|
49
|
-
/** The 164, sorted by GType name. */
|
|
50
|
-
readonly widgets: readonly GirClass[];
|
|
51
|
-
readonly declarations: ReadonlyMap<string, Declaration>;
|
|
52
|
-
/** Widget GType -> the GTypes of every declaration its members come from, self first. */
|
|
53
|
-
readonly closure: ReadonlyMap<string, readonly string[]>;
|
|
54
|
-
/** Enum GType -> nicks, for the emitted aliases and for the runtime nick check. */
|
|
55
|
-
readonly enumNicks: ReadonlyMap<string, readonly string[]>;
|
|
56
|
-
readonly namespacesUsed: ReadonlySet<string>;
|
|
57
|
-
/** Copied from the universe, so the emitter needs no second source for it. */
|
|
58
|
-
readonly packages: Readonly<Record<string, string>>;
|
|
59
|
-
/** Base -> members it must not contribute, because a nearer declaration disagrees. */
|
|
60
|
-
readonly omissions: ReadonlyMap<string, ReadonlyMap<string, readonly string[]>>;
|
|
61
|
-
}
|
|
62
|
-
export declare function buildSurface(widgets: readonly GirClass[], namespaces: readonly GirNamespace[], universe: Universe): SurfaceModel;
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GIR type -> TypeScript type, and the two places variance decides the answer.
|
|
3
|
-
*
|
|
4
|
-
* Measured over the real Gtk-4.0 + Adw-1 GIR with the seven referenced namespaces
|
|
5
|
-
* loaded: 6768 writable property slots and 1889 signal parameters, and NOT ONE
|
|
6
|
-
* type name that fails to resolve. So there is no "unknown fallback" branch to
|
|
7
|
-
* hide behind — every type either maps or the generator fails and says which.
|
|
8
|
-
*
|
|
9
|
-
* WHERE PROPERTIES AND PARAMETERS MUST DIFFER, twice, both times because a
|
|
10
|
-
* property is an INPUT and a handler parameter is an OUTPUT:
|
|
11
|
-
*
|
|
12
|
-
* 1. An enum PROPERTY takes the nick (`orientation="vertical"`) — the host
|
|
13
|
-
* resolves it (`coerce()` in props.ts) precisely because GObject would
|
|
14
|
-
* silently keep the old value. An enum PARAMETER arrives as a NUMBER: GJS
|
|
15
|
-
* hands the marshalled value. Offering the nick union in a parameter would
|
|
16
|
-
* invite `if (mode === 'single')`, which is always false — a silent bug worse
|
|
17
|
-
* than no typing at all.
|
|
18
|
-
* 2. Nullability widens a property harmlessly and BREAKS a parameter. GIR marks
|
|
19
|
-
* many parameters `nullable="1"`, but a parameter type is contravariant: with
|
|
20
|
-
* `(row: Gtk.ListBoxRow | null) => void` declared, the ordinary
|
|
21
|
-
* `onRowActivated={(row: Gtk.ListBoxRow) => …}` stops compiling. So object
|
|
22
|
-
* PROPERTIES get `| null` (clearing one is legitimate) and parameters do not,
|
|
23
|
-
* and this comment is the record that the second was a decision rather than an
|
|
24
|
-
* oversight.
|
|
25
|
-
*
|
|
26
|
-
* FLAGS ARE `number`, in both positions, and that mirrors the runtime exactly: the
|
|
27
|
-
* host REFUSES a nick string for a flags property by name (`err.badFlags`),
|
|
28
|
-
* because resolving a nick set ("horizontal|vertical") is not something GObject
|
|
29
|
-
* exposes. A union of nicks here would type-check something the host rejects.
|
|
30
|
-
*/
|
|
31
|
-
import type { GirClass, GirEnum, GirNamespace, GirType } from './gir.mjs';
|
|
32
|
-
/** GIR namespace -> the `@girs` package that types it. Only these seven are referenced. */
|
|
33
|
-
export declare const GIRS_PACKAGES: Readonly<Record<string, string>>;
|
|
34
|
-
export interface Universe {
|
|
35
|
-
readonly enums: Map<string, GirEnum>;
|
|
36
|
-
readonly classes: Map<string, GirClass>;
|
|
37
|
-
readonly others: Set<string>;
|
|
38
|
-
/**
|
|
39
|
-
* GIR namespace -> the `@girs` package that types it.
|
|
40
|
-
*
|
|
41
|
-
* Carried here rather than read from the module constant, so a fixture can
|
|
42
|
-
* supply its own five-class namespace. Without it the type mapper is only ever
|
|
43
|
-
* exercised against the real GIR, where the branch that refuses an unknown
|
|
44
|
-
* namespace can never be reached.
|
|
45
|
-
*/
|
|
46
|
-
readonly packages: Readonly<Record<string, string>>;
|
|
47
|
-
}
|
|
48
|
-
export declare function buildUniverse(namespaces: readonly GirNamespace[], packages?: Readonly<Record<string, string>>): Universe;
|
|
49
|
-
export { nickOf } from './gir.mjs';
|
|
50
|
-
export interface TsType {
|
|
51
|
-
readonly text: string;
|
|
52
|
-
/** GIR namespaces whose `@girs` import the emitted text needs. */
|
|
53
|
-
readonly namespaces: readonly string[];
|
|
54
|
-
/** Enum GTypes whose nick alias the emitted text references. */
|
|
55
|
-
readonly enums: readonly string[];
|
|
56
|
-
}
|
|
57
|
-
export declare class TypeMapError extends Error {
|
|
58
|
-
}
|
|
59
|
-
/** A nick union, or `never` for an enum GIR declares with no members. */
|
|
60
|
-
export declare const nickUnion: (e: GirEnum) => string;
|
|
61
|
-
/** The alias name a nick union is emitted under — the GType name, so it is unique. */
|
|
62
|
-
export declare const nickAliasOf: (e: GirEnum) => string;
|
|
63
|
-
/**
|
|
64
|
-
* Map one GIR type.
|
|
65
|
-
*
|
|
66
|
-
* `where` is not decoration: see the header — an enum in a `prop` accepts nicks
|
|
67
|
-
* and in a `param` never does, and an object in a `prop` accepts null.
|
|
68
|
-
*/
|
|
69
|
-
export declare function tsTypeOf(type: GirType, u: Universe, where: 'prop' | 'param'): TsType;
|
|
70
|
-
/** `row-activated` -> `onRowActivated`; `notify` handled by the caller. */
|
|
71
|
-
export declare const eventPropOf: (signal: string) => string;
|
|
72
|
-
/** `can-focus` -> `canFocus`. The inverse of the host's `toPropertyName`. */
|
|
73
|
-
export declare const camelOf: (kebab: string) => string;
|